linux-kexecboot: add 2.6.23 for c7x0
authorKoen Kooi <koen@openembedded.org>
Sat, 13 Dec 2008 18:44:49 +0000 (19:44 +0100)
committerKoen Kooi <koen@openembedded.org>
Sat, 13 Dec 2008 18:44:49 +0000 (19:44 +0100)
56 files changed:
packages/kexecboot/linux-kexecboot-2.6.23/akita/defconfig [new file with mode: 0644]
packages/kexecboot/linux-kexecboot-2.6.23/arm-dma-coherent.patch [new file with mode: 0644]
packages/kexecboot/linux-kexecboot-2.6.23/arm_pxa_20070923.patch [new file with mode: 0644]
packages/kexecboot/linux-kexecboot-2.6.23/binutils-buildid-arm.patch [new file with mode: 0644]
packages/kexecboot/linux-kexecboot-2.6.23/bootcdx86/defconfig [new file with mode: 0644]
packages/kexecboot/linux-kexecboot-2.6.23/c7x0/defconfig [new file with mode: 0644]
packages/kexecboot/linux-kexecboot-2.6.23/collie/defconfig [new file with mode: 0644]
packages/kexecboot/linux-kexecboot-2.6.23/connectplus-prevent-oops-HACK.patch [new file with mode: 0644]
packages/kexecboot/linux-kexecboot-2.6.23/connectplus-remove-ide-HACK.patch [new file with mode: 0644]
packages/kexecboot/linux-kexecboot-2.6.23/hostap-monitor-mode.patch [new file with mode: 0644]
packages/kexecboot/linux-kexecboot-2.6.23/hrw-add-wcf11-to-hostap.patch [new file with mode: 0644]
packages/kexecboot/linux-kexecboot-2.6.23/htcuni-acx.patch [new file with mode: 0644]
packages/kexecboot/linux-kexecboot-2.6.23/htcuni.patch [new file with mode: 0644]
packages/kexecboot/linux-kexecboot-2.6.23/htcuniversal/defconfig [new file with mode: 0644]
packages/kexecboot/linux-kexecboot-2.6.23/hx2000/defconfig [new file with mode: 0644]
packages/kexecboot/linux-kexecboot-2.6.23/mtd-module.patch [new file with mode: 0644]
packages/kexecboot/linux-kexecboot-2.6.23/poodle/defconfig [new file with mode: 0644]
packages/kexecboot/linux-kexecboot-2.6.23/pxa-serial-hack.patch [new file with mode: 0644]
packages/kexecboot/linux-kexecboot-2.6.23/pxa2xx_udc_support_inverse_vbus.patch [new file with mode: 0644]
packages/kexecboot/linux-kexecboot-2.6.23/pxa_fb_overlay.patch [new file with mode: 0644]
packages/kexecboot/linux-kexecboot-2.6.23/qemuarm/defconfig [new file with mode: 0644]
packages/kexecboot/linux-kexecboot-2.6.23/qemux86/defconfig [new file with mode: 0644]
packages/kexecboot/linux-kexecboot-2.6.23/serial-add-support-for-non-standard-xtals-to-16c950-driver.patch [new file with mode: 0644]
packages/kexecboot/linux-kexecboot-2.6.23/sharpsl-pm-postresume-r1.patch [new file with mode: 0644]
packages/kexecboot/linux-kexecboot-2.6.23/sharpsl-rc-r1.patch [new file with mode: 0644]
packages/kexecboot/linux-kexecboot-2.6.23/spitz/defconfig [new file with mode: 0644]
packages/kexecboot/linux-kexecboot-2.6.23/squashfs3.0-2.6.15.patch [new file with mode: 0644]
packages/kexecboot/linux-kexecboot-2.6.23/tmio-fb-r6-fix-r0.patch [new file with mode: 0644]
packages/kexecboot/linux-kexecboot-2.6.23/tmio-nand-r8.patch [new file with mode: 0644]
packages/kexecboot/linux-kexecboot-2.6.23/tmio-ohci-r9.patch [new file with mode: 0644]
packages/kexecboot/linux-kexecboot-2.6.23/tmio-tc6393-r8.patch [new file with mode: 0644]
packages/kexecboot/linux-kexecboot-2.6.23/tosa-bluetooth-r8.patch [new file with mode: 0644]
packages/kexecboot/linux-kexecboot-2.6.23/tosa-keyboard-r19.patch [new file with mode: 0644]
packages/kexecboot/linux-kexecboot-2.6.23/tosa-lcdnoise-r1-fix-r0.patch [new file with mode: 0644]
packages/kexecboot/linux-kexecboot-2.6.23/tosa-lcdnoise-r1.patch [new file with mode: 0644]
packages/kexecboot/linux-kexecboot-2.6.23/tosa-power-r18-fix-r0.patch [new file with mode: 0644]
packages/kexecboot/linux-kexecboot-2.6.23/tosa-power-r18.patch [new file with mode: 0644]
packages/kexecboot/linux-kexecboot-2.6.23/tosa-pxaac97-r6-fix-r0.patch [new file with mode: 0644]
packages/kexecboot/linux-kexecboot-2.6.23/tosa-tmio-lcd-r10-fix-r0.patch [new file with mode: 0644]
packages/kexecboot/linux-kexecboot-2.6.23/tosa-tmio-lcd-r10.patch [new file with mode: 0644]
packages/kexecboot/linux-kexecboot-2.6.23/tosa/defconfig [new file with mode: 0644]
packages/kexecboot/linux-kexecboot-2.6.23/tosa_udc_use_gpio_vbus.patch [new file with mode: 0644]
packages/kexecboot/linux-kexecboot-2.6.23/usb-ohci-hooks-r3.patch [new file with mode: 0644]
packages/kexecboot/linux-kexecboot-2.6.23/uvesafb-0.1-rc3-2.6.22.patch [new file with mode: 0644]
packages/kexecboot/linux-kexecboot-2.6.23/versatile-armv6.patch [new file with mode: 0644]
packages/kexecboot/linux-kexecboot-2.6.23/wm8750-treble.patch [new file with mode: 0644]
packages/kexecboot/linux-kexecboot-2.6.23/wm9712-reset-loop-r2.patch [new file with mode: 0644]
packages/kexecboot/linux-kexecboot-2.6.23/wm9712-suspend-cold-res-r2.patch [new file with mode: 0644]
packages/kexecboot/linux-kexecboot-2.6.23/wm97xx-lg13-r0-fix-r0.patch [new file with mode: 0644]
packages/kexecboot/linux-kexecboot-2.6.23/wm97xx-lg13-r0.patch [new file with mode: 0644]
packages/kexecboot/linux-kexecboot-2.6.23/zylonite-boot.patch [new file with mode: 0644]
packages/kexecboot/linux-kexecboot-2.6.23/zylonite/defconfig [new file with mode: 0644]
packages/kexecboot/linux-kexecboot-2.6.23/zylonite_keypad-r0.patch [new file with mode: 0644]
packages/kexecboot/linux-kexecboot-2.6.23/zylonite_mtd-r0.patch [new file with mode: 0644]
packages/kexecboot/linux-kexecboot-2.6.23/zylonite_touch-r0.patch [new file with mode: 0644]
packages/kexecboot/linux-kexecboot_2.6.23.bb [new file with mode: 0644]

diff --git a/packages/kexecboot/linux-kexecboot-2.6.23/akita/defconfig b/packages/kexecboot/linux-kexecboot-2.6.23/akita/defconfig
new file mode 100644 (file)
index 0000000..ddc7ba0
--- /dev/null
@@ -0,0 +1,1737 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.23
+# Mon May 19 22:50:30 2008
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_MMU=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ZONE_DMA=y
+CONFIG_ARCH_MTD_XIP=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=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_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+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_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=m
+CONFIG_IOSCHED_CFQ=m
+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_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_MXC 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_DAVINCI is not set
+# CONFIG_ARCH_OMAP 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=y
+# CONFIG_MACH_TRIZEPS4 is not set
+# CONFIG_MACH_EM_X270 is not set
+# CONFIG_MACH_HX2750 is not set
+# CONFIG_MACH_HTCUNIVERSAL is not set
+# CONFIG_PXA_SHARPSL_25x is not set
+CONFIG_PXA_SHARPSL_27x=y
+CONFIG_MACH_AKITA=y
+CONFIG_MACH_SPITZ=y
+CONFIG_MACH_BORZOI=y
+CONFIG_PXA27x=y
+CONFIG_PXA_SHARP_Cxx00=y
+CONFIG_PXA_SSP=y
+# CONFIG_PXA_KEYS is not set
+
+#
+# Boot options
+#
+
+#
+# Power management
+#
+
+#
+# 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
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_OUTER_CACHE is not set
+CONFIG_IWMMXT=y
+CONFIG_XSCALE_PMU=y
+CONFIG_SHARP_PARAM=y
+CONFIG_SHARPSL_PM=y
+CONFIG_SHARP_SCOOP=y
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+
+#
+# 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_TICK_ONESHOT is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_PREEMPT=y
+CONFIG_HZ=100
+CONFIG_AEABI=y
+CONFIG_OABI_COMPAT=y
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=ttyS0,115200n8 console=tty1 noinitrd root=/dev/mtdblock2 rootfstype=jffs2  fbcon=rotate:1 dyntick=enable debug"
+# CONFIG_XIP_KERNEL is not set
+CONFIG_KEXEC=y
+CONFIG_ATAGS_PROC=y
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_AOUT=m
+CONFIG_BINFMT_MISC=m
+
+#
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND_UP_POSSIBLE=y
+CONFIG_SUSPEND=y
+CONFIG_APM_EMULATION=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=m
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=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=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IP_VS is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+# CONFIG_IPV6_MIP6 is not set
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=m
+CONFIG_IPV6_TUNNEL=m
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK is not set
+# CONFIG_NF_CONNTRACK_ENABLED is not set
+# CONFIG_NF_CONNTRACK is not set
+CONFIG_NETFILTER_XTABLES=m
+# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
+# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
+# CONFIG_NETFILTER_XT_TARGET_MARK is not set
+# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
+# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
+# CONFIG_NETFILTER_XT_TARGET_TRACE is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
+# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
+# CONFIG_NETFILTER_XT_MATCH_ESP is not set
+# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
+# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_MAC is not set
+# CONFIG_NETFILTER_XT_MATCH_MARK is not set
+# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
+# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
+# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
+# CONFIG_NETFILTER_XT_MATCH_REALM is not set
+# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
+# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
+# CONFIG_NETFILTER_XT_MATCH_STRING is not set
+# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_U32 is not set
+# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=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_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=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 is not set
+# CONFIG_IP6_NF_IPTABLES is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# 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 is not set
+
+#
+# IrDA options
+#
+# CONFIG_IRDA_CACHE_LAST_LSAP is not set
+# CONFIG_IRDA_FAST_RR is not set
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+# CONFIG_IRTTY_SIR is not set
+
+#
+# Dongle support
+#
+# CONFIG_KINGSUN_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=m
+# CONFIG_MCS_FIR is not set
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIUSB=m
+# CONFIG_BT_HCIUSB_SCO is not set
+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_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+CONFIG_WIRELESS_EXT=y
+# CONFIG_MAC80211 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_RFKILL is not set
+# CONFIG_NET_9P 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_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI 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=y
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_SHARP_SL=y
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_VERIFY_WRITE=y
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_H1900 is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+CONFIG_MTD_NAND_SHARPSL=y
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+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 is not set
+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
+CONFIG_IDE_PROC_FS=y
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_IDEPCI_PCIBUS_ORDER is not set
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=m
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=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 is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set
+# CONFIG_ATA is not set
+CONFIG_MD=y
+# CONFIG_BLK_DEV_MD is not set
+CONFIG_BLK_DEV_DM=m
+# CONFIG_DM_DEBUG is not set
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_EMC=m
+# CONFIG_DM_MULTIPATH_RDAC is not set
+# CONFIG_DM_DELAY is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+# CONFIG_AX88796 is not set
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+# CONFIG_SMC911X is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+CONFIG_WLAN_PRE80211=y
+# CONFIG_STRIP is not set
+# CONFIG_PCMCIA_WAVELAN is not set
+# CONFIG_PCMCIA_NETWAVE is not set
+CONFIG_WLAN_80211=y
+# CONFIG_PCMCIA_RAYCS is not set
+# CONFIG_LIBERTAS is not set
+CONFIG_HERMES=m
+# CONFIG_ATMEL is not set
+CONFIG_PCMCIA_HERMES=m
+CONFIG_PCMCIA_SPECTRUM=m
+CONFIG_AIRO_CS=m
+# CONFIG_PCMCIA_WL3501 is not set
+# CONFIG_USB_ZD1201 is not set
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+# CONFIG_HOSTAP_FIRMWARE_NVRAM is not set
+CONFIG_HOSTAP_CS=m
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET_MII=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_CDCETHER=m
+# CONFIG_USB_NET_DM9601 is not set
+# CONFIG_USB_NET_GL620A is not set
+CONFIG_USB_NET_NET1080=m
+# CONFIG_USB_NET_PLUSB is not set
+# CONFIG_USB_NET_MCS7830 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_NET_PCMCIA=y
+# CONFIG_PCMCIA_3C589 is not set
+# CONFIG_PCMCIA_3C574 is not set
+# CONFIG_PCMCIA_FMVJ18X is not set
+CONFIG_PCMCIA_PCNET=m
+# CONFIG_PCMCIA_NMCLAN is not set
+# CONFIG_PCMCIA_SMC91C92 is not set
+# CONFIG_PCMCIA_XIRC2PS is not set
+# CONFIG_PCMCIA_AXNET is not set
+# 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 is not set
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+# CONFIG_PPP_MPPE is not set
+# CONFIG_PPPOE is not set
+# CONFIG_PPPOL2TP is not set
+# CONFIG_SLIP is not set
+CONFIG_SLHC=m
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=m
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=640
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=480
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+CONFIG_INPUT_POWER=y
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_CORGI is not set
+CONFIG_KEYBOARD_SPITZ=y
+# CONFIG_KEYBOARD_PXA27x is not set
+# CONFIG_KEYBOARD_GPIO is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_CORGI=y
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_UCB1400 is not set
+# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_ATI_REMOTE is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
+CONFIG_INPUT_UINPUT=m
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250_CS=m
+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_PXA=y
+CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_HW_RANDOM=m
+# CONFIG_NVRAM is not set
+# CONFIG_R3964 is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_CARDMAN_4000 is not set
+# CONFIG_CARDMAN_4040 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=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_GPIO is not set
+CONFIG_I2C_PXA=y
+# CONFIG_I2C_PXA_SLAVE is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_DS1682 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_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_EEPROM_93CX6 is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_ASIC3 is not set
+# CONFIG_HTC_ASIC3_DS1WM is not set
+
+#
+# Multi-Function Devices
+#
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+CONFIG_LEDS_SPITZ=y
+# CONFIG_LEDS_TOSA is not set
+# CONFIG_LEDS_GPIO is not set
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_IDE_DISK=y
+# CONFIG_LEDS_TRIGGER_HEARTBEAT is not set
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_VIDEO_V4L2=y
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_TUNER_3036 is not set
+# CONFIG_TUNER_TEA5761 is not set
+CONFIG_V4L_USB_DRIVERS=y
+# CONFIG_VIDEO_PVRUSB2 is not set
+# CONFIG_VIDEO_EM28XX is not set
+# CONFIG_VIDEO_USBVISION is not set
+# CONFIG_USB_VICAM is not set
+# CONFIG_USB_IBMCAM is not set
+# CONFIG_USB_KONICAWC is not set
+# CONFIG_USB_QUICKCAM_MESSENGER is not set
+# CONFIG_USB_ET61X251 is not set
+# CONFIG_VIDEO_OVCAMCHIP is not set
+# CONFIG_USB_W9968CF is not set
+# CONFIG_USB_OV511 is not set
+# CONFIG_USB_SE401 is not set
+# CONFIG_USB_SN9C102 is not set
+# CONFIG_USB_STV680 is not set
+# CONFIG_USB_ZC0301 is not set
+# CONFIG_USB_PWC is not set
+# CONFIG_USB_ZR364XX is not set
+CONFIG_RADIO_ADAPTERS=y
+# CONFIG_USB_DSBR is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
+CONFIG_USB_DABUSB=m
+
+#
+# Graphics support
+#
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_CORGI=y
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=m
+CONFIG_FB=y
+CONFIG_FIRMWARE_EDID=y
+# CONFIG_FB_DDC is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_SYS_FOPS is not set
+CONFIG_FB_DEFERRED_IO=y
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_PXA=y
+CONFIG_FB_PXA_LCD_QVGA=y
+# CONFIG_FB_PXA_LCD_VGA is not set
+CONFIG_FB_PXA_OVERLAY=y
+# CONFIG_FB_PXA_PARAMETERS is not set
+# CONFIG_FB_MBX is not set
+# CONFIG_FB_W100 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_DETECT_PRIMARY is not set
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+CONFIG_FONTS=y
+# CONFIG_FONT_8x8 is not set
+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
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+CONFIG_LOGO_OHAND_CLUT224=y
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_HWDEP=m
+CONFIG_SND_RAWMIDI=m
+CONFIG_SND_SEQUENCER=m
+# CONFIG_SND_SEQ_DUMMY is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_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=y
+# CONFIG_SND_DEBUG_DETECT is not set
+# CONFIG_SND_PCM_XRUN_DEBUG is not set
+
+#
+# Generic devices
+#
+CONFIG_SND_AC97_CODEC=m
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_VIRMIDI is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# ALSA ARM devices
+#
+CONFIG_SND_PXA2XX_PCM=m
+CONFIG_SND_PXA2XX_AC97=m
+
+#
+# USB devices
+#
+CONFIG_SND_USB_AUDIO=m
+# CONFIG_SND_USB_CAIAQ is not set
+
+#
+# PCMCIA devices
+#
+# CONFIG_SND_VXPOCKET is not set
+# CONFIG_SND_PDAUDIOCF is not set
+
+#
+# System on Chip audio support
+#
+CONFIG_SND_SOC=m
+CONFIG_SND_PXA2XX_SOC=m
+CONFIG_SND_PXA2XX_SOC_I2S=m
+CONFIG_SND_PXA2XX_SOC_SPITZ=m
+
+#
+# SoC Audio support for SuperH
+#
+CONFIG_SND_SOC_WM8750=m
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+CONFIG_AC97_BUS=m
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=m
+# CONFIG_HID_DEBUG is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=m
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+CONFIG_USB_KBD=m
+CONFIG_USB_MOUSE=m
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_PERSIST is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_SL811_HCD=m
+CONFIG_USB_SL811_CS=m
+# CONFIG_USB_R8A66597_HCD is not set
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_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_KARMA is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+CONFIG_USB_MDC800=m
+CONFIG_USB_MICROTEK=m
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+# CONFIG_USB_SERIAL_AIRCABLE is not set
+# CONFIG_USB_SERIAL_AIRPRIME is not set
+# CONFIG_USB_SERIAL_ARK3116 is not set
+CONFIG_USB_SERIAL_BELKIN=m
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+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=m
+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_MOS7720 is not set
+# CONFIG_USB_SERIAL_MOS7840 is not set
+# CONFIG_USB_SERIAL_NAVMAN is not set
+CONFIG_USB_SERIAL_PL2303=m
+# CONFIG_USB_SERIAL_OTI6858 is not set
+# 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=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+# CONFIG_USB_SERIAL_OPTION is not set
+CONFIG_USB_SERIAL_OMNINET=m
+# CONFIG_USB_SERIAL_DEBUG is not set
+CONFIG_USB_EZUSB=y
+
+#
+# USB Miscellaneous drivers
+#
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+# CONFIG_USB_ADUTUX is not set
+CONFIG_USB_AUERSWALD=m
+CONFIG_USB_RIO500=m
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+# CONFIG_USB_BERRY_CHARGE is not set
+CONFIG_USB_LED=m
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+CONFIG_USB_CYTHERM=m
+# CONFIG_USB_PHIDGET is not set
+CONFIG_USB_IDMOUSE=m
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+CONFIG_USB_GADGET=m
+# CONFIG_USB_GADGET_DEBUG is not set
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_PXA2XX is not set
+# CONFIG_USB_GADGET_M66592 is not set
+CONFIG_USB_GADGET_PXA27X=y
+CONFIG_USB_PXA27X=m
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+# CONFIG_USB_GADGET_DUALSPEED is not set
+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
+# CONFIG_USB_MIDI_GADGET is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_UNSAFE_RESUME=y
+
+#
+# MMC/SD Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+
+#
+# MMC/SD Host Controller Drivers
+#
+CONFIG_MMC_PXA=y
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_SA1100=y
+
+#
+# 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=m
+# CONFIG_EXT3_FS_XATTR is not set
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=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 is not set
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+CONFIG_JFFS2_SUMMARY=y
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_SYSFS is not set
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_LZO=y
+CONFIG_JFFS2_RTIME=y
+CONFIG_JFFS2_RUBIN=y
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
+CONFIG_CRAMFS=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 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=y
+# CONFIG_NFS_DIRECTIO is not set
+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_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+# CONFIG_SUNRPC_BIND34 is not set
+CONFIG_RPCSEC_GSS_KRB5=m
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+CONFIG_SMB_NLS_DEFAULT=y
+CONFIG_SMB_NLS_REMOTE="cp437"
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_WEAK_PW_HASH is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="cp437"
+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=m
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=y
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
+# Profiling support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+# CONFIG_DETECT_SOFTLOCKUP is not set
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+CONFIG_TIMER_STATS=y
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_PREEMPT is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_FORCED_INLINING is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_DEBUG_USER is not set
+CONFIG_DEBUG_ERRORS=y
+# CONFIG_DEBUG_LL is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+CONFIG_CRYPTO_DES=m
+# CONFIG_CRYPTO_FCRYPT is not set
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+# CONFIG_CRYPTO_LZO is not set
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_CAMELLIA is not set
+CONFIG_CRYPTO_TEST=m
+CONFIG_CRYPTO_HW=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/packages/kexecboot/linux-kexecboot-2.6.23/arm-dma-coherent.patch b/packages/kexecboot/linux-kexecboot-2.6.23/arm-dma-coherent.patch
new file mode 100644 (file)
index 0000000..2454bec
--- /dev/null
@@ -0,0 +1,361 @@
+Patch largely based on the work of Ian Molton (spyro@f2s.com).
+
+Signed-off-by: Dmitry Baryshkov <dbaryshkov@gmail.com>
+Index: linux-2.6.23/arch/arm/mm/consistent.c
+===================================================================
+--- linux-2.6.23.orig/arch/arm/mm/consistent.c 2007-10-10 00:31:38.000000000 +0400
++++ linux-2.6.23/arch/arm/mm/consistent.c      2007-11-13 01:20:58.281143408 +0300
+@@ -3,6 +3,8 @@
+  *
+  *  Copyright (C) 2000-2004 Russell King
+  *
++ *  Device local coherent memory support added by Ian Molton (spyro@f2s.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.
+@@ -20,6 +22,7 @@
+ #include <asm/memory.h>
+ #include <asm/cacheflush.h>
++#include <asm/io.h>
+ #include <asm/tlbflush.h>
+ #include <asm/sizes.h>
+@@ -35,6 +38,13 @@
+ #define CONSISTENT_PTE_INDEX(x) (((unsigned long)(x) - CONSISTENT_BASE) >> PGDIR_SHIFT)
+ #define NUM_CONSISTENT_PTES (CONSISTENT_DMA_SIZE >> PGDIR_SHIFT)
++struct dma_coherent_mem {
++      void            *virt_base;
++      u32             device_base;
++      int             size;
++      int             flags;
++      unsigned long   *bitmap;
++};
+ /*
+  * These are the page tables (2MB each) covering uncached, DMA consistent allocations
+@@ -153,6 +163,13 @@
+       unsigned long order;
+       u64 mask = ISA_DMA_THRESHOLD, limit;
++      /* Following is a work-around (a.k.a. hack) to prevent pages
++       * with __GFP_COMP being passed to split_page() which cannot
++       * handle them.  The real problem is that this flag probably
++       * should be 0 on ARM as it is not supported on this
++       * platform--see CONFIG_HUGETLB_PAGE. */
++      gfp &= ~(__GFP_COMP);
++
+       if (!consistent_pte[0]) {
+               printk(KERN_ERR "%s: not initialised\n", __func__);
+               dump_stack();
+@@ -160,6 +177,26 @@
+       }
+       if (dev) {
++
++              if (dev->dma_mem) {
++                      unsigned long flags;
++                      int page;
++                      void *ret;
++
++                      spin_lock_irqsave(&consistent_lock, flags);
++                      page = bitmap_find_free_region(dev->dma_mem->bitmap,
++                                                     dev->dma_mem->size,
++                                                     get_order(size));
++                      spin_unlock_irqrestore(&consistent_lock, flags);
++
++                      if (page >= 0) {
++                              *handle = dev->dma_mem->device_base + (page << PAGE_SHIFT);
++                              ret = dev->dma_mem->virt_base + (page << PAGE_SHIFT);
++                              memset(ret, 0, size);
++                              return ret;
++                      }
++              }
++
+               mask = dev->coherent_dma_mask;
+               /*
+@@ -177,6 +214,9 @@
+                                mask, (unsigned long long)ISA_DMA_THRESHOLD);
+                       goto no_page;
+               }
++
++              if (dev->dma_mem && dev->dma_mem->flags & DMA_MEMORY_EXCLUSIVE)
++                      return NULL;
+       }
+       /*
+@@ -360,6 +400,8 @@
+       pte_t *ptep;
+       int idx;
+       u32 off;
++      struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
++      unsigned long order;
+       WARN_ON(irqs_disabled());
+@@ -369,6 +411,15 @@
+       }
+       size = PAGE_ALIGN(size);
++      order = get_order(size);
++
++      /* What if mem is valid and the range is not? */
++      if (mem && cpu_addr >= mem->virt_base && cpu_addr < (mem->virt_base + (mem->size << PAGE_SHIFT))) {
++              int page = (cpu_addr - mem->virt_base) >> PAGE_SHIFT;
++
++              bitmap_release_region(mem->bitmap, page, order);
++              return;
++      }
+       spin_lock_irqsave(&consistent_lock, flags);
+       c = vm_region_find(&consistent_head, (unsigned long)cpu_addr);
+@@ -438,6 +489,81 @@
+ }
+ EXPORT_SYMBOL(dma_free_coherent);
++int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
++                              dma_addr_t device_addr, size_t size, int flags)
++{
++      void *mem_base;
++      int pages = size >> PAGE_SHIFT;
++      int bitmap_size = (pages + 31)/32;
++
++      if ((flags & (DMA_MEMORY_MAP | DMA_MEMORY_IO)) == 0)
++              goto out;
++      if (!size)
++              goto out;
++      if (dev->dma_mem)
++              goto out;
++
++      /* FIXME: this routine just ignores DMA_MEMORY_INCLUDES_CHILDREN */
++      mem_base = ioremap_nocache(bus_addr, size);
++      if (!mem_base)
++              goto out;
++
++      dev->dma_mem = kmalloc(GFP_KERNEL, sizeof(struct dma_coherent_mem));
++      if (!dev->dma_mem)
++              goto out;
++      memset(dev->dma_mem, 0, sizeof(struct dma_coherent_mem));
++      dev->dma_mem->bitmap = kmalloc(GFP_KERNEL, bitmap_size);
++      if (!dev->dma_mem->bitmap)
++              goto free1_out;
++      memset(dev->dma_mem->bitmap, 0, bitmap_size);
++
++      dev->dma_mem->virt_base = mem_base;
++      dev->dma_mem->device_base = device_addr;
++      dev->dma_mem->size = pages;
++      dev->dma_mem->flags = flags;
++
++      if (flags & DMA_MEMORY_MAP)
++              return DMA_MEMORY_MAP;
++
++      return DMA_MEMORY_IO;
++
++ free1_out:
++      kfree(dev->dma_mem->bitmap);
++ out:
++      return 0;
++}
++EXPORT_SYMBOL(dma_declare_coherent_memory);
++
++void dma_release_declared_memory(struct device *dev)
++{
++      struct dma_coherent_mem *mem = dev->dma_mem;
++
++      if (!mem)
++              return;
++      dev->dma_mem = NULL;
++      kfree(mem->bitmap);
++      kfree(mem);
++}
++EXPORT_SYMBOL(dma_release_declared_memory);
++
++void *dma_mark_declared_memory_occupied(struct device *dev,
++                                      dma_addr_t device_addr, size_t size)
++{
++      struct dma_coherent_mem *mem = dev->dma_mem;
++      int pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
++      int pos, err;
++
++      if (!mem)
++              return ERR_PTR(-EINVAL);
++
++      pos = (device_addr - mem->device_base) >> PAGE_SHIFT;
++      err = bitmap_allocate_region(mem->bitmap, pos, get_order(pages));
++      if (err != 0)
++              return ERR_PTR(err);
++      return mem->virt_base + (pos << PAGE_SHIFT);
++}
++EXPORT_SYMBOL(dma_mark_declared_memory_occupied);
++
+ /*
+  * Initialise the consistent memory allocation.
+  */
+Index: linux-2.6.23/arch/arm/common/dmabounce.c
+===================================================================
+--- linux-2.6.23.orig/arch/arm/common/dmabounce.c      2007-10-10 00:31:38.000000000 +0400
++++ linux-2.6.23/arch/arm/common/dmabounce.c   2007-11-13 01:23:17.452501736 +0300
+@@ -16,6 +16,7 @@
+  *
+  *  Copyright (C) 2002 Hewlett Packard Company.
+  *  Copyright (C) 2004 MontaVista Software, Inc.
++ *  Copyright (C) 2007 Dmitry Baryshkov <dbaryshkov@gmail.com>
+  *
+  *  This program is free software; you can redistribute it and/or
+  *  modify it under the terms of the GNU General Public License
+@@ -29,6 +30,7 @@
+ #include <linux/dma-mapping.h>
+ #include <linux/dmapool.h>
+ #include <linux/list.h>
++#include <linux/rwsem.h>
+ #include <asm/cacheflush.h>
+@@ -79,6 +81,75 @@
+       rwlock_t lock;
+ };
++struct dmabounce_check_entry {
++      struct list_head        list;
++      dmabounce_check         checker;
++      void                    *data;
++};
++
++static struct list_head checkers = LIST_HEAD_INIT(checkers);
++static rwlock_t checkers_lock = RW_LOCK_UNLOCKED;
++
++int
++dmabounce_register_checker(dmabounce_check function, void *data)
++{
++      unsigned long flags;
++      struct dmabounce_check_entry *entry =
++              kzalloc(sizeof(struct dmabounce_check_entry), GFP_ATOMIC);
++
++      if (!entry)
++              return ENOMEM;
++
++      INIT_LIST_HEAD(&entry->list);
++      entry->checker = function;
++      entry->data = data;
++
++      write_lock_irqsave(checkers_lock, flags);
++      list_add(&entry->list, &checkers);
++      write_unlock_irqrestore(checkers_lock, flags);
++
++      return 0;
++}
++
++void
++dmabounce_remove_checker(dmabounce_check function, void *data)
++{
++      unsigned long flags;
++      struct list_head *pos;
++
++      write_lock_irqsave(checkers_lock, flags);
++      __list_for_each(pos, &checkers) {
++              struct dmabounce_check_entry *entry = container_of(pos,
++                              struct dmabounce_check_entry, list);
++              if (entry->checker == function && entry->data == data) {
++                      list_del(pos);
++                      write_unlock_irqrestore(checkers_lock, flags);
++                      kfree(entry);
++                      return;
++              }
++      }
++
++      printk(KERN_WARNING "dmabounce checker not found: %p\n", function);
++}
++
++int dma_needs_bounce(struct device *dev, dma_addr_t dma, size_t size)
++{
++      unsigned long flags;
++      struct list_head *pos;
++
++      read_lock_irqsave(checkers_lock, flags);
++      __list_for_each(pos, &checkers) {
++              struct dmabounce_check_entry *entry = container_of(pos,
++                              struct dmabounce_check_entry, list);
++              if (entry->checker(dev, dma, size, entry->data)) {
++                      read_unlock_irqrestore(checkers_lock, flags);
++                      return 1;
++              }
++      }
++
++      read_unlock_irqrestore(checkers_lock, flags);
++      return 0;
++}
+ #ifdef STATS
+ static ssize_t dmabounce_show(struct device *dev, struct device_attribute *attr,
+                             char *buf)
+@@ -642,7 +713,6 @@
+               dev->bus_id, dev->bus->name);
+ }
+-
+ EXPORT_SYMBOL(dma_map_single);
+ EXPORT_SYMBOL(dma_unmap_single);
+ EXPORT_SYMBOL(dma_map_sg);
+@@ -652,6 +722,9 @@
+ EXPORT_SYMBOL(dma_sync_sg);
+ EXPORT_SYMBOL(dmabounce_register_dev);
+ EXPORT_SYMBOL(dmabounce_unregister_dev);
++EXPORT_SYMBOL(dmabounce_register_checker);
++EXPORT_SYMBOL(dmabounce_remove_checker);
++
+ MODULE_AUTHOR("Christopher Hoover <ch@hpl.hp.com>, Deepak Saxena <dsaxena@plexity.net>");
+ MODULE_DESCRIPTION("Special dma_{map/unmap/dma_sync}_* routines for systems with limited DMA windows");
+Index: linux-2.6.23/include/asm-arm/dma-mapping.h
+===================================================================
+--- linux-2.6.23.orig/include/asm-arm/dma-mapping.h    2007-10-10 00:31:38.000000000 +0400
++++ linux-2.6.23/include/asm-arm/dma-mapping.h 2007-11-13 01:24:05.588500474 +0300
+@@ -7,6 +7,18 @@
+ #include <asm/scatterlist.h>
++#define ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY
++extern int
++dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
++                          dma_addr_t device_addr, size_t size, int flags);
++
++extern void
++dma_release_declared_memory(struct device *dev);
++
++extern void *
++dma_mark_declared_memory_occupied(struct device *dev,
++                                dma_addr_t device_addr, size_t size);
++
+ /*
+  * DMA-consistent mapping functions.  These allocate/free a region of
+  * uncached, unwrite-buffered mapped memory space for use with DMA
+@@ -433,23 +445,10 @@
+  */
+ extern void dmabounce_unregister_dev(struct device *);
+-/**
+- * dma_needs_bounce
+- *
+- * @dev: valid struct device pointer
+- * @dma_handle: dma_handle of unbounced buffer
+- * @size: size of region being mapped
+- *
+- * Platforms that utilize the dmabounce mechanism must implement
+- * this function.
+- *
+- * The dmabounce routines call this function whenever a dma-mapping
+- * is requested to determine whether a given buffer needs to be bounced
+- * or not. The function must return 0 if the buffer is OK for
+- * DMA access and 1 if the buffer needs to be bounced.
+- *
+- */
+-extern int dma_needs_bounce(struct device*, dma_addr_t, size_t);
++typedef int (*dmabounce_check)(struct device *dev, dma_addr_t dma, size_t size, void *data);
++extern int dmabounce_register_checker(dmabounce_check, void *data);
++extern void dmabounce_remove_checker(dmabounce_check, void *data);
++
+ #endif /* CONFIG_DMABOUNCE */
+ #endif /* __KERNEL__ */
diff --git a/packages/kexecboot/linux-kexecboot-2.6.23/arm_pxa_20070923.patch b/packages/kexecboot/linux-kexecboot-2.6.23/arm_pxa_20070923.patch
new file mode 100644 (file)
index 0000000..ad4ce99
--- /dev/null
@@ -0,0 +1,5877 @@
+# Base git commit: da8f153e51290e7438ba7da66234a864e5d3e1c1
+#      (Revert "x86_64: Quicklist support for x86_64")
+#
+# Author:    eric miao (Wed Sep 12 03:13:17 BST 2007)
+# Committer: Russell King (Sun Sep 23 14:18:19 BST 2007)
+#   
+#   [ARM] pxa: PXA3xx base support
+#   
+#   Signed-off-by: eric miao
+#   Signed-off-by: Russell King
+#
+# arch/arm/Kconfig                         |    6 
+# arch/arm/boot/compressed/head-xscale.S   |    4 
+# arch/arm/mach-pxa/Kconfig                |   30 +
+# arch/arm/mach-pxa/Makefile               |    9 
+# arch/arm/mach-pxa/clock.c                |   79 ++--
+# arch/arm/mach-pxa/clock.h                |   43 ++
+# arch/arm/mach-pxa/devices.h              |    3 
+# arch/arm/mach-pxa/generic.c              |  146 ++++---
+# arch/arm/mach-pxa/generic.h              |   26 +
+# arch/arm/mach-pxa/irq.c                  |   80 ----
+# arch/arm/mach-pxa/mfp.c                  |  235 ++++++++++++
+# arch/arm/mach-pxa/pxa25x.c               |   90 ++++
+# arch/arm/mach-pxa/pxa27x.c               |  127 ++++++
+# arch/arm/mach-pxa/pxa300.c               |   93 +++++
+# arch/arm/mach-pxa/pxa320.c               |   88 ++++
+# arch/arm/mach-pxa/pxa3xx.c               |  216 +++++++++++
+# arch/arm/mach-pxa/time.c                 |   53 ++
+# arch/arm/mach-pxa/zylonite.c             |  184 +++++++++
+# arch/arm/mach-pxa/zylonite_pxa300.c      |  188 ++++++++++
+# arch/arm/mach-pxa/zylonite_pxa320.c      |  173 +++++++++
+# arch/arm/mm/Kconfig                      |    4 
+# drivers/i2c/busses/i2c-pxa.c             |   45 +-
+# drivers/input/keyboard/pxa27x_keyboard.c |   25 +
+# drivers/mmc/host/pxamci.c                |   43 +-
+# drivers/mmc/host/pxamci.h                |   14 
+# drivers/mtd/maps/lubbock-flash.c         |    9 
+# drivers/mtd/maps/mainstone-flash.c       |    5 
+# drivers/net/irda/pxaficp_ir.c            |   51 ++
+# drivers/net/smc91x.c                     |   62 ---
+# drivers/net/smc91x.h                     |   71 +++
+# drivers/serial/pxa.c                     |  163 ++++----
+# drivers/serial/serial_core.c             |   18 
+# drivers/usb/gadget/pxa2xx_udc.c          |   68 ++-
+# drivers/usb/gadget/pxa2xx_udc.h          |    1 
+# drivers/video/pxafb.c                    |   36 +
+# drivers/video/pxafb.h                    |    1 
+# include/asm-arm/arch-pxa/hardware.h      |   72 +++
+# include/asm-arm/arch-pxa/irqs.h          |    6 
+# include/asm-arm/arch-pxa/mfp-pxa300.h    |  574 ++++++++++++++++++++++++++++++
+# include/asm-arm/arch-pxa/mfp-pxa320.h    |  446 ++++++++++++++++++++++++
+# include/asm-arm/arch-pxa/mfp.h           |  576 +++++++++++++++++++++++++++++++
+# include/asm-arm/arch-pxa/pxa-regs.h      |    2 
+# include/asm-arm/arch-pxa/pxa3xx-regs.h   |   75 ++++
+# include/asm-arm/arch-pxa/timex.h         |    2 
+# include/asm-arm/arch-pxa/zylonite.h      |   35 +
+# 45 files changed, 3825 insertions(+), 452 deletions(-)
+#    create mode 100644 arch/arm/mach-pxa/mfp.c
+#    create mode 100644 arch/arm/mach-pxa/pxa300.c
+#    create mode 100644 arch/arm/mach-pxa/pxa320.c
+#    create mode 100644 arch/arm/mach-pxa/pxa3xx.c
+#    create mode 100644 arch/arm/mach-pxa/zylonite.c
+#    create mode 100644 arch/arm/mach-pxa/zylonite_pxa300.c
+#    create mode 100644 arch/arm/mach-pxa/zylonite_pxa320.c
+#    create mode 100644 include/asm-arm/arch-pxa/mfp-pxa300.h
+#    create mode 100644 include/asm-arm/arch-pxa/mfp-pxa320.h
+#    create mode 100644 include/asm-arm/arch-pxa/mfp.h
+#    create mode 100644 include/asm-arm/arch-pxa/pxa3xx-regs.h
+#    create mode 100644 include/asm-arm/arch-pxa/zylonite.h
+#
+# Author:    Russell King (Sat Sep  1 21:27:18 BST 2007)
+# Committer: Russell King (Sun Sep 23 14:18:17 BST 2007)
+#   
+#   [NET] smc91x: fix PXA DMA support code
+#   
+#   The PXA DMA support code for smc91x doesn't pass a struct device to
+#   the dma_*map_single() functions, which leads to an oops in the dma
+#   bounce code.  We have a struct device which was used to probe the
+#   SMC chip.  Use it.
+#   
+#   (This patch is slightly larger because it requires struct smc_local
+#   to move into the header file.)
+#   
+#   Signed-off-by: Russell King
+#
+#
+# Author:    Russell King (Sat Sep  1 21:25:09 BST 2007)
+# Committer: Russell King (Sun Sep 23 14:18:12 BST 2007)
+#   
+#   [SERIAL] Fix console initialisation ordering
+#   
+#   Ensure pm callback is called upon initialisation to place port in
+#   correct power saving state.  Ensure console is initialised prior
+#   to deciding whether to power down the port.
+#   
+#   Signed-off-by: Russell King
+#
+#
+# Author:    Russell King (Wed Sep 19 09:21:51 BST 2007)
+# Committer: Russell King (Sun Sep 23 14:18:07 BST 2007)
+#   
+#   [ARM] pxa: tidy up arch/arm/mach-pxa/Makefile
+#   
+#   Signed-off-by: Russell King
+#
+#
+# Author:    Russell King (Sat Sep  1 21:28:55 BST 2007)
+# Committer: Russell King (Sun Sep 23 14:18:03 BST 2007)
+#   
+#   [ARM] lubbock, mainstone: only initialise if running on that platform
+#   
+#   Signed-off-by: Russell King
+#
+#
+# Author:    eric miao (Wed Aug 29 10:22:17 BST 2007)
+# Committer: Russell King (Sun Sep 23 14:18:01 BST 2007)
+#   
+#   [ARM] 4560/1: pxa: move processor specific set_wake logic out of irq.c
+#   
+#   a function pxa_init_irq_set_wake() was introduced, so that
+#   processor specific code could install their own version
+#   
+#   code setting PFER and PRER registers within pxa_gpio_irq_type
+#   are removed, and the edge configuration is postponed to the
+#   (*set_wake) and copies the GRER and GFER register, which will
+#   always be set up correctly by pxa_gpio_irq_type()
+#   
+#   Signed-off-by: eric miao
+#   Signed-off-by: Russell King
+#
+#
+# Author:    eric miao (Wed Aug 29 10:18:47 BST 2007)
+# Committer: Russell King (Sun Sep 23 14:17:59 BST 2007)
+#   
+#   [ARM] 4559/1: pxa: make PXA_LAST_GPIO a run-time variable
+#   
+#   This definition produces processor specific code in generic function
+#   pxa_gpio_mode(), thus creating inconsistencies for support of pxa25x
+#   and pxa27x in a single zImage.
+#   
+#   As David Brownell suggests, make it a run-time variable and initialize
+#   at run-time according to the number of GPIOs on the processor. For now
+#   the initialization happens in pxa_init_irq_gpio(),  since there is
+#   already a parameter for that, besides, this is and MUST be earlier
+#   than any subsequent calls to pxa_gpio_mode().
+#   
+#   Signed-off-by: eric miao
+#   Signed-off-by: Russell King
+#
+#
+# Author:    eric miao (Wed Aug 29 10:15:41 BST 2007)
+# Committer: Russell King (Sun Sep 23 14:17:57 BST 2007)
+#   
+#   [ARM] 4558/1: pxa: remove MACH_TYPE_LUBBOCK assignment and leave it to boot loader
+#   
+#   since both u-boot and blob support passing MACH_TYPE_LUBBOCK to the
+#   kernel, it should be quite safe to remove this
+#   
+#   Signed-off-by: eric miao
+#   Acked-by: Nicolas Pitre
+#   Signed-off-by: Russell King
+#
+#
+# Author:    eric miao (Wed Sep 12 03:13:17 BST 2007)
+# Committer: Russell King (Sun Sep 23 14:17:55 BST 2007)
+#   
+#   [ARM] pxa: add PXA3 cpu_is_xxx() macros
+#   
+#   Extracted from patch by Eric Miao, this adds the cpu_is_xxx() macros
+#   for identifying PXA3 SoCs.
+#   
+#   Signed-off-by: eric miao
+#   Signed-off-by: Russell King
+#
+#
+# Author:    Russell King (Wed Sep 19 09:38:32 BST 2007)
+# Committer: Russell King (Sun Sep 23 14:17:51 BST 2007)
+#   
+#   [ARM] pxa: Make CPU_XSCALE depend on PXA25x or PXA27x
+#   
+#   PXA3 SoCs are supported by the Xscale3 CPU code rather than the
+#   Xscale CPU code.
+#   
+#   Signed-off-by: Russell King
+#
+#
+# Author:    Russell King (Wed Sep 19 09:33:55 BST 2007)
+# Committer: Russell King (Sun Sep 23 14:17:48 BST 2007)
+#   
+#   [ARM] pxa: mark pxa_set_cken deprecated
+#   
+#   Allow the generic clock support code to fiddle with the CKEN register
+#   and mark pxa_set_cken() deprecated.
+#   
+#   Signed-off-by: Russell King
+#
+#
+# Author:    Russell King (Mon Aug 20 10:34:37 BST 2007)
+# Committer: Russell King (Sun Sep 23 14:17:43 BST 2007)
+#   
+#   [ARM] pxa: remove get_lcdclk_frequency_10khz()
+#   
+#   get_lcdclk_frequency_10khz() is now redundant, remove it.  Hide
+#   pxa27x_get_lcdclk_frequency_10khz() from public view.
+#   
+#   Signed-off-by: Russell King
+#
+#
+# Author:    Russell King (Sun Sep  2 17:09:23 BST 2007)
+# Committer: Russell King (Sun Sep 23 14:17:39 BST 2007)
+#   
+#   [ARM] pxa: update pxa irda driver to use clk support
+#   
+#   Signed-off-by: Russell King
+#
+#
+# Author:    Russell King (Sun Sep  2 17:08:42 BST 2007)
+# Committer: Russell King (Sun Sep 23 14:17:36 BST 2007)
+#   
+#   [ARM] pxa: Make STUART and FICP clocks available
+#   
+#   Signed-off-by: Russell King
+#
+#
+# Author:    Russell King (Mon Aug 20 10:33:35 BST 2007)
+# Committer: Russell King (Sun Sep 23 14:17:34 BST 2007)
+#   
+#   [ARM] pxa: update PXA UDC driver to use clk support
+#   
+#   Note: this produces a WARN() dump.
+#   
+#   Signed-off-by: Russell King
+#
+#
+# Author:    Russell King (Mon Aug 20 10:28:15 BST 2007)
+# Committer: Russell King (Sun Sep 23 14:17:31 BST 2007)
+#   
+#   [ARM] pxa: update pxa serial driver to use clk support
+#   
+#   Signed-off-by: Russell King
+#
+#
+# Author:    Russell King (Mon Aug 20 10:20:03 BST 2007)
+# Committer: Russell King (Sun Sep 23 14:17:27 BST 2007)
+#   
+#   [ARM] pxa: update PXA MMC interface driver to use clk support
+#   
+#   Signed-off-by: Russell King
+#
+#
+# Author:    Russell King (Mon Aug 20 10:19:39 BST 2007)
+# Committer: Russell King (Sun Sep 23 14:17:23 BST 2007)
+#   
+#   [ARM] pxa: update pxa27x keypad driver to use clk support
+#   
+#   Signed-off-by: Russell King
+#
+#
+# Author:    Russell King (Mon Aug 20 10:19:10 BST 2007)
+# Committer: Russell King (Sun Sep 23 14:17:19 BST 2007)
+#   
+#   [ARM] pxa: update pxa i2c driver to use clk support
+#   
+#   Signed-off-by: Russell King
+#
+#
+# Author:    Russell King (Mon Aug 20 10:18:42 BST 2007)
+# Committer: Russell King (Sun Sep 23 14:16:50 BST 2007)
+#   
+#   [ARM] pxa: update pxafb to use clk support
+#   
+#   Signed-off-by: Russell King
+#
+#
+# Author:    Russell King (Mon Aug 20 10:18:02 BST 2007)
+# Committer: Russell King (Sat Sep 22 20:48:09 BST 2007)
+#   
+#   [ARM] pxa: introduce clk support for PXA SoC clocks
+#   
+#   Signed-off-by: Russell King
+#
+#    create mode 100644 arch/arm/mach-pxa/clock.h
+#
+# Author:    Russell King (Mon Aug 20 10:09:18 BST 2007)
+# Committer: Russell King (Sat Sep 22 20:48:09 BST 2007)
+#   
+#   [ARM] pxa: make pxa27x devices globally visible
+#   
+#   Signed-off-by: Russell King
+#
+#
+# Author:    Russell King (Mon Aug 20 10:07:44 BST 2007)
+# Committer: Russell King (Sat Sep 22 20:48:08 BST 2007)
+#   
+#   [ARM] pxa: fix naming of memory/lcd/core clock functions
+#   
+#   Rename pxa25x and pxa27x memory/lcd/core clock functions, and
+#   select the correct version at run time.
+#   
+#   Signed-off-by: Russell King
+#
+#
+# Author:    Russell King (Mon Aug 20 09:47:41 BST 2007)
+# Committer: Russell King (Sat Sep 22 20:48:08 BST 2007)
+#   
+#   [ARM] pxa: convert PXA serial drivers to use platform resources
+#   
+#   Signed-off-by: Russell King
+#
+#
+# Author:    Russell King (Sat Sep  1 21:12:50 BST 2007)
+# Committer: Russell King (Sat Sep 22 20:48:07 BST 2007)
+#   
+#   [ARM] pxa: make pxa timer initialisation select clock rate at runtime
+#   
+#   Rather than using the compile-time constant CLOCK_TICK_RATE, select
+#   the clock tick rate at run time.  We organise the selection so that
+#   PXA3 automatically falls out with the right tick rate.
+#   
+#   Signed-off-by: Russell King
+#
+#
+# Author:    Nicolas Pitre (Fri Aug 17 16:55:22 BST 2007)
+# Committer: Russell King (Sat Sep 22 20:48:05 BST 2007)
+#   
+#   [ARM] 4550/1: sched_clock on PXA should cope with run time clock rate selection
+#   
+#   The previous implementation was relying on compile time optimizations
+#   based on a constant clock rate.  However, support for different PXA
+#   flavors in the same kernel binary requires that the clock be selected at
+#   run time, so here it is.
+#   
+#   Let's move this code to a more appropriate location while at it.
+#   
+#   Signed-off-by: Nicolas Pitre
+#   Signed-off-by: Russell King
+#
+#
+--- linux-2.6.23.orig/arch/arm/Kconfig
++++ linux-2.6.23/arch/arm/Kconfig
+@@ -336,14 +336,14 @@
+         This enables support for Philips PNX4008 mobile platform.
+ config ARCH_PXA
+-      bool "PXA2xx-based"
++      bool "PXA2xx/PXA3xx-based"
+       depends on MMU
+       select ARCH_MTD_XIP
+       select GENERIC_GPIO
+       select GENERIC_TIME
+       select GENERIC_CLOCKEVENTS
+       help
+-        Support for Intel's PXA2XX processor line.
++        Support for Intel/Marvell's PXA2xx/PXA3xx processor line.
+ config ARCH_RPC
+       bool "RiscPC"
+@@ -486,7 +486,7 @@
+ config IWMMXT
+       bool "Enable iWMMXt support"
+       depends on CPU_XSCALE || CPU_XSC3
+-      default y if PXA27x
++      default y if PXA27x || PXA3xx
+       help
+         Enable support for iWMMXt context switching at run time if
+         running on a CPU that supports it.
+--- linux-2.6.23.orig/arch/arm/boot/compressed/head-xscale.S
++++ linux-2.6.23/arch/arm/boot/compressed/head-xscale.S
+@@ -33,10 +33,6 @@
+               bic     r0, r0, #0x1000         @ clear Icache
+               mcr     p15, 0, r0, c1, c0, 0
+-#ifdef CONFIG_ARCH_LUBBOCK
+-              mov     r7, #MACH_TYPE_LUBBOCK
+-#endif
+-
+ #ifdef CONFIG_ARCH_COTULLA_IDP
+               mov     r7, #MACH_TYPE_COTULLA_IDP
+ #endif
+--- linux-2.6.23.orig/arch/arm/mach-pxa/Kconfig
++++ linux-2.6.23/arch/arm/mach-pxa/Kconfig
+@@ -1,6 +1,24 @@
+ if ARCH_PXA
+-menu "Intel PXA2xx Implementations"
++menu "Intel PXA2xx/PXA3xx Implementations"
++
++if PXA3xx
++
++menu "Supported PXA3xx Processor Variants"
++
++config CPU_PXA300
++      bool "PXA300 (codename Monahans-L)"
++
++config CPU_PXA310
++      bool "PXA310 (codename Monahans-LV)"
++      select CPU_PXA300
++
++config CPU_PXA320
++      bool "PXA320 (codename Monahans-P)"
++
++endmenu
++
++endif
+ choice
+       prompt "Select target board"
+@@ -41,6 +59,11 @@
+       bool "CompuLab EM-x270 platform"
+       select PXA27x
++
++config MACH_ZYLONITE
++      bool "PXA3xx Development Platform"
++      select PXA3xx
++
+ config MACH_HX2750
+       bool "HP iPAQ hx2750"
+       select PXA27x
+@@ -228,6 +251,11 @@
+       help
+         Select code specific to PXA27x variants
++config PXA3xx
++      bool
++      help
++        Select code specific to PXA3xx variants
++
+ config PXA_SHARP_C7xx
+       bool
+       select PXA_SSP
+--- linux-2.6.23.orig/arch/arm/mach-pxa/Makefile
++++ linux-2.6.23/arch/arm/mach-pxa/Makefile
+@@ -6,6 +6,9 @@
+ obj-y += clock.o generic.o irq.o dma.o time.o
+ obj-$(CONFIG_PXA25x) += pxa25x.o
+ obj-$(CONFIG_PXA27x) += pxa27x.o
++obj-$(CONFIG_PXA3xx) += pxa3xx.o mfp.o
++obj-$(CONFIG_CPU_PXA300)       += pxa300.o
++obj-$(CONFIG_CPU_PXA320)       += pxa320.o
+ # Specific board support
+ obj-$(CONFIG_ARCH_LUBBOCK) += lubbock.o
+@@ -19,6 +22,12 @@
+ obj-$(CONFIG_MACH_POODLE)     += poodle.o corgi_ssp.o sharpsl_pm.o poodle_pm.o
+ obj-$(CONFIG_MACH_TOSA)         += tosa.o
+ obj-$(CONFIG_MACH_EM_X270) += em-x270.o
++ifeq ($(CONFIG_MACH_ZYLONITE),y)
++   obj-y                      += zylonite.o
++   obj-$(CONFIG_CPU_PXA300)   += zylonite_pxa300.o
++   obj-$(CONFIG_CPU_PXA320)   += zylonite_pxa320.o
++endif
++
+ obj-$(CONFIG_MACH_HX2750)     += hx2750.o hx2750_test.o
+ obj-$(CONFIG_MACH_HTCUNIVERSAL) += htcuniversal/
+--- linux-2.6.23.orig/arch/arm/mach-pxa/clock.c
++++ linux-2.6.23/arch/arm/mach-pxa/clock.c
+@@ -9,19 +9,15 @@
+ #include <linux/string.h>
+ #include <linux/clk.h>
+ #include <linux/spinlock.h>
++#include <linux/platform_device.h>
++#include <linux/delay.h>
+ #include <asm/arch/pxa-regs.h>
+ #include <asm/hardware.h>
+-struct clk {
+-      struct list_head        node;
+-      unsigned long           rate;
+-      struct module           *owner;
+-      const char              *name;
+-      unsigned int            enabled;
+-      void                    (*enable)(void);
+-      void                    (*disable)(void);
+-};
++#include "devices.h"
++#include "generic.h"
++#include "clock.h"
+ static LIST_HEAD(clocks);
+ static DEFINE_MUTEX(clocks_mutex);
+@@ -33,7 +29,8 @@
+       mutex_lock(&clocks_mutex);
+       list_for_each_entry(p, &clocks, node) {
+-              if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
++              if (strcmp(id, p->name) == 0 &&
++                  (p->dev == NULL || p->dev == dev)) {
+                       clk = p;
+                       break;
+               }
+@@ -46,7 +43,6 @@
+ void clk_put(struct clk *clk)
+ {
+-      module_put(clk->owner);
+ }
+ EXPORT_SYMBOL(clk_put);
+@@ -56,8 +52,12 @@
+       spin_lock_irqsave(&clocks_lock, flags);
+       if (clk->enabled++ == 0)
+-              clk->enable();
++              clk->ops->enable(clk);
+       spin_unlock_irqrestore(&clocks_lock, flags);
++
++      if (clk->delay)
++              udelay(clk->delay);
++
+       return 0;
+ }
+ EXPORT_SYMBOL(clk_enable);
+@@ -70,54 +70,75 @@
+       spin_lock_irqsave(&clocks_lock, flags);
+       if (--clk->enabled == 0)
+-              clk->disable();
++              clk->ops->disable(clk);
+       spin_unlock_irqrestore(&clocks_lock, flags);
+ }
+ EXPORT_SYMBOL(clk_disable);
+ unsigned long clk_get_rate(struct clk *clk)
+ {
+-      return clk->rate;
++      unsigned long rate;
++
++      rate = clk->rate;
++      if (clk->ops->getrate)
++              rate = clk->ops->getrate(clk);
++
++      return rate;
+ }
+ EXPORT_SYMBOL(clk_get_rate);
+-static void clk_gpio27_enable(void)
++static void clk_gpio27_enable(struct clk *clk)
+ {
+       pxa_gpio_mode(GPIO11_3_6MHz_MD);
+ }
+-static void clk_gpio27_disable(void)
++static void clk_gpio27_disable(struct clk *clk)
+ {
+ }
+-static struct clk clk_gpio27 = {
+-      .name           = "GPIO27_CLK",
+-      .rate           = 3686400,
++static const struct clkops clk_gpio27_ops = {
+       .enable         = clk_gpio27_enable,
+       .disable        = clk_gpio27_disable,
+ };
+-int clk_register(struct clk *clk)
++
++void clk_cken_enable(struct clk *clk)
+ {
+-      mutex_lock(&clocks_mutex);
+-      list_add(&clk->node, &clocks);
+-      mutex_unlock(&clocks_mutex);
+-      return 0;
++      CKEN |= 1 << clk->cken;
+ }
+-EXPORT_SYMBOL(clk_register);
+-void clk_unregister(struct clk *clk)
++void clk_cken_disable(struct clk *clk)
+ {
++      CKEN &= ~(1 << clk->cken);
++}
++
++const struct clkops clk_cken_ops = {
++      .enable         = clk_cken_enable,
++      .disable        = clk_cken_disable,
++};
++
++static struct clk common_clks[] = {
++      {
++              .name           = "GPIO27_CLK",
++              .ops            = &clk_gpio27_ops,
++              .rate           = 3686400,
++      },
++};
++
++void clks_register(struct clk *clks, size_t num)
++{
++      int i;
++
+       mutex_lock(&clocks_mutex);
+-      list_del(&clk->node);
++      for (i = 0; i < num; i++)
++              list_add(&clks[i].node, &clocks);
+       mutex_unlock(&clocks_mutex);
+ }
+-EXPORT_SYMBOL(clk_unregister);
+ static int __init clk_init(void)
+ {
+-      clk_register(&clk_gpio27);
++      clks_register(common_clks, ARRAY_SIZE(common_clks));
+       return 0;
+ }
+ arch_initcall(clk_init);
+--- /dev/null
++++ linux-2.6.23/arch/arm/mach-pxa/clock.h
+@@ -0,0 +1,43 @@
++struct clk;
++
++struct clkops {
++      void                    (*enable)(struct clk *);
++      void                    (*disable)(struct clk *);
++      unsigned long           (*getrate)(struct clk *);
++};
++
++struct clk {
++      struct list_head        node;
++      const char              *name;
++      struct device           *dev;
++      const struct clkops     *ops;
++      unsigned long           rate;
++      unsigned int            cken;
++      unsigned int            delay;
++      unsigned int            enabled;
++};
++
++#define INIT_CKEN(_name, _cken, _rate, _delay, _dev)  \
++      {                                               \
++              .name   = _name,                        \
++              .dev    = _dev,                         \
++              .ops    = &clk_cken_ops,                \
++              .rate   = _rate,                        \
++              .cken   = CKEN_##_cken,                 \
++              .delay  = _delay,                       \
++      }
++
++#define INIT_CK(_name, _cken, _ops, _dev)             \
++      {                                               \
++              .name   = _name,                        \
++              .dev    = _dev,                         \
++              .ops    = _ops,                         \
++              .cken   = CKEN_##_cken,                 \
++      }
++
++extern const struct clkops clk_cken_ops;
++
++void clk_cken_enable(struct clk *clk);
++void clk_cken_disable(struct clk *clk);
++
++void clks_register(struct clk *clks, size_t num);
+--- linux-2.6.23.orig/arch/arm/mach-pxa/devices.h
++++ linux-2.6.23/arch/arm/mach-pxa/devices.h
+@@ -9,3 +9,6 @@
+ extern struct platform_device pxa_device_i2s;
+ extern struct platform_device pxa_device_ficp;
+ extern struct platform_device pxa_device_rtc;
++
++extern struct platform_device pxa27x_device_i2c_power;
++extern struct platform_device pxa27x_device_ohci;
+--- linux-2.6.23.orig/arch/arm/mach-pxa/generic.c
++++ linux-2.6.23/arch/arm/mach-pxa/generic.c
+@@ -25,10 +25,6 @@
+ #include <linux/pm.h>
+ #include <linux/string.h>
+-#include <linux/sched.h>
+-#include <asm/cnt32_to_63.h>
+-#include <asm/div64.h>
+-
+ #include <asm/hardware.h>
+ #include <asm/irq.h>
+ #include <asm/system.h>
+@@ -48,66 +44,39 @@
+ #include "generic.h"
+ /*
+- * This is the PXA2xx sched_clock implementation. This has a resolution
+- * of at least 308ns and a maximum value that depends on the value of
+- * CLOCK_TICK_RATE.
+- *
+- * The return value is guaranteed to be monotonic in that range as
+- * long as there is always less than 582 seconds between successive
+- * calls to this function.
++ * Get the clock frequency as reflected by CCCR and the turbo flag.
++ * We assume these values have been applied via a fcs.
++ * If info is not 0 we also display the current settings.
+  */
+-unsigned long long sched_clock(void)
++unsigned int get_clk_frequency_khz(int info)
+ {
+-      unsigned long long v = cnt32_to_63(OSCR);
+-      /* Note: top bit ov v needs cleared unless multiplier is even. */
+-
+-#if   CLOCK_TICK_RATE == 3686400
+-      /* 1E9 / 3686400 => 78125 / 288, max value = 32025597s (370 days). */
+-      /* The <<1 is used to get rid of tick.hi top bit */
+-      v *= 78125<<1;
+-      do_div(v, 288<<1);
+-#elif CLOCK_TICK_RATE == 3250000
+-      /* 1E9 / 3250000 => 4000 / 13, max value = 709490156s (8211 days) */
+-      v *= 4000;
+-      do_div(v, 13);
+-#elif CLOCK_TICK_RATE == 3249600
+-      /* 1E9 / 3249600 => 625000 / 2031, max value = 4541295s (52 days) */
+-      v *= 625000;
+-      do_div(v, 2031);
+-#else
+-#warning "consider fixing sched_clock for your value of CLOCK_TICK_RATE"
+-      /*
+-       * 96-bit math to perform tick * NSEC_PER_SEC / CLOCK_TICK_RATE for
+-       * any value of CLOCK_TICK_RATE. Max value is in the 80 thousand
+-       * years range and truncation to unsigned long long limits it to
+-       * sched_clock's max range of ~584 years.  This is nice but with
+-       * higher computation cost.
+-       */
+-      {
+-              union {
+-                      unsigned long long val;
+-                      struct { unsigned long lo, hi; };
+-              } x;
+-              unsigned long long y;
+-
+-              x.val = v;
+-              x.hi &= 0x7fffffff;
+-              y = (unsigned long long)x.lo * NSEC_PER_SEC;
+-              x.lo = y;
+-              y = (y >> 32) + (unsigned long long)x.hi * NSEC_PER_SEC;
+-              x.hi = do_div(y, CLOCK_TICK_RATE);
+-              do_div(x.val, CLOCK_TICK_RATE);
+-              x.hi += y;
+-              v = x.val;
+-      }
+-#endif
++      if (cpu_is_pxa21x() || cpu_is_pxa25x())
++              return pxa25x_get_clk_frequency_khz(info);
++      else if (cpu_is_pxa27x())
++              return pxa27x_get_clk_frequency_khz(info);
++      else
++              return pxa3xx_get_clk_frequency_khz(info);
++}
++EXPORT_SYMBOL(get_clk_frequency_khz);
+-      return v;
++/*
++ * Return the current memory clock frequency in units of 10kHz
++ */
++unsigned int get_memclk_frequency_10khz(void)
++{
++      if (cpu_is_pxa21x() || cpu_is_pxa25x())
++              return pxa25x_get_memclk_frequency_10khz();
++      else if (cpu_is_pxa27x())
++              return pxa27x_get_memclk_frequency_10khz();
++      else
++              return pxa3xx_get_memclk_frequency_10khz();
+ }
++EXPORT_SYMBOL(get_memclk_frequency_10khz);
+ /*
+  * Handy function to set GPIO alternate functions
+  */
++int pxa_last_gpio;
+ int pxa_gpio_mode(int gpio_mode)
+ {
+@@ -116,7 +85,7 @@
+       int fn = (gpio_mode & GPIO_MD_MASK_FN) >> 8;
+       int gafr;
+-      if (gpio > PXA_LAST_GPIO)
++      if (gpio > pxa_last_gpio)
+               return -EINVAL;
+       local_irq_save(flags);
+@@ -160,7 +129,7 @@
+ /*
+  * Routine to safely enable or disable a clock in the CKEN
+  */
+-void pxa_set_cken(int clock, int enable)
++void __pxa_set_cken(int clock, int enable)
+ {
+       unsigned long flags;
+       local_irq_save(flags);
+@@ -173,7 +142,7 @@
+       local_irq_restore(flags);
+ }
+-EXPORT_SYMBOL(pxa_set_cken);
++EXPORT_SYMBOL(__pxa_set_cken);
+ /*
+  * Intel PXA2xx internal register mapping.
+@@ -330,21 +299,80 @@
+       pxa_device_fb.dev.parent = parent_dev;
+ }
++static struct resource pxa_resource_ffuart[] = {
++      {
++              .start  = __PREG(FFUART),
++              .end    = __PREG(FFUART) + 35,
++              .flags  = IORESOURCE_MEM,
++      }, {
++              .start  = IRQ_FFUART,
++              .end    = IRQ_FFUART,
++              .flags  = IORESOURCE_IRQ,
++      }
++};
++
+ struct platform_device pxa_device_ffuart= {
+       .name           = "pxa2xx-uart",
+       .id             = 0,
++      .resource       = pxa_resource_ffuart,
++      .num_resources  = ARRAY_SIZE(pxa_resource_ffuart),
++};
++
++static struct resource pxa_resource_btuart[] = {
++      {
++              .start  = __PREG(BTUART),
++              .end    = __PREG(BTUART) + 35,
++              .flags  = IORESOURCE_MEM,
++      }, {
++              .start  = IRQ_BTUART,
++              .end    = IRQ_BTUART,
++              .flags  = IORESOURCE_IRQ,
++      }
+ };
++
+ struct platform_device pxa_device_btuart = {
+       .name           = "pxa2xx-uart",
+       .id             = 1,
++      .resource       = pxa_resource_btuart,
++      .num_resources  = ARRAY_SIZE(pxa_resource_btuart),
+ };
++
++static struct resource pxa_resource_stuart[] = {
++      {
++              .start  = __PREG(STUART),
++              .end    = __PREG(STUART) + 35,
++              .flags  = IORESOURCE_MEM,
++      }, {
++              .start  = IRQ_STUART,
++              .end    = IRQ_STUART,
++              .flags  = IORESOURCE_IRQ,
++      }
++};
++
+ struct platform_device pxa_device_stuart = {
+       .name           = "pxa2xx-uart",
+       .id             = 2,
++      .resource       = pxa_resource_stuart,
++      .num_resources  = ARRAY_SIZE(pxa_resource_stuart),
++};
++
++static struct resource pxa_resource_hwuart[] = {
++      {
++              .start  = __PREG(HWUART),
++              .end    = __PREG(HWUART) + 47,
++              .flags  = IORESOURCE_MEM,
++      }, {
++              .start  = IRQ_HWUART,
++              .end    = IRQ_HWUART,
++              .flags  = IORESOURCE_IRQ,
++      }
+ };
++
+ struct platform_device pxa_device_hwuart = {
+       .name           = "pxa2xx-uart",
+       .id             = 3,
++      .resource       = pxa_resource_hwuart,
++      .num_resources  = ARRAY_SIZE(pxa_resource_hwuart),
+ };
+ void __init pxa_set_ffuart_info(struct platform_pxa_serial_funcs *info)
+--- linux-2.6.23.orig/arch/arm/mach-pxa/generic.h
++++ linux-2.6.23/arch/arm/mach-pxa/generic.h
+@@ -15,14 +15,40 @@
+ extern void __init pxa_init_irq_low(void);
+ extern void __init pxa_init_irq_high(void);
+ extern void __init pxa_init_irq_gpio(int gpio_nr);
++extern void __init pxa_init_irq_set_wake(int (*set_wake)(unsigned int, unsigned int));
+ extern void __init pxa25x_init_irq(void);
+ extern void __init pxa27x_init_irq(void);
++extern void __init pxa3xx_init_irq(void);
+ extern void __init pxa_map_io(void);
+ extern unsigned int get_clk_frequency_khz(int info);
++extern int pxa_last_gpio;
+ #define SET_BANK(__nr,__start,__size) \
+       mi->bank[__nr].start = (__start), \
+       mi->bank[__nr].size = (__size), \
+       mi->bank[__nr].node = (((unsigned)(__start) - PHYS_OFFSET) >> 27)
++#ifdef CONFIG_PXA25x
++extern unsigned pxa25x_get_clk_frequency_khz(int);
++extern unsigned pxa25x_get_memclk_frequency_10khz(void);
++#else
++#define pxa25x_get_clk_frequency_khz(x)               (0)
++#define pxa25x_get_memclk_frequency_10khz()   (0)
++#endif
++
++#ifdef CONFIG_PXA27x
++extern unsigned pxa27x_get_clk_frequency_khz(int);
++extern unsigned pxa27x_get_memclk_frequency_10khz(void);
++#else
++#define pxa27x_get_clk_frequency_khz(x)               (0)
++#define pxa27x_get_memclk_frequency_10khz()   (0)
++#endif
++
++#ifdef CONFIG_PXA3xx
++extern unsigned pxa3xx_get_clk_frequency_khz(int);
++extern unsigned pxa3xx_get_memclk_frequency_10khz(void);
++#else
++#define pxa3xx_get_clk_frequency_khz(x)               (0)
++#define pxa3xx_get_memclk_frequency_10khz()   (0)
++#endif
+--- linux-2.6.23.orig/arch/arm/mach-pxa/irq.c
++++ linux-2.6.23/arch/arm/mach-pxa/irq.c
+@@ -38,33 +38,11 @@
+       ICMR |= (1 << irq);
+ }
+-static int pxa_set_wake(unsigned int irq, unsigned int on)
+-{
+-      u32     mask;
+-
+-      switch (irq) {
+-      case IRQ_RTCAlrm:
+-              mask = PWER_RTC;
+-              break;
+-#ifdef CONFIG_PXA27x
+-      /* REVISIT can handle USBH1, USBH2, USB, MSL, USIM, ... */
+-#endif
+-      default:
+-              return -EINVAL;
+-      }
+-      if (on)
+-              PWER |= mask;
+-      else
+-              PWER &= ~mask;
+-      return 0;
+-}
+-
+ static struct irq_chip pxa_internal_chip_low = {
+       .name           = "SC",
+       .ack            = pxa_mask_low_irq,
+       .mask           = pxa_mask_low_irq,
+       .unmask         = pxa_unmask_low_irq,
+-      .set_wake       = pxa_set_wake,
+ };
+ void __init pxa_init_irq_low(void)
+@@ -87,7 +65,7 @@
+       }
+ }
+-#ifdef CONFIG_PXA27x
++#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
+ /*
+  * This is for the second set of internal IRQs as found on the PXA27x.
+@@ -125,26 +103,6 @@
+ }
+ #endif
+-/* Note that if an input/irq line ever gets changed to an output during
+- * suspend, the relevant PWER, PRER, and PFER bits should be cleared.
+- */
+-#ifdef CONFIG_PXA27x
+-
+-/* PXA27x:  Various gpios can issue wakeup events.  This logic only
+- * handles the simple cases, not the WEMUX2 and WEMUX3 options
+- */
+-#define PXA27x_GPIO_NOWAKE_MASK \
+-      ((1 << 8) | (1 << 7) | (1 << 6) | (1 << 5) | (1 << 2))
+-#define       WAKEMASK(gpio) \
+-      (((gpio) <= 15) \
+-              ? ((1 << (gpio)) & ~PXA27x_GPIO_NOWAKE_MASK) \
+-              : ((gpio == 35) ? (1 << 24) : 0))
+-#else
+-
+-/* pxa 210, 250, 255, 26x:  gpios 0..15 can issue wakeups */
+-#define       WAKEMASK(gpio) (((gpio) <= 15) ? (1 << (gpio)) : 0)
+-#endif
+-
+ /*
+  * PXA GPIO edge detection for IRQs:
+  * IRQs are generated on Falling-Edge, Rising-Edge, or both.
+@@ -158,11 +116,9 @@
+ static int pxa_gpio_irq_type(unsigned int irq, unsigned int type)
+ {
+       int gpio, idx;
+-      u32 mask;
+       gpio = IRQ_TO_GPIO(irq);
+       idx = gpio >> 5;
+-      mask = WAKEMASK(gpio);
+       if (type == IRQT_PROBE) {
+           /* Don't mess with enabled GPIOs using preconfigured edges or
+@@ -182,19 +138,15 @@
+       if (type & __IRQT_RISEDGE) {
+               /* printk("rising "); */
+               __set_bit (gpio, GPIO_IRQ_rising_edge);
+-              PRER |= mask;
+       } else {
+               __clear_bit (gpio, GPIO_IRQ_rising_edge);
+-              PRER &= ~mask;
+       }
+       if (type & __IRQT_FALEDGE) {
+               /* printk("falling "); */
+               __set_bit (gpio, GPIO_IRQ_falling_edge);
+-              PFER |= mask;
+       } else {
+               __clear_bit (gpio, GPIO_IRQ_falling_edge);
+-              PFER &= ~mask;
+       }
+       /* printk("edges\n"); */
+@@ -213,29 +165,12 @@
+       GEDR0 = (1 << (irq - IRQ_GPIO0));
+ }
+-static int pxa_set_gpio_wake(unsigned int irq, unsigned int on)
+-{
+-      int     gpio = IRQ_TO_GPIO(irq);
+-      u32     mask = WAKEMASK(gpio);
+-
+-      if (!mask)
+-              return -EINVAL;
+-
+-      if (on)
+-              PWER |= mask;
+-      else
+-              PWER &= ~mask;
+-      return 0;
+-}
+-
+-
+ static struct irq_chip pxa_low_gpio_chip = {
+       .name           = "GPIO-l",
+       .ack            = pxa_ack_low_gpio,
+       .mask           = pxa_mask_low_irq,
+       .unmask         = pxa_unmask_low_irq,
+       .set_type       = pxa_gpio_irq_type,
+-      .set_wake       = pxa_set_gpio_wake,
+ };
+ /*
+@@ -342,13 +277,14 @@
+       .mask           = pxa_mask_muxed_gpio,
+       .unmask         = pxa_unmask_muxed_gpio,
+       .set_type       = pxa_gpio_irq_type,
+-      .set_wake       = pxa_set_gpio_wake,
+ };
+ void __init pxa_init_irq_gpio(int gpio_nr)
+ {
+       int irq, i;
++      pxa_last_gpio = gpio_nr - 1;
++
+       /* clear all GPIO edge detects */
+       for (i = 0; i < gpio_nr; i += 32) {
+               GFER(i) = 0;
+@@ -375,3 +311,13 @@
+       set_irq_chip(IRQ_GPIO_2_x, &pxa_internal_chip_low);
+       set_irq_chained_handler(IRQ_GPIO_2_x, pxa_gpio_demux_handler);
+ }
++
++void __init pxa_init_irq_set_wake(int (*set_wake)(unsigned int, unsigned int))
++{
++      pxa_internal_chip_low.set_wake = set_wake;
++#ifdef CONFIG_PXA27x
++      pxa_internal_chip_high.set_wake = set_wake;
++#endif
++      pxa_low_gpio_chip.set_wake = set_wake;
++      pxa_muxed_gpio_chip.set_wake = set_wake;
++}
+--- /dev/null
++++ linux-2.6.23/arch/arm/mach-pxa/mfp.c
+@@ -0,0 +1,235 @@
++/*
++ * linux/arch/arm/mach-pxa/mfp.c
++ *
++ * PXA3xx Multi-Function Pin Support
++ *
++ * Copyright (C) 2007 Marvell Internation Ltd.
++ *
++ * 2007-08-21: eric miao <eric.y.miao@gmail.com>
++ *             initial version
++ *
++ *  This program is free software; you can 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/io.h>
++
++#include <asm/hardware.h>
++#include <asm/arch/mfp.h>
++
++/* mfp_spin_lock is used to ensure that MFP register configuration
++ * (most likely a read-modify-write operation) is atomic, and that
++ * mfp_table[] is consistent
++ */
++static DEFINE_SPINLOCK(mfp_spin_lock);
++
++static void __iomem *mfpr_mmio_base = (void __iomem *)&__REG(MFPR_BASE);
++static struct pxa3xx_mfp_pin mfp_table[MFP_PIN_MAX];
++
++#define mfpr_readl(off)                       \
++      __raw_readl(mfpr_mmio_base + (off))
++
++#define mfpr_writel(off, val)         \
++      __raw_writel(val, mfpr_mmio_base + (off))
++
++/*
++ * perform a read-back of any MFPR register to make sure the
++ * previous writings are finished
++ */
++#define mfpr_sync()   (void)__raw_readl(mfpr_mmio_base + 0)
++
++static inline void __mfp_config(int pin, unsigned long val)
++{
++      unsigned long off = mfp_table[pin].mfpr_off;
++
++      mfp_table[pin].mfpr_val = val;
++      mfpr_writel(off, val);
++}
++
++void pxa3xx_mfp_config(mfp_cfg_t *mfp_cfgs, int num)
++{
++      int i, pin;
++      unsigned long val, flags;
++      mfp_cfg_t *mfp_cfg = mfp_cfgs;
++
++      spin_lock_irqsave(&mfp_spin_lock, flags);
++
++      for (i = 0; i < num; i++, mfp_cfg++) {
++              pin = MFP_CFG_PIN(*mfp_cfg);
++              val = MFP_CFG_VAL(*mfp_cfg);
++
++              BUG_ON(pin >= MFP_PIN_MAX);
++
++              __mfp_config(pin, val);
++      }
++
++      mfpr_sync();
++      spin_unlock_irqrestore(&mfp_spin_lock, flags);
++}
++
++unsigned long pxa3xx_mfp_read(int mfp)
++{
++      unsigned long val, flags;
++
++      BUG_ON(mfp >= MFP_PIN_MAX);
++
++      spin_lock_irqsave(&mfp_spin_lock, flags);
++      val = mfpr_readl(mfp_table[mfp].mfpr_off);
++      spin_unlock_irqrestore(&mfp_spin_lock, flags);
++
++      return val;
++}
++
++void pxa3xx_mfp_write(int mfp, unsigned long val)
++{
++      unsigned long flags;
++
++      BUG_ON(mfp >= MFP_PIN_MAX);
++
++      spin_lock_irqsave(&mfp_spin_lock, flags);
++      mfpr_writel(mfp_table[mfp].mfpr_off, val);
++      mfpr_sync();
++      spin_unlock_irqrestore(&mfp_spin_lock, flags);
++}
++
++void pxa3xx_mfp_set_afds(int mfp, int af, int ds)
++{
++      uint32_t mfpr_off, mfpr_val;
++      unsigned long flags;
++
++      BUG_ON(mfp >= MFP_PIN_MAX);
++
++      spin_lock_irqsave(&mfp_spin_lock, flags);
++      mfpr_off = mfp_table[mfp].mfpr_off;
++
++      mfpr_val = mfpr_readl(mfpr_off);
++      mfpr_val &= ~(MFPR_AF_MASK | MFPR_DRV_MASK);
++      mfpr_val |= (((af & 0x7) << MFPR_ALT_OFFSET) |
++                   ((ds & 0x7) << MFPR_DRV_OFFSET));
++
++      mfpr_writel(mfpr_off, mfpr_val);
++      mfpr_sync();
++
++      spin_unlock_irqrestore(&mfp_spin_lock, flags);
++}
++
++void pxa3xx_mfp_set_rdh(int mfp, int rdh)
++{
++      uint32_t mfpr_off, mfpr_val;
++      unsigned long flags;
++
++      BUG_ON(mfp >= MFP_PIN_MAX);
++
++      spin_lock_irqsave(&mfp_spin_lock, flags);
++
++      mfpr_off = mfp_table[mfp].mfpr_off;
++
++      mfpr_val = mfpr_readl(mfpr_off);
++      mfpr_val &= ~MFPR_RDH_MASK;
++
++      if (likely(rdh))
++              mfpr_val |= (1u << MFPR_SS_OFFSET);
++
++      mfpr_writel(mfpr_off, mfpr_val);
++      mfpr_sync();
++
++      spin_unlock_irqrestore(&mfp_spin_lock, flags);
++}
++
++void pxa3xx_mfp_set_lpm(int mfp, int lpm)
++{
++      uint32_t mfpr_off, mfpr_val;
++      unsigned long flags;
++
++      BUG_ON(mfp >= MFP_PIN_MAX);
++
++      spin_lock_irqsave(&mfp_spin_lock, flags);
++
++      mfpr_off = mfp_table[mfp].mfpr_off;
++      mfpr_val = mfpr_readl(mfpr_off);
++      mfpr_val &= ~MFPR_LPM_MASK;
++
++      if (lpm & 0x1) mfpr_val |= 1u << MFPR_SON_OFFSET;
++      if (lpm & 0x2) mfpr_val |= 1u << MFPR_SD_OFFSET;
++      if (lpm & 0x4) mfpr_val |= 1u << MFPR_PU_OFFSET;
++      if (lpm & 0x8) mfpr_val |= 1u << MFPR_PD_OFFSET;
++      if (lpm &0x10) mfpr_val |= 1u << MFPR_PS_OFFSET;
++
++      mfpr_writel(mfpr_off, mfpr_val);
++      mfpr_sync();
++
++      spin_unlock_irqrestore(&mfp_spin_lock, flags);
++}
++
++void pxa3xx_mfp_set_pull(int mfp, int pull)
++{
++      uint32_t mfpr_off, mfpr_val;
++      unsigned long flags;
++
++      BUG_ON(mfp >= MFP_PIN_MAX);
++
++      spin_lock_irqsave(&mfp_spin_lock, flags);
++
++      mfpr_off = mfp_table[mfp].mfpr_off;
++      mfpr_val = mfpr_readl(mfpr_off);
++      mfpr_val &= ~MFPR_PULL_MASK;
++      mfpr_val |= ((pull & 0x7u) << MFPR_PD_OFFSET);
++
++      mfpr_writel(mfpr_off, mfpr_val);
++      mfpr_sync();
++
++      spin_unlock_irqrestore(&mfp_spin_lock, flags);
++}
++
++void pxa3xx_mfp_set_edge(int mfp, int edge)
++{
++      uint32_t mfpr_off, mfpr_val;
++      unsigned long flags;
++
++      BUG_ON(mfp >= MFP_PIN_MAX);
++
++      spin_lock_irqsave(&mfp_spin_lock, flags);
++
++      mfpr_off = mfp_table[mfp].mfpr_off;
++      mfpr_val = mfpr_readl(mfpr_off);
++
++      mfpr_val &= ~MFPR_EDGE_MASK;
++      mfpr_val |= (edge & 0x3u) << MFPR_ERE_OFFSET;
++      mfpr_val |= (!edge & 0x1) << MFPR_EC_OFFSET;
++
++      mfpr_writel(mfpr_off, mfpr_val);
++      mfpr_sync();
++
++      spin_unlock_irqrestore(&mfp_spin_lock, flags);
++}
++
++void __init pxa3xx_mfp_init_addr(struct pxa3xx_mfp_addr_map *map)
++{
++      struct pxa3xx_mfp_addr_map *p;
++      unsigned long offset, flags;
++      int i;
++
++      spin_lock_irqsave(&mfp_spin_lock, flags);
++
++      for (p = map; p->start != MFP_PIN_INVALID; p++) {
++              offset = p->offset;
++              i = p->start;
++
++              do {
++                      mfp_table[i].mfpr_off = offset;
++                      mfp_table[i].mfpr_val = 0;
++                      offset += 4; i++;
++              } while ((i <= p->end) && (p->end != -1));
++      }
++
++      spin_unlock_irqrestore(&mfp_spin_lock, flags);
++}
++
++void __init pxa3xx_init_mfp(void)
++{
++      memset(mfp_table, 0, sizeof(mfp_table));
++}
+--- linux-2.6.23.orig/arch/arm/mach-pxa/pxa25x.c
++++ linux-2.6.23/arch/arm/mach-pxa/pxa25x.c
+@@ -30,6 +30,7 @@
+ #include "generic.h"
+ #include "devices.h"
++#include "clock.h"
+ /*
+  * Various clock factors driven by the CCCR register.
+@@ -53,7 +54,7 @@
+  * We assume these values have been applied via a fcs.
+  * If info is not 0 we also display the current settings.
+  */
+-unsigned int get_clk_frequency_khz(int info)
++unsigned int pxa25x_get_clk_frequency_khz(int info)
+ {
+       unsigned long cccr, turbo;
+       unsigned int l, L, m, M, n2, N;
+@@ -86,27 +87,48 @@
+       return (turbo & 1) ? (N/1000) : (M/1000);
+ }
+-EXPORT_SYMBOL(get_clk_frequency_khz);
+-
+ /*
+  * Return the current memory clock frequency in units of 10kHz
+  */
+-unsigned int get_memclk_frequency_10khz(void)
++unsigned int pxa25x_get_memclk_frequency_10khz(void)
+ {
+       return L_clk_mult[(CCCR >> 0) & 0x1f] * BASE_CLK / 10000;
+ }
+-EXPORT_SYMBOL(get_memclk_frequency_10khz);
+-
+-/*
+- * Return the current LCD clock frequency in units of 10kHz
+- */
+-unsigned int get_lcdclk_frequency_10khz(void)
++static unsigned long clk_pxa25x_lcd_getrate(struct clk *clk)
+ {
+-      return get_memclk_frequency_10khz();
++      return pxa25x_get_memclk_frequency_10khz() * 10000;
+ }
+-EXPORT_SYMBOL(get_lcdclk_frequency_10khz);
++static const struct clkops clk_pxa25x_lcd_ops = {
++      .enable         = clk_cken_enable,
++      .disable        = clk_cken_disable,
++      .getrate        = clk_pxa25x_lcd_getrate,
++};
++
++/*
++ * 3.6864MHz -> OST, GPIO, SSP, PWM, PLLs (95.842MHz, 147.456MHz)
++ * 95.842MHz -> MMC 19.169MHz, I2C 31.949MHz, FICP 47.923MHz, USB 47.923MHz
++ * 147.456MHz -> UART 14.7456MHz, AC97 12.288MHz, I2S 5.672MHz (allegedly)
++ */
++static struct clk pxa25x_clks[] = {
++      INIT_CK("LCDCLK", LCD, &clk_pxa25x_lcd_ops, &pxa_device_fb.dev),
++      INIT_CKEN("UARTCLK", FFUART, 14745600, 1, &pxa_device_ffuart.dev),
++      INIT_CKEN("UARTCLK", BTUART, 14745600, 1, &pxa_device_btuart.dev),
++      INIT_CKEN("UARTCLK", BTUART, 14745600, 1, &pxa_device_btuart.dev),
++      INIT_CKEN("UARTCLK", STUART, 14745600, 1, NULL),
++      INIT_CKEN("UDCCLK", USB, 47923000, 5, &pxa_device_udc.dev),
++      INIT_CKEN("MMCCLK", MMC, 19169000, 0, &pxa_device_mci.dev),
++      INIT_CKEN("I2CCLK", I2C, 31949000, 0, &pxa_device_i2c.dev),
++      /*
++      INIT_CKEN("PWMCLK",  PWM0, 3686400,  0, NULL),
++      INIT_CKEN("PWMCLK",  PWM0, 3686400,  0, NULL),
++      INIT_CKEN("SSPCLK",  SSP,  3686400,  0, NULL),
++      INIT_CKEN("I2SCLK",  I2S,  14745600, 0, NULL),
++      INIT_CKEN("NSSPCLK", NSSP, 3686400,  0, NULL),
++      */
++      INIT_CKEN("FICPCLK", FICP, 47923000, 0, NULL),
++};
+ #ifdef CONFIG_PM
+@@ -207,10 +229,52 @@
+ }
+ #endif
++/* PXA25x: supports wakeup from GPIO0..GPIO15 and RTC alarm
++ */
++
++static int pxa25x_set_wake(unsigned int irq, unsigned int on)
++{
++      int gpio = IRQ_TO_GPIO(irq);
++      uint32_t gpio_bit, mask = 0;
++
++      if (gpio >= 0 && gpio <= 15) {
++              gpio_bit = GPIO_bit(gpio);
++              mask = gpio_bit;
++              if (on) {
++                      if (GRER(gpio) | gpio_bit)
++                              PRER |= gpio_bit;
++                      else
++                              PRER &= ~gpio_bit;
++
++                      if (GFER(gpio) | gpio_bit)
++                              PFER |= gpio_bit;
++                      else
++                              PFER &= ~gpio_bit;
++              }
++              goto set_pwer;
++      }
++
++      if (irq == IRQ_RTCAlrm) {
++              mask = PWER_RTC;
++              goto set_pwer;
++      }
++
++      return -EINVAL;
++
++set_pwer:
++      if (on)
++              PWER |= mask;
++      else
++              PWER &=~mask;
++
++      return 0;
++}
++
+ void __init pxa25x_init_irq(void)
+ {
+       pxa_init_irq_low();
+       pxa_init_irq_gpio(85);
++      pxa_init_irq_set_wake(pxa25x_set_wake);
+ }
+ static struct platform_device *pxa25x_devices[] __initdata = {
+@@ -231,6 +295,8 @@
+       int ret = 0;
+       if (cpu_is_pxa21x() || cpu_is_pxa25x()) {
++              clks_register(pxa25x_clks, ARRAY_SIZE(pxa25x_clks));
++
+               if ((ret = pxa_init_dma(16)))
+                       return ret;
+ #ifdef CONFIG_PM
+--- linux-2.6.23.orig/arch/arm/mach-pxa/pxa27x.c
++++ linux-2.6.23/arch/arm/mach-pxa/pxa27x.c
+@@ -27,6 +27,7 @@
+ #include "generic.h"
+ #include "devices.h"
++#include "clock.h"
+ /* Crystal clock: 13MHz */
+ #define BASE_CLK      13000000
+@@ -36,7 +37,7 @@
+  * We assume these values have been applied via a fcs.
+  * If info is not 0 we also display the current settings.
+  */
+-unsigned int get_clk_frequency_khz( int info)
++unsigned int pxa27x_get_clk_frequency_khz(int info)
+ {
+       unsigned long ccsr, clkcfg;
+       unsigned int l, L, m, M, n2, N, S;
+@@ -79,7 +80,7 @@
+  * Return the current mem clock frequency in units of 10kHz as
+  * reflected by CCCR[A], B, and L
+  */
+-unsigned int get_memclk_frequency_10khz(void)
++unsigned int pxa27x_get_memclk_frequency_10khz(void)
+ {
+       unsigned long ccsr, clkcfg;
+       unsigned int l, L, m, M;
+@@ -104,7 +105,7 @@
+ /*
+  * Return the current LCD clock frequency in units of 10kHz as
+  */
+-unsigned int get_lcdclk_frequency_10khz(void)
++static unsigned int pxa27x_get_lcdclk_frequency_10khz(void)
+ {
+       unsigned long ccsr;
+       unsigned int l, L, k, K;
+@@ -120,9 +121,47 @@
+       return (K / 10000);
+ }
+-EXPORT_SYMBOL(get_clk_frequency_khz);
+-EXPORT_SYMBOL(get_memclk_frequency_10khz);
+-EXPORT_SYMBOL(get_lcdclk_frequency_10khz);
++static unsigned long clk_pxa27x_lcd_getrate(struct clk *clk)
++{
++      return pxa27x_get_lcdclk_frequency_10khz() * 10000;
++}
++
++static const struct clkops clk_pxa27x_lcd_ops = {
++      .enable         = clk_cken_enable,
++      .disable        = clk_cken_disable,
++      .getrate        = clk_pxa27x_lcd_getrate,
++};
++
++static struct clk pxa27x_clks[] = {
++      INIT_CK("LCDCLK", LCD,    &clk_pxa27x_lcd_ops, &pxa_device_fb.dev),
++      INIT_CK("CAMCLK", CAMERA, &clk_pxa27x_lcd_ops, NULL),
++
++      INIT_CKEN("UARTCLK", FFUART, 14857000, 1, &pxa_device_ffuart.dev),
++      INIT_CKEN("UARTCLK", BTUART, 14857000, 1, &pxa_device_btuart.dev),
++      INIT_CKEN("UARTCLK", STUART, 14857000, 1, NULL),
++
++      INIT_CKEN("I2SCLK",  I2S,  14682000, 0, &pxa_device_i2s.dev),
++      INIT_CKEN("I2CCLK",  I2C,  32842000, 0, &pxa_device_i2c.dev),
++      INIT_CKEN("UDCCLK",  USB,  48000000, 5, &pxa_device_udc.dev),
++      INIT_CKEN("MMCCLK",  MMC,  19500000, 0, &pxa_device_mci.dev),
++      INIT_CKEN("FICPCLK", FICP, 48000000, 0, &pxa_device_ficp.dev),
++
++      INIT_CKEN("USBCLK", USB,    48000000, 0, &pxa27x_device_ohci.dev),
++      INIT_CKEN("I2CCLK", PWRI2C, 13000000, 0, &pxa27x_device_i2c_power.dev),
++      INIT_CKEN("KBDCLK", KEYPAD, 32768, 0, NULL),
++
++      /*
++      INIT_CKEN("PWMCLK",  PWM0, 13000000, 0, NULL),
++      INIT_CKEN("SSPCLK",  SSP1, 13000000, 0, NULL),
++      INIT_CKEN("SSPCLK",  SSP2, 13000000, 0, NULL),
++      INIT_CKEN("SSPCLK",  SSP3, 13000000, 0, NULL),
++      INIT_CKEN("MSLCLK",  MSL,  48000000, 0, NULL),
++      INIT_CKEN("USIMCLK", USIM, 48000000, 0, NULL),
++      INIT_CKEN("MSTKCLK", MEMSTK, 19500000, 0, NULL),
++      INIT_CKEN("IMCLK",   IM,   0, 0, NULL),
++      INIT_CKEN("MEMCLK",  MEMC, 0, 0, NULL),
++      */
++};
+ #ifdef CONFIG_PM
+@@ -269,6 +308,69 @@
+ }
+ #endif
++/* PXA27x:  Various gpios can issue wakeup events.  This logic only
++ * handles the simple cases, not the WEMUX2 and WEMUX3 options
++ */
++#define PXA27x_GPIO_NOWAKE_MASK \
++        ((1 << 8) | (1 << 7) | (1 << 6) | (1 << 5) | (1 << 2))
++#define WAKEMASK(gpio) \
++        (((gpio) <= 15) \
++                 ? ((1 << (gpio)) & ~PXA27x_GPIO_NOWAKE_MASK) \
++                 : ((gpio == 35) ? (1 << 24) : 0))
++
++static int pxa27x_set_wake(unsigned int irq, unsigned int on)
++{
++      int gpio = IRQ_TO_GPIO(irq);
++      uint32_t mask;
++
++      if ((gpio >= 0 && gpio <= 15) || (gpio == 35)) {
++              if (WAKEMASK(gpio) == 0)
++                      return -EINVAL;
++
++              mask = WAKEMASK(gpio);
++
++              if (on) {
++                      if (GRER(gpio) | GPIO_bit(gpio))
++                              PRER |= mask;
++                      else
++                              PRER &= ~mask;
++
++                      if (GFER(gpio) | GPIO_bit(gpio))
++                              PFER |= mask;
++                      else
++                              PFER &= ~mask;
++              }
++              goto set_pwer;
++      }
++
++      switch (irq) {
++      case IRQ_RTCAlrm:
++              mask = PWER_RTC;
++              break;
++      case IRQ_USB:
++              mask = 1u << 26;
++              break;
++      default:
++              return -EINVAL;
++      }
++
++set_pwer:
++      if (on)
++              PWER |= mask;
++      else
++              PWER &=~mask;
++
++      return 0;
++}
++
++void __init pxa27x_init_irq(void)
++{
++      pxa_init_irq_low();
++      pxa_init_irq_high();
++      pxa_init_irq_gpio(128);
++      pxa_init_irq_set_wake(pxa27x_set_wake);
++}
++
+ /*
+  * device registration specific to PXA27x.
+  */
+@@ -288,7 +390,7 @@
+       },
+ };
+-static struct platform_device pxa27x_device_ohci = {
++struct platform_device pxa27x_device_ohci = {
+       .name           = "pxa27x-ohci",
+       .id             = -1,
+       .dev            = {
+@@ -316,7 +418,7 @@
+       },
+ };
+-static struct platform_device pxa27x_device_i2c_power = {
++struct platform_device pxa27x_device_i2c_power = {
+       .name           = "pxa2xx-i2c",
+       .id             = 1,
+       .resource       = i2c_power_resources,
+@@ -338,17 +440,12 @@
+       &pxa27x_device_ohci,
+ };
+-void __init pxa27x_init_irq(void)
+-{
+-      pxa_init_irq_low();
+-      pxa_init_irq_high();
+-      pxa_init_irq_gpio(128);
+-}
+-
+ static int __init pxa27x_init(void)
+ {
+       int ret = 0;
+       if (cpu_is_pxa27x()) {
++              clks_register(pxa27x_clks, ARRAY_SIZE(pxa27x_clks));
++
+               if ((ret = pxa_init_dma(32)))
+                       return ret;
+ #ifdef CONFIG_PM
+--- /dev/null
++++ linux-2.6.23/arch/arm/mach-pxa/pxa300.c
+@@ -0,0 +1,93 @@
++/*
++ * linux/arch/arm/mach-pxa/pxa300.c
++ *
++ * Code specific to PXA300/PXA310
++ *
++ * Copyright (C) 2007 Marvell Internation Ltd.
++ *
++ * 2007-08-21: eric miao <eric.y.miao@gmail.com>
++ *             initial version
++ *
++ * This program is free software; you can 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 <asm/hardware.h>
++#include <asm/arch/mfp-pxa300.h>
++
++static struct pxa3xx_mfp_addr_map pxa300_mfp_addr_map[] __initdata = {
++
++      MFP_ADDR_X(GPIO0,   GPIO2,   0x00b4),
++      MFP_ADDR_X(GPIO3,   GPIO26,  0x027c),
++      MFP_ADDR_X(GPIO27,  GPIO127, 0x0400),
++      MFP_ADDR_X(GPIO0_2, GPIO6_2, 0x02ec),
++
++      MFP_ADDR(nBE0, 0x0204),
++      MFP_ADDR(nBE1, 0x0208),
++
++      MFP_ADDR(nLUA, 0x0244),
++      MFP_ADDR(nLLA, 0x0254),
++
++      MFP_ADDR(DF_CLE_nOE, 0x0240),
++      MFP_ADDR(DF_nRE_nOE, 0x0200),
++      MFP_ADDR(DF_ALE_nWE, 0x020C),
++      MFP_ADDR(DF_INT_RnB, 0x00C8),
++      MFP_ADDR(DF_nCS0, 0x0248),
++      MFP_ADDR(DF_nCS1, 0x0278),
++      MFP_ADDR(DF_nWE, 0x00CC),
++
++      MFP_ADDR(DF_ADDR0, 0x0210),
++      MFP_ADDR(DF_ADDR1, 0x0214),
++      MFP_ADDR(DF_ADDR2, 0x0218),
++      MFP_ADDR(DF_ADDR3, 0x021C),
++
++      MFP_ADDR(DF_IO0, 0x0220),
++      MFP_ADDR(DF_IO1, 0x0228),
++      MFP_ADDR(DF_IO2, 0x0230),
++      MFP_ADDR(DF_IO3, 0x0238),
++      MFP_ADDR(DF_IO4, 0x0258),
++      MFP_ADDR(DF_IO5, 0x0260),
++      MFP_ADDR(DF_IO6, 0x0268),
++      MFP_ADDR(DF_IO7, 0x0270),
++      MFP_ADDR(DF_IO8, 0x0224),
++      MFP_ADDR(DF_IO9, 0x022C),
++      MFP_ADDR(DF_IO10, 0x0234),
++      MFP_ADDR(DF_IO11, 0x023C),
++      MFP_ADDR(DF_IO12, 0x025C),
++      MFP_ADDR(DF_IO13, 0x0264),
++      MFP_ADDR(DF_IO14, 0x026C),
++      MFP_ADDR(DF_IO15, 0x0274),
++
++      MFP_ADDR_END,
++};
++
++/* override pxa300 MFP register addresses */
++static struct pxa3xx_mfp_addr_map pxa310_mfp_addr_map[] __initdata = {
++      MFP_ADDR_X(GPIO30,  GPIO98,   0x0418),
++      MFP_ADDR_X(GPIO7_2, GPIO12_2, 0x052C),
++
++      MFP_ADDR(ULPI_STP, 0x040C),
++      MFP_ADDR(ULPI_NXT, 0x0410),
++      MFP_ADDR(ULPI_DIR, 0x0414),
++
++      MFP_ADDR_END,
++};
++
++static int __init pxa300_init(void)
++{
++      if (cpu_is_pxa300() || cpu_is_pxa310()) {
++              pxa3xx_init_mfp();
++              pxa3xx_mfp_init_addr(pxa300_mfp_addr_map);
++      }
++
++      if (cpu_is_pxa310())
++              pxa3xx_mfp_init_addr(pxa310_mfp_addr_map);
++
++      return 0;
++}
++
++core_initcall(pxa300_init);
+--- /dev/null
++++ linux-2.6.23/arch/arm/mach-pxa/pxa320.c
+@@ -0,0 +1,88 @@
++/*
++ * linux/arch/arm/mach-pxa/pxa320.c
++ *
++ * Code specific to PXA320
++ *
++ * Copyright (C) 2007 Marvell Internation Ltd.
++ *
++ * 2007-08-21: eric miao <eric.y.miao@gmail.com>
++ *             initial version
++ *
++ * This program is free software; you can 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 <asm/hardware.h>
++#include <asm/arch/mfp.h>
++#include <asm/arch/mfp-pxa320.h>
++
++static struct pxa3xx_mfp_addr_map pxa320_mfp_addr_map[] __initdata = {
++
++      MFP_ADDR_X(GPIO0,  GPIO4,   0x0124),
++      MFP_ADDR_X(GPIO5,  GPIO26,  0x028C),
++      MFP_ADDR_X(GPIO27, GPIO62,  0x0400),
++      MFP_ADDR_X(GPIO63, GPIO73,  0x04B4),
++      MFP_ADDR_X(GPIO74, GPIO98,  0x04F0),
++      MFP_ADDR_X(GPIO99, GPIO127, 0x0600),
++      MFP_ADDR_X(GPIO0_2,  GPIO5_2,   0x0674),
++      MFP_ADDR_X(GPIO6_2,  GPIO13_2,  0x0494),
++      MFP_ADDR_X(GPIO14_2, GPIO17_2, 0x04E0),
++
++      MFP_ADDR(nXCVREN, 0x0138),
++      MFP_ADDR(DF_CLE_nOE, 0x0204),
++      MFP_ADDR(DF_nADV1_ALE, 0x0208),
++      MFP_ADDR(DF_SCLK_S, 0x020C),
++      MFP_ADDR(DF_SCLK_E, 0x0210),
++      MFP_ADDR(nBE0, 0x0214),
++      MFP_ADDR(nBE1, 0x0218),
++      MFP_ADDR(DF_nADV2_ALE, 0x021C),
++      MFP_ADDR(DF_INT_RnB, 0x0220),
++      MFP_ADDR(DF_nCS0, 0x0224),
++      MFP_ADDR(DF_nCS1, 0x0228),
++      MFP_ADDR(DF_nWE, 0x022C),
++      MFP_ADDR(DF_nRE_nOE, 0x0230),
++      MFP_ADDR(nLUA, 0x0234),
++      MFP_ADDR(nLLA, 0x0238),
++      MFP_ADDR(DF_ADDR0, 0x023C),
++      MFP_ADDR(DF_ADDR1, 0x0240),
++      MFP_ADDR(DF_ADDR2, 0x0244),
++      MFP_ADDR(DF_ADDR3, 0x0248),
++      MFP_ADDR(DF_IO0, 0x024C),
++      MFP_ADDR(DF_IO8, 0x0250),
++      MFP_ADDR(DF_IO1, 0x0254),
++      MFP_ADDR(DF_IO9, 0x0258),
++      MFP_ADDR(DF_IO2, 0x025C),
++      MFP_ADDR(DF_IO10, 0x0260),
++      MFP_ADDR(DF_IO3, 0x0264),
++      MFP_ADDR(DF_IO11, 0x0268),
++      MFP_ADDR(DF_IO4, 0x026C),
++      MFP_ADDR(DF_IO12, 0x0270),
++      MFP_ADDR(DF_IO5, 0x0274),
++      MFP_ADDR(DF_IO13, 0x0278),
++      MFP_ADDR(DF_IO6, 0x027C),
++      MFP_ADDR(DF_IO14, 0x0280),
++      MFP_ADDR(DF_IO7, 0x0284),
++      MFP_ADDR(DF_IO15, 0x0288),
++
++      MFP_ADDR_END,
++};
++
++static void __init pxa320_init_mfp(void)
++{
++      pxa3xx_init_mfp();
++      pxa3xx_mfp_init_addr(pxa320_mfp_addr_map);
++}
++
++static int __init pxa320_init(void)
++{
++      if (cpu_is_pxa320())
++              pxa320_init_mfp();
++
++      return 0;
++}
++
++core_initcall(pxa320_init);
+--- /dev/null
++++ linux-2.6.23/arch/arm/mach-pxa/pxa3xx.c
+@@ -0,0 +1,216 @@
++/*
++ * linux/arch/arm/mach-pxa/pxa3xx.c
++ *
++ * code specific to pxa3xx aka Monahans
++ *
++ * Copyright (C) 2006 Marvell International Ltd.
++ *
++ * 2007-09-02: eric miao <eric.y.miao@gmail.com>
++ *             initial version
++ *
++ * This program is free software; you can 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/pm.h>
++#include <linux/platform_device.h>
++#include <linux/irq.h>
++
++#include <asm/hardware.h>
++#include <asm/arch/pxa3xx-regs.h>
++#include <asm/arch/ohci.h>
++#include <asm/arch/pm.h>
++#include <asm/arch/dma.h>
++#include <asm/arch/ssp.h>
++
++#include "generic.h"
++#include "devices.h"
++#include "clock.h"
++
++/* Crystal clock: 13MHz */
++#define BASE_CLK      13000000
++
++/* Ring Oscillator Clock: 60MHz */
++#define RO_CLK                60000000
++
++#define ACCR_D0CS     (1 << 26)
++
++/* crystal frequency to static memory controller multiplier (SMCFS) */
++static unsigned char smcfs_mult[8] = { 6, 0, 8, 0, 0, 16, };
++
++/* crystal frequency to HSIO bus frequency multiplier (HSS) */
++static unsigned char hss_mult[4] = { 8, 12, 16, 0 };
++
++/*
++ * Get the clock frequency as reflected by CCSR and the turbo flag.
++ * We assume these values have been applied via a fcs.
++ * If info is not 0 we also display the current settings.
++ */
++unsigned int pxa3xx_get_clk_frequency_khz(int info)
++{
++      unsigned long acsr, xclkcfg;
++      unsigned int t, xl, xn, hss, ro, XL, XN, CLK, HSS;
++
++      /* Read XCLKCFG register turbo bit */
++      __asm__ __volatile__("mrc\tp14, 0, %0, c6, c0, 0" : "=r"(xclkcfg));
++      t = xclkcfg & 0x1;
++
++      acsr = ACSR;
++
++      xl  = acsr & 0x1f;
++      xn  = (acsr >> 8) & 0x7;
++      hss = (acsr >> 14) & 0x3;
++
++      XL = xl * BASE_CLK;
++      XN = xn * XL;
++
++      ro = acsr & ACCR_D0CS;
++
++      CLK = (ro) ? RO_CLK : ((t) ? XN : XL);
++      HSS = (ro) ? RO_CLK : hss_mult[hss] * BASE_CLK;
++
++      if (info) {
++              pr_info("RO Mode clock: %d.%02dMHz (%sactive)\n",
++                      RO_CLK / 1000000, (RO_CLK % 1000000) / 10000,
++                      (ro) ? "" : "in");
++              pr_info("Run Mode clock: %d.%02dMHz (*%d)\n",
++                      XL / 1000000, (XL % 1000000) / 10000, xl);
++              pr_info("Turbo Mode clock: %d.%02dMHz (*%d, %sactive)\n",
++                      XN / 1000000, (XN % 1000000) / 10000, xn,
++                      (t) ? "" : "in");
++              pr_info("HSIO bus clock: %d.%02dMHz\n",
++                      HSS / 1000000, (HSS % 1000000) / 10000);
++      }
++
++      return CLK;
++}
++
++/*
++ * Return the current static memory controller clock frequency
++ * in units of 10kHz
++ */
++unsigned int pxa3xx_get_memclk_frequency_10khz(void)
++{
++      unsigned long acsr;
++      unsigned int smcfs, clk = 0;
++
++      acsr = ACSR;
++
++      smcfs = (acsr >> 23) & 0x7;
++      clk = (acsr & ACCR_D0CS) ? RO_CLK : smcfs_mult[smcfs] * BASE_CLK;
++
++      return (clk / 10000);
++}
++
++/*
++ * Return the current HSIO bus clock frequency
++ */
++static unsigned long clk_pxa3xx_hsio_getrate(struct clk *clk)
++{
++      unsigned long acsr;
++      unsigned int hss, hsio_clk;
++
++      acsr = ACSR;
++
++      hss = (acsr >> 14) & 0x3;
++      hsio_clk = (acsr & ACCR_D0CS) ? RO_CLK : hss_mult[hss] * BASE_CLK;
++
++      return hsio_clk;
++}
++
++static void clk_pxa3xx_cken_enable(struct clk *clk)
++{
++      unsigned long mask = 1ul << (clk->cken & 0x1f);
++
++      local_irq_disable();
++
++      if (clk->cken < 32)
++              CKENA |= mask;
++      else
++              CKENB |= mask;
++
++      local_irq_enable();
++}
++
++static void clk_pxa3xx_cken_disable(struct clk *clk)
++{
++      unsigned long mask = 1ul << (clk->cken & 0x1f);
++
++      local_irq_disable();
++
++      if (clk->cken < 32)
++              CKENA &= ~mask;
++      else
++              CKENB &= ~mask;
++
++      local_irq_enable();
++}
++
++static const struct clkops clk_pxa3xx_hsio_ops = {
++      .enable         = clk_pxa3xx_cken_enable,
++      .disable        = clk_pxa3xx_cken_disable,
++      .getrate        = clk_pxa3xx_hsio_getrate,
++};
++
++static struct clk pxa3xx_clks[] = {
++      INIT_CK("LCDCLK", LCD,    &clk_pxa3xx_hsio_ops, &pxa_device_fb.dev),
++      INIT_CK("CAMCLK", CAMERA, &clk_pxa3xx_hsio_ops, NULL),
++
++      INIT_CKEN("UARTCLK", FFUART, 14857000, 1, &pxa_device_ffuart.dev),
++      INIT_CKEN("UARTCLK", BTUART, 14857000, 1, &pxa_device_btuart.dev),
++      INIT_CKEN("UARTCLK", STUART, 14857000, 1, NULL),
++
++      INIT_CKEN("I2CCLK",  I2C,  32842000, 0, &pxa_device_i2c.dev),
++      INIT_CKEN("UDCCLK",  UDC,  48000000, 5, &pxa_device_udc.dev),
++};
++
++void __init pxa3xx_init_irq(void)
++{
++      /* enable CP6 access */
++      u32 value;
++      __asm__ __volatile__("mrc p15, 0, %0, c15, c1, 0\n": "=r"(value));
++      value |= (1 << 6);
++      __asm__ __volatile__("mcr p15, 0, %0, c15, c1, 0\n": :"r"(value));
++
++      pxa_init_irq_low();
++      pxa_init_irq_high();
++      pxa_init_irq_gpio(128);
++}
++
++/*
++ * device registration specific to PXA3xx.
++ */
++
++static struct platform_device *devices[] __initdata = {
++      &pxa_device_mci,
++      &pxa_device_udc,
++      &pxa_device_fb,
++      &pxa_device_ffuart,
++      &pxa_device_btuart,
++      &pxa_device_stuart,
++      &pxa_device_i2c,
++      &pxa_device_i2s,
++      &pxa_device_ficp,
++      &pxa_device_rtc,
++};
++
++static int __init pxa3xx_init(void)
++{
++      int ret = 0;
++
++      if (cpu_is_pxa3xx()) {
++              clks_register(pxa3xx_clks, ARRAY_SIZE(pxa3xx_clks));
++
++              if ((ret = pxa_init_dma(32)))
++                      return ret;
++
++              return platform_add_devices(devices, ARRAY_SIZE(devices));
++      }
++      return 0;
++}
++
++subsys_initcall(pxa3xx_init);
+--- linux-2.6.23.orig/arch/arm/mach-pxa/time.c
++++ linux-2.6.23/arch/arm/mach-pxa/time.c
+@@ -16,10 +16,48 @@
+ #include <linux/init.h>
+ #include <linux/interrupt.h>
+ #include <linux/clockchips.h>
++#include <linux/sched.h>
++#include <asm/div64.h>
++#include <asm/cnt32_to_63.h>
+ #include <asm/mach/irq.h>
+ #include <asm/mach/time.h>
+ #include <asm/arch/pxa-regs.h>
++#include <asm/mach-types.h>
++
++/*
++ * This is PXA's sched_clock implementation. This has a resolution
++ * of at least 308 ns and a maximum value of 208 days.
++ *
++ * The return value is guaranteed to be monotonic in that range as
++ * long as there is always less than 582 seconds between successive
++ * calls to sched_clock() which should always be the case in practice.
++ */
++
++#define OSCR2NS_SCALE_FACTOR 10
++
++static unsigned long oscr2ns_scale;
++
++static void __init set_oscr2ns_scale(unsigned long oscr_rate)
++{
++      unsigned long long v = 1000000000ULL << OSCR2NS_SCALE_FACTOR;
++      do_div(v, oscr_rate);
++      oscr2ns_scale = v;
++      /*
++       * We want an even value to automatically clear the top bit
++       * returned by cnt32_to_63() without an additional run time
++       * instruction. So if the LSB is 1 then round it up.
++       */
++      if (oscr2ns_scale & 1)
++              oscr2ns_scale++;
++}
++
++unsigned long long sched_clock(void)
++{
++      unsigned long long v = cnt32_to_63(OSCR);
++      return (v * oscr2ns_scale) >> OSCR2NS_SCALE_FACTOR;
++}
++
+ static irqreturn_t
+ pxa_ost0_interrupt(int irq, void *dev_id)
+@@ -149,18 +187,29 @@
+ static void __init pxa_timer_init(void)
+ {
++      unsigned long clock_tick_rate;
++
+       OIER = 0;
+       OSSR = OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3;
++      if (cpu_is_pxa21x() || cpu_is_pxa25x())
++              clock_tick_rate = 3686400;
++      else if (machine_is_mainstone())
++              clock_tick_rate = 3249600;
++      else
++              clock_tick_rate = 3250000;
++
++      set_oscr2ns_scale(clock_tick_rate);
++
+       ckevt_pxa_osmr0.mult =
+-              div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, ckevt_pxa_osmr0.shift);
++              div_sc(clock_tick_rate, NSEC_PER_SEC, ckevt_pxa_osmr0.shift);
+       ckevt_pxa_osmr0.max_delta_ns =
+               clockevent_delta2ns(0x7fffffff, &ckevt_pxa_osmr0);
+       ckevt_pxa_osmr0.min_delta_ns =
+               clockevent_delta2ns(MIN_OSCR_DELTA, &ckevt_pxa_osmr0) + 1;
+       cksrc_pxa_oscr0.mult =
+-              clocksource_hz2mult(CLOCK_TICK_RATE, cksrc_pxa_oscr0.shift);
++              clocksource_hz2mult(clock_tick_rate, cksrc_pxa_oscr0.shift);
+       setup_irq(IRQ_OST0, &pxa_ost0_irq);
+--- /dev/null
++++ linux-2.6.23/arch/arm/mach-pxa/zylonite.c
+@@ -0,0 +1,184 @@
++/*
++ * linux/arch/arm/mach-pxa/zylonite.c
++ *
++ * Support for the PXA3xx Development Platform (aka Zylonite)
++ *
++ * Copyright (C) 2006 Marvell International Ltd.
++ *
++ * 2007-09-04: eric miao <eric.y.miao@gmail.com>
++ *             rewrite to align with latest kernel
++ *
++ * This program is free software; you can 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/interrupt.h>
++#include <linux/init.h>
++#include <linux/platform_device.h>
++
++#include <asm/mach-types.h>
++#include <asm/mach/arch.h>
++#include <asm/hardware.h>
++#include <asm/arch/gpio.h>
++#include <asm/arch/pxafb.h>
++#include <asm/arch/zylonite.h>
++
++#include "generic.h"
++
++int gpio_backlight;
++int gpio_eth_irq;
++
++int lcd_id;
++int lcd_orientation;
++
++static struct resource smc91x_resources[] = {
++      [0] = {
++              .start  = ZYLONITE_ETH_PHYS + 0x300,
++              .end    = ZYLONITE_ETH_PHYS + 0xfffff,
++              .flags  = IORESOURCE_MEM,
++      },
++      [1] = {
++              .start  = -1,   /* for run-time assignment */
++              .end    = -1,
++              .flags  = IORESOURCE_IRQ,
++      }
++};
++
++static struct platform_device smc91x_device = {
++      .name           = "smc91x",
++      .id             = 0,
++      .num_resources  = ARRAY_SIZE(smc91x_resources),
++      .resource       = smc91x_resources,
++};
++
++#if defined(CONFIG_FB_PXA) || (CONFIG_FB_PXA_MODULES)
++static void zylonite_backlight_power(int on)
++{
++      gpio_set_value(gpio_backlight, on);
++}
++
++static struct pxafb_mode_info toshiba_ltm035a776c_mode = {
++      .pixclock               = 110000,
++      .xres                   = 240,
++      .yres                   = 320,
++      .bpp                    = 16,
++      .hsync_len              = 4,
++      .left_margin            = 6,
++      .right_margin           = 4,
++      .vsync_len              = 2,
++      .upper_margin           = 2,
++      .lower_margin           = 3,
++      .sync                   = FB_SYNC_VERT_HIGH_ACT,
++};
++
++static struct pxafb_mode_info toshiba_ltm04c380k_mode = {
++      .pixclock               = 50000,
++      .xres                   = 640,
++      .yres                   = 480,
++      .bpp                    = 16,
++      .hsync_len              = 1,
++      .left_margin            = 0x9f,
++      .right_margin           = 1,
++      .vsync_len              = 44,
++      .upper_margin           = 0,
++      .lower_margin           = 0,
++      .sync                   = FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
++};
++
++static struct pxafb_mach_info zylonite_toshiba_lcd_info = {
++      .num_modes              = 1,
++      .lccr0                  = LCCR0_Act,
++      .lccr3                  = LCCR3_PCP,
++      .pxafb_backlight_power  = zylonite_backlight_power,
++};
++
++static struct pxafb_mode_info sharp_ls037_modes[] = {
++      [0] = {
++              .pixclock       = 158000,
++              .xres           = 240,
++              .yres           = 320,
++              .bpp            = 16,
++              .hsync_len      = 4,
++              .left_margin    = 39,
++              .right_margin   = 39,
++              .vsync_len      = 1,
++              .upper_margin   = 2,
++              .lower_margin   = 3,
++              .sync           = 0,
++      },
++      [1] = {
++              .pixclock       = 39700,
++              .xres           = 480,
++              .yres           = 640,
++              .bpp            = 16,
++              .hsync_len      = 8,
++              .left_margin    = 81,
++              .right_margin   = 81,
++              .vsync_len      = 1,
++              .upper_margin   = 2,
++              .lower_margin   = 7,
++              .sync           = 0,
++      },
++};
++
++static struct pxafb_mach_info zylonite_sharp_lcd_info = {
++      .modes                  = sharp_ls037_modes,
++      .num_modes              = 2,
++      .lccr0                  = LCCR0_Act,
++      .lccr3                  = LCCR3_PCP | LCCR3_HSP | LCCR3_VSP,
++      .pxafb_backlight_power  = zylonite_backlight_power,
++};
++
++static void __init zylonite_init_lcd(void)
++{
++      /* backlight GPIO: output, default on */
++      gpio_direction_output(gpio_backlight, 1);
++
++      if (lcd_id & 0x20) {
++              set_pxa_fb_info(&zylonite_sharp_lcd_info);
++              return;
++      }
++
++      /* legacy LCD panels, it would be handy here if LCD panel type can
++       * be decided at run-time
++       */
++      if (1)
++              zylonite_toshiba_lcd_info.modes = &toshiba_ltm035a776c_mode;
++      else
++              zylonite_toshiba_lcd_info.modes = &toshiba_ltm04c380k_mode;
++
++      set_pxa_fb_info(&zylonite_toshiba_lcd_info);
++}
++#else
++static inline void zylonite_init_lcd(void) {}
++#endif
++
++static void __init zylonite_init(void)
++{
++      /* board-processor specific initialization */
++      zylonite_pxa300_init();
++      zylonite_pxa320_init();
++
++      /*
++       * Note: We depend that the bootloader set
++       * the correct value to MSC register for SMC91x.
++       */
++      smc91x_resources[1].start = gpio_to_irq(gpio_eth_irq);
++      smc91x_resources[1].end   = gpio_to_irq(gpio_eth_irq);
++      platform_device_register(&smc91x_device);
++
++      zylonite_init_lcd();
++}
++
++MACHINE_START(ZYLONITE, "PXA3xx Platform Development Kit (aka Zylonite)")
++      .phys_io        = 0x40000000,
++      .boot_params    = 0xa0000100,
++      .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
++      .map_io         = pxa_map_io,
++      .init_irq       = pxa3xx_init_irq,
++      .timer          = &pxa_timer,
++      .init_machine   = zylonite_init,
++MACHINE_END
+--- /dev/null
++++ linux-2.6.23/arch/arm/mach-pxa/zylonite_pxa300.c
+@@ -0,0 +1,188 @@
++/*
++ * linux/arch/arm/mach-pxa/zylonite_pxa300.c
++ *
++ * PXA300/PXA310 specific support code for the
++ * PXA3xx Development Platform (aka Zylonite)
++ *
++ * Copyright (C) 2007 Marvell Internation Ltd.
++ * 2007-08-21: eric miao <eric.y.miao@gmail.com>
++ *             initial version
++ *
++ * This program is free software; you can 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 <asm/gpio.h>
++#include <asm/arch/mfp-pxa300.h>
++#include <asm/arch/zylonite.h>
++
++#define ARRAY_AND_SIZE(x)     (x), ARRAY_SIZE(x)
++
++/* PXA300/PXA310 common configurations */
++static mfp_cfg_t common_mfp_cfg[] __initdata = {
++      /* LCD */
++      GPIO54_LCD_LDD_0,
++      GPIO55_LCD_LDD_1,
++      GPIO56_LCD_LDD_2,
++      GPIO57_LCD_LDD_3,
++      GPIO58_LCD_LDD_4,
++      GPIO59_LCD_LDD_5,
++      GPIO60_LCD_LDD_6,
++      GPIO61_LCD_LDD_7,
++      GPIO62_LCD_LDD_8,
++      GPIO63_LCD_LDD_9,
++      GPIO64_LCD_LDD_10,
++      GPIO65_LCD_LDD_11,
++      GPIO66_LCD_LDD_12,
++      GPIO67_LCD_LDD_13,
++      GPIO68_LCD_LDD_14,
++      GPIO69_LCD_LDD_15,
++      GPIO70_LCD_LDD_16,
++      GPIO71_LCD_LDD_17,
++      GPIO72_LCD_FCLK,
++      GPIO73_LCD_LCLK,
++      GPIO74_LCD_PCLK,
++      GPIO75_LCD_BIAS,
++      GPIO76_LCD_VSYNC,
++      GPIO127_LCD_CS_N,
++
++      /* BTUART */
++      GPIO111_UART2_RTS,
++      GPIO112_UART2_RXD,
++      GPIO113_UART2_TXD,
++      GPIO114_UART2_CTS,
++
++      /* STUART */
++      GPIO109_UART3_TXD,
++      GPIO110_UART3_RXD,
++
++      /* AC97 */
++      GPIO23_AC97_nACRESET,
++      GPIO24_AC97_SYSCLK,
++      GPIO29_AC97_BITCLK,
++      GPIO25_AC97_SDATA_IN_0,
++      GPIO27_AC97_SDATA_OUT,
++      GPIO28_AC97_SYNC,
++
++      /* Keypad */
++      GPIO107_KP_DKIN_0,
++      GPIO108_KP_DKIN_1,
++      GPIO115_KP_MKIN_0,
++      GPIO116_KP_MKIN_1,
++      GPIO117_KP_MKIN_2,
++      GPIO118_KP_MKIN_3,
++      GPIO119_KP_MKIN_4,
++      GPIO120_KP_MKIN_5,
++      GPIO2_2_KP_MKIN_6,
++      GPIO3_2_KP_MKIN_7,
++      GPIO121_KP_MKOUT_0,
++      GPIO122_KP_MKOUT_1,
++      GPIO123_KP_MKOUT_2,
++      GPIO124_KP_MKOUT_3,
++      GPIO125_KP_MKOUT_4,
++      GPIO4_2_KP_MKOUT_5,
++      GPIO5_2_KP_MKOUT_6,
++      GPIO6_2_KP_MKOUT_7,
++};
++
++static mfp_cfg_t pxa300_mfp_cfg[] __initdata = {
++      /* FFUART */
++      GPIO30_UART1_RXD,
++      GPIO31_UART1_TXD,
++      GPIO32_UART1_CTS,
++      GPIO37_UART1_RTS,
++      GPIO33_UART1_DCD,
++      GPIO34_UART1_DSR,
++      GPIO35_UART1_RI,
++      GPIO36_UART1_DTR,
++
++      /* Ethernet */
++      GPIO2_nCS3,
++      GPIO99_GPIO,
++};
++
++static mfp_cfg_t pxa310_mfp_cfg[] __initdata = {
++      /* FFUART */
++      GPIO99_UART1_RXD,
++      GPIO100_UART1_TXD,
++      GPIO101_UART1_CTS,
++      GPIO106_UART1_RTS,
++
++      /* Ethernet */
++      GPIO2_nCS3,
++      GPIO102_GPIO,
++};
++
++#define NUM_LCD_DETECT_PINS   7
++
++static int lcd_detect_pins[] __initdata = {
++      MFP_PIN_GPIO71, /* LCD_LDD_17 - ORIENT */
++      MFP_PIN_GPIO70, /* LCD_LDD_16 - LCDID[5] */
++      MFP_PIN_GPIO75, /* LCD_BIAS   - LCDID[4] */
++      MFP_PIN_GPIO73, /* LCD_LCLK   - LCDID[3] */
++      MFP_PIN_GPIO72, /* LCD_FCLK   - LCDID[2] */
++      MFP_PIN_GPIO127,/* LCD_CS_N   - LCDID[1] */
++      MFP_PIN_GPIO76, /* LCD_VSYNC  - LCDID[0] */
++};
++
++static void __init zylonite_detect_lcd_panel(void)
++{
++      unsigned long mfpr_save[NUM_LCD_DETECT_PINS];
++      int i, gpio, id = 0;
++
++      /* save the original MFP settings of these pins and configure
++       * them as GPIO Input, DS01X, Pull Neither, Edge Clear
++       */
++      for (i = 0; i < NUM_LCD_DETECT_PINS; i++) {
++              mfpr_save[i] = pxa3xx_mfp_read(lcd_detect_pins[i]);
++              pxa3xx_mfp_write(lcd_detect_pins[i], 0x8440);
++      }
++
++      for (i = 0; i < NUM_LCD_DETECT_PINS; i++) {
++              id = id << 1;
++              gpio = mfp_to_gpio(lcd_detect_pins[i]);
++              gpio_direction_input(gpio);
++
++              if (gpio_get_value(gpio))
++                      id = id | 0x1;
++      }
++
++      /* lcd id, flush out bit 1 */
++      lcd_id = id & 0x3d;
++
++      /* lcd orientation, portrait or landscape */
++      lcd_orientation = (id >> 6) & 0x1;
++
++      /* restore the original MFP settings */
++      for (i = 0; i < NUM_LCD_DETECT_PINS; i++)
++              pxa3xx_mfp_write(lcd_detect_pins[i], mfpr_save[i]);
++}
++
++void __init zylonite_pxa300_init(void)
++{
++      if (cpu_is_pxa300() || cpu_is_pxa310()) {
++              /* initialize MFP */
++              pxa3xx_mfp_config(ARRAY_AND_SIZE(common_mfp_cfg));
++
++              /* detect LCD panel */
++              zylonite_detect_lcd_panel();
++
++              /* GPIO pin assignment */
++              gpio_backlight = mfp_to_gpio(MFP_PIN_GPIO20);
++      }
++
++      if (cpu_is_pxa300()) {
++              pxa3xx_mfp_config(ARRAY_AND_SIZE(pxa300_mfp_cfg));
++              gpio_eth_irq = mfp_to_gpio(MFP_PIN_GPIO99);
++      }
++
++      if (cpu_is_pxa310()) {
++              pxa3xx_mfp_config(ARRAY_AND_SIZE(pxa310_mfp_cfg));
++              gpio_eth_irq = mfp_to_gpio(MFP_PIN_GPIO102);
++      }
++}
+--- /dev/null
++++ linux-2.6.23/arch/arm/mach-pxa/zylonite_pxa320.c
+@@ -0,0 +1,173 @@
++/*
++ * linux/arch/arm/mach-pxa/zylonite_pxa320.c
++ *
++ * PXA320 specific support code for the
++ * PXA3xx Development Platform (aka Zylonite)
++ *
++ * Copyright (C) 2007 Marvell Internation Ltd.
++ * 2007-08-21: eric miao <eric.y.miao@gmail.com>
++ *             initial version
++ *
++ * This program is free software; you can 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 <asm/arch/gpio.h>
++#include <asm/arch/mfp-pxa320.h>
++#include <asm/arch/zylonite.h>
++
++#define ARRAY_AND_SIZE(x)     (x), ARRAY_SIZE(x)
++
++static mfp_cfg_t mfp_cfg[] __initdata = {
++      /* LCD */
++      GPIO6_2_LCD_LDD_0,
++      GPIO7_2_LCD_LDD_1,
++      GPIO8_2_LCD_LDD_2,
++      GPIO9_2_LCD_LDD_3,
++      GPIO10_2_LCD_LDD_4,
++      GPIO11_2_LCD_LDD_5,
++      GPIO12_2_LCD_LDD_6,
++      GPIO13_2_LCD_LDD_7,
++      GPIO63_LCD_LDD_8,
++      GPIO64_LCD_LDD_9,
++      GPIO65_LCD_LDD_10,
++      GPIO66_LCD_LDD_11,
++      GPIO67_LCD_LDD_12,
++      GPIO68_LCD_LDD_13,
++      GPIO69_LCD_LDD_14,
++      GPIO70_LCD_LDD_15,
++      GPIO71_LCD_LDD_16,
++      GPIO72_LCD_LDD_17,
++      GPIO73_LCD_CS_N,
++      GPIO74_LCD_VSYNC,
++      GPIO14_2_LCD_FCLK,
++      GPIO15_2_LCD_LCLK,
++      GPIO16_2_LCD_PCLK,
++      GPIO17_2_LCD_BIAS,
++
++      /* FFUART */
++      GPIO41_UART1_RXD,
++      GPIO42_UART1_TXD,
++      GPIO43_UART1_CTS,
++      GPIO44_UART1_DCD,
++      GPIO45_UART1_DSR,
++      GPIO46_UART1_RI,
++      GPIO47_UART1_DTR,
++      GPIO48_UART1_RTS,
++
++      /* AC97 */
++      GPIO34_AC97_SYSCLK,
++      GPIO35_AC97_SDATA_IN_0,
++      GPIO37_AC97_SDATA_OUT,
++      GPIO38_AC97_SYNC,
++      GPIO39_AC97_BITCLK,
++      GPIO40_AC97_nACRESET,
++
++      /* I2C */
++      GPIO32_I2C_SCL,
++      GPIO33_I2C_SDA,
++
++      /* Keypad */
++      GPIO105_KP_DKIN_0,
++      GPIO106_KP_DKIN_1,
++      GPIO113_KP_MKIN_0,
++      GPIO114_KP_MKIN_1,
++      GPIO115_KP_MKIN_2,
++      GPIO116_KP_MKIN_3,
++      GPIO117_KP_MKIN_4,
++      GPIO118_KP_MKIN_5,
++      GPIO119_KP_MKIN_6,
++      GPIO120_KP_MKIN_7,
++      GPIO121_KP_MKOUT_0,
++      GPIO122_KP_MKOUT_1,
++      GPIO123_KP_MKOUT_2,
++      GPIO124_KP_MKOUT_3,
++      GPIO125_KP_MKOUT_4,
++      GPIO126_KP_MKOUT_5,
++      GPIO127_KP_MKOUT_6,
++      GPIO5_2_KP_MKOUT_7,
++
++      /* Ethernet */
++      GPIO4_nCS3,
++      GPIO90_GPIO,
++};
++
++#define NUM_LCD_DETECT_PINS   7
++
++static int lcd_detect_pins[] __initdata = {
++      MFP_PIN_GPIO72,   /* LCD_LDD_17 - ORIENT */
++      MFP_PIN_GPIO71,   /* LCD_LDD_16 - LCDID[5] */
++      MFP_PIN_GPIO17_2, /* LCD_BIAS   - LCDID[4] */
++      MFP_PIN_GPIO15_2, /* LCD_LCLK   - LCDID[3] */
++      MFP_PIN_GPIO14_2, /* LCD_FCLK   - LCDID[2] */
++      MFP_PIN_GPIO73,   /* LCD_CS_N   - LCDID[1] */
++      MFP_PIN_GPIO74,   /* LCD_VSYNC  - LCDID[0] */
++      /*
++       * set the MFP_PIN_GPIO 14/15/17 to alternate function other than
++       * GPIO to avoid input level confliction with 14_2, 15_2, 17_2
++       */
++      MFP_PIN_GPIO14,
++      MFP_PIN_GPIO15,
++      MFP_PIN_GPIO17,
++};
++
++static int lcd_detect_mfpr[] __initdata = {
++      /* AF0, DS 1X, Pull Neither, Edge Clear */
++      0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440,
++      0xc442, /* Backlight, Pull-Up, AF2 */
++      0x8445, /* AF5 */
++      0x8445, /* AF5 */
++};
++
++static void __init zylonite_detect_lcd_panel(void)
++{
++      unsigned long mfpr_save[ARRAY_SIZE(lcd_detect_pins)];
++      int i, gpio, id = 0;
++
++      /* save the original MFP settings of these pins and configure them
++       * as GPIO Input, DS01X, Pull Neither, Edge Clear
++       */
++      for (i = 0; i < ARRAY_SIZE(lcd_detect_pins); i++) {
++              mfpr_save[i] = pxa3xx_mfp_read(lcd_detect_pins[i]);
++              pxa3xx_mfp_write(lcd_detect_pins[i], lcd_detect_mfpr[i]);
++      }
++
++      for (i = 0; i < NUM_LCD_DETECT_PINS; i++) {
++              id = id << 1;
++              gpio = mfp_to_gpio(lcd_detect_pins[i]);
++              gpio_direction_input(gpio);
++
++              if (gpio_get_value(gpio))
++                      id = id | 0x1;
++      }
++
++      /* lcd id, flush out bit 1 */
++      lcd_id = id & 0x3d;
++
++      /* lcd orientation, portrait or landscape */
++      lcd_orientation = (id >> 6) & 0x1;
++
++      /* restore the original MFP settings */
++      for (i = 0; i < ARRAY_SIZE(lcd_detect_pins); i++)
++              pxa3xx_mfp_write(lcd_detect_pins[i], mfpr_save[i]);
++}
++
++void __init zylonite_pxa320_init(void)
++{
++      if (cpu_is_pxa320()) {
++              /* initialize MFP */
++              pxa3xx_mfp_config(ARRAY_AND_SIZE(mfp_cfg));
++
++              /* detect LCD panel */
++              zylonite_detect_lcd_panel();
++
++              /* GPIO pin assignment */
++              gpio_backlight  = mfp_to_gpio(MFP_PIN_GPIO14);
++              gpio_eth_irq    = mfp_to_gpio(MFP_PIN_GPIO9);
++      }
++}
+--- linux-2.6.23.orig/arch/arm/mm/Kconfig
++++ linux-2.6.23/arch/arm/mm/Kconfig
+@@ -322,7 +322,7 @@
+ # XScale
+ config CPU_XSCALE
+       bool
+-      depends on ARCH_IOP32X || ARCH_IOP33X || ARCH_PXA || ARCH_IXP4XX || ARCH_IXP2000
++      depends on ARCH_IOP32X || ARCH_IOP33X || PXA25x || PXA27x || ARCH_IXP4XX || ARCH_IXP2000
+       default y
+       select CPU_32v5
+       select CPU_ABRT_EV5T
+@@ -333,7 +333,7 @@
+ # XScale Core Version 3
+ config CPU_XSC3
+       bool
+-      depends on ARCH_IXP23XX || ARCH_IOP13XX
++      depends on ARCH_IXP23XX || ARCH_IOP13XX || PXA3xx
+       default y
+       select CPU_32v5
+       select CPU_ABRT_EV5T
+--- linux-2.6.23.orig/drivers/i2c/busses/i2c-pxa.c
++++ linux-2.6.23/drivers/i2c/busses/i2c-pxa.c
+@@ -31,6 +31,8 @@
+ #include <linux/interrupt.h>
+ #include <linux/i2c-pxa.h>
+ #include <linux/platform_device.h>
++#include <linux/err.h>
++#include <linux/clk.h>
+ #include <asm/hardware.h>
+ #include <asm/irq.h>
+@@ -48,6 +50,7 @@
+       unsigned int            slave_addr;
+       struct i2c_adapter      adap;
++      struct clk              *clk;
+ #ifdef CONFIG_I2C_PXA_SLAVE
+       struct i2c_slave_client *slave;
+ #endif
+@@ -869,6 +872,12 @@
+       sprintf(i2c->adap.name, "pxa_i2c-i2c.%u", dev->id);
++      i2c->clk = clk_get(&dev->dev, "I2CCLK");
++      if (IS_ERR(i2c->clk)) {
++              ret = PTR_ERR(i2c->clk);
++              goto eclk;
++      }
++
+       i2c->reg_base = ioremap(res->start, res_len(res));
+       if (!i2c->reg_base) {
+               ret = -EIO;
+@@ -889,22 +898,19 @@
+       }
+ #endif
++      clk_enable(i2c->clk);
++#ifdef CONFIG_PXA27x
+       switch (dev->id) {
+       case 0:
+-#ifdef CONFIG_PXA27x
+               pxa_gpio_mode(GPIO117_I2CSCL_MD);
+               pxa_gpio_mode(GPIO118_I2CSDA_MD);
+-#endif
+-              pxa_set_cken(CKEN_I2C, 1);
+               break;
+-#ifdef CONFIG_PXA27x
+       case 1:
+               local_irq_disable();
+               PCFR |= PCFR_PI2CEN;
+               local_irq_enable();
+-              pxa_set_cken(CKEN_PWRI2C, 1);
+-#endif
+       }
++#endif
+       ret = request_irq(irq, i2c_pxa_handler, IRQF_DISABLED,
+                         i2c->adap.name, i2c);
+@@ -948,19 +954,18 @@
+ eadapt:
+       free_irq(irq, i2c);
+ ereqirq:
+-      switch (dev->id) {
+-      case 0:
+-              pxa_set_cken(CKEN_I2C, 0);
+-              break;
++      clk_disable(i2c->clk);
++
+ #ifdef CONFIG_PXA27x
+-      case 1:
+-              pxa_set_cken(CKEN_PWRI2C, 0);
++      if (dev->id == 1) {
+               local_irq_disable();
+               PCFR &= ~PCFR_PI2CEN;
+               local_irq_enable();
+-#endif
+       }
++#endif
+ eremap:
++      clk_put(i2c->clk);
++eclk:
+       kfree(i2c);
+ emalloc:
+       release_mem_region(res->start, res_len(res));
+@@ -975,18 +980,18 @@
+       i2c_del_adapter(&i2c->adap);
+       free_irq(i2c->irq, i2c);
+-      switch (dev->id) {
+-      case 0:
+-              pxa_set_cken(CKEN_I2C, 0);
+-              break;
++
++      clk_disable(i2c->clk);
++      clk_put(i2c->clk);
++
+ #ifdef CONFIG_PXA27x
+-      case 1:
+-              pxa_set_cken(CKEN_PWRI2C, 0);
++      if (dev->id == 1) {
+               local_irq_disable();
+               PCFR &= ~PCFR_PI2CEN;
+               local_irq_enable();
+-#endif
+       }
++#endif
++
+       release_mem_region(i2c->iobase, i2c->iosize);
+       kfree(i2c);
+--- linux-2.6.23.orig/drivers/input/keyboard/pxa27x_keyboard.c
++++ linux-2.6.23/drivers/input/keyboard/pxa27x_keyboard.c
+@@ -23,6 +23,8 @@
+ #include <linux/input.h>
+ #include <linux/device.h>
+ #include <linux/platform_device.h>
++#include <linux/clk.h>
++#include <linux/err.h>
+ #include <asm/mach-types.h>
+ #include <asm/mach/arch.h>
+@@ -40,6 +42,8 @@
+                                col/2 == 2 ? KPASMKP2 : KPASMKP3)
+ #define KPASMKPx_MKC(row, col)        (1 << (row + 16 * (col % 2)))
++static struct clk *pxakbd_clk;
++
+ static irqreturn_t pxakbd_irq_handler(int irq, void *dev_id)
+ {
+       struct platform_device *pdev = dev_id;
+@@ -104,7 +108,7 @@
+       KPREC = 0x7F;
+       /* Enable unit clock */
+-      pxa_set_cken(CKEN_KEYPAD, 1);
++      clk_enable(pxakbd_clk);
+       return 0;
+ }
+@@ -112,7 +116,7 @@
+ static void pxakbd_close(struct input_dev *dev)
+ {
+       /* Disable clock unit */
+-      pxa_set_cken(CKEN_KEYPAD, 0);
++      clk_disable(pxakbd_clk);
+ }
+ #ifdef CONFIG_PM
+@@ -140,7 +144,8 @@
+               KPREC = pdata->reg_kprec;
+               /* Enable unit clock */
+-              pxa_set_cken(CKEN_KEYPAD, 1);
++              clk_disable(pxakbd_clk);
++              clk_enable(pxakbd_clk);
+       }
+       mutex_unlock(&input_dev->mutex);
+@@ -158,11 +163,18 @@
+       struct input_dev *input_dev;
+       int i, row, col, error;
++      pxakbd_clk = clk_get(&pdev->dev, "KBDCLK");
++      if (IS_ERR(pxakbd_clk)) {
++              error = PTR_ERR(pxakbd_clk);
++              goto err_clk;
++      }
++
+       /* Create and register the input driver. */
+       input_dev = input_allocate_device();
+       if (!input_dev) {
+               printk(KERN_ERR "Cannot request keypad device\n");
+-              return -ENOMEM;
++              error = -ENOMEM;
++              goto err_alloc;
+       }
+       input_dev->name = DRIVER_NAME;
+@@ -185,7 +197,6 @@
+                           DRIVER_NAME, pdev);
+       if (error) {
+               printk(KERN_ERR "Cannot request keypad IRQ\n");
+-              pxa_set_cken(CKEN_KEYPAD, 0);
+               goto err_free_dev;
+       }
+@@ -217,6 +228,9 @@
+       free_irq(IRQ_KEYPAD, pdev);
+  err_free_dev:
+       input_free_device(input_dev);
++ err_alloc:
++      clk_put(pxakbd_clk);
++ err_clk:
+       return error;
+ }
+@@ -226,6 +240,7 @@
+       input_unregister_device(input_dev);
+       free_irq(IRQ_KEYPAD, pdev);
++      clk_put(pxakbd_clk);
+       platform_set_drvdata(pdev, NULL);
+       return 0;
+--- linux-2.6.23.orig/drivers/mmc/host/pxamci.c
++++ linux-2.6.23/drivers/mmc/host/pxamci.c
+@@ -23,6 +23,8 @@
+ #include <linux/delay.h>
+ #include <linux/interrupt.h>
+ #include <linux/dma-mapping.h>
++#include <linux/clk.h>
++#include <linux/err.h>
+ #include <linux/mmc/host.h>
+ #include <asm/dma.h>
+@@ -44,6 +46,8 @@
+       spinlock_t              lock;
+       struct resource         *res;
+       void __iomem            *base;
++      struct clk              *clk;
++      unsigned long           clkrate;
+       int                     irq;
+       int                     dma;
+       unsigned int            clkrt;
+@@ -119,7 +123,7 @@
+       writel(nob, host->base + MMC_NOB);
+       writel(data->blksz, host->base + MMC_BLKLEN);
+-      clks = (unsigned long long)data->timeout_ns * CLOCKRATE;
++      clks = (unsigned long long)data->timeout_ns * host->clkrate;
+       do_div(clks, 1000000000UL);
+       timeout = (unsigned int)clks + (data->timeout_clks << host->clkrt);
+       writel((timeout + 255) / 256, host->base + MMC_RDTO);
+@@ -358,18 +362,25 @@
+       struct pxamci_host *host = mmc_priv(mmc);
+       if (ios->clock) {
+-              unsigned int clk = CLOCKRATE / ios->clock;
+-              if (CLOCKRATE / clk > ios->clock)
++              unsigned long rate = host->clkrate;
++              unsigned int clk = rate / ios->clock;
++
++              /*
++               * clk might result in a lower divisor than we
++               * desire.  check for that condition and adjust
++               * as appropriate.
++               */
++              if (rate / clk > ios->clock)
+                       clk <<= 1;
+               host->clkrt = fls(clk) - 1;
+-              pxa_set_cken(CKEN_MMC, 1);
++              clk_enable(host->clk);
+               /*
+                * we write clkrt on the next command
+                */
+       } else {
+               pxamci_stop_clock(host);
+-              pxa_set_cken(CKEN_MMC, 0);
++              clk_disable(host->clk);
+       }
+       if (host->power_mode != ios->power_mode) {
+@@ -429,8 +440,6 @@
+       }
+       mmc->ops = &pxamci_ops;
+-      mmc->f_min = CLOCKRATE_MIN;
+-      mmc->f_max = CLOCKRATE_MAX;
+       /*
+        * We can do SG-DMA, but we don't because we never know how much
+@@ -457,6 +466,22 @@
+       host->mmc = mmc;
+       host->dma = -1;
+       host->pdata = pdev->dev.platform_data;
++
++      host->clk = clk_get(&pdev->dev, "MMCCLK");
++      if (IS_ERR(host->clk)) {
++              ret = PTR_ERR(host->clk);
++              host->clk = NULL;
++              goto out;
++      }
++
++      host->clkrate = clk_get_rate(host->clk);
++
++      /*
++       * Calculate minimum clock rate, rounding up.
++       */
++      mmc->f_min = (host->clkrate + 63) / 64;
++      mmc->f_max = host->clkrate;
++
+       mmc->ocr_avail = host->pdata ?
+                        host->pdata->ocr_mask :
+                        MMC_VDD_32_33|MMC_VDD_33_34;
+@@ -515,6 +540,8 @@
+                       iounmap(host->base);
+               if (host->sg_cpu)
+                       dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma);
++              if (host->clk)
++                      clk_put(host->clk);
+       }
+       if (mmc)
+               mmc_free_host(mmc);
+@@ -549,6 +576,8 @@
+               iounmap(host->base);
+               dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma);
++              clk_put(host->clk);
++
+               release_resource(host->res);
+               mmc_free_host(mmc);
+--- linux-2.6.23.orig/drivers/mmc/host/pxamci.h
++++ linux-2.6.23/drivers/mmc/host/pxamci.h
+@@ -86,17 +86,3 @@
+ #define MMC_RXFIFO    0x0040  /* 8 bit */
+ #define MMC_TXFIFO    0x0044  /* 8 bit */
+-
+-/*
+- * The base MMC clock rate
+- */
+-#ifdef CONFIG_PXA27x
+-#define CLOCKRATE_MIN 304688
+-#define CLOCKRATE_MAX 19500000
+-#else
+-#define CLOCKRATE_MIN 312500
+-#define CLOCKRATE_MAX 20000000
+-#endif
+-
+-#define CLOCKRATE     CLOCKRATE_MAX
+-
+--- linux-2.6.23.orig/drivers/mtd/maps/lubbock-flash.c
++++ linux-2.6.23/drivers/mtd/maps/lubbock-flash.c
+@@ -22,6 +22,7 @@
+ #include <asm/io.h>
+ #include <asm/hardware.h>
++#include <asm/mach-types.h>
+ #include <asm/arch/pxa-regs.h>
+ #include <asm/arch/lubbock.h>
+ #include <asm/cacheflush.h>
+@@ -71,9 +72,14 @@
+ static int __init init_lubbock(void)
+ {
+-      int flashboot = (LUB_CONF_SWITCHES & 1);
++      int flashboot;
+       int ret = 0, i;
++      if (!machine_is_lubbock())
++              return -ENODEV;
++
++      flashboot = (LUB_CONF_SWITCHES & 1);
++
+       lubbock_maps[0].bankwidth = lubbock_maps[1].bankwidth =
+               (BOOT_DEF & 1) ? 2 : 4;
+--- linux-2.6.23.orig/drivers/mtd/maps/mainstone-flash.c
++++ linux-2.6.23/drivers/mtd/maps/mainstone-flash.c
+@@ -22,6 +22,7 @@
+ #include <asm/io.h>
+ #include <asm/hardware.h>
++#include <asm/mach-types.h>
+ #include <asm/arch/pxa-regs.h>
+ #include <asm/arch/mainstone.h>
+ #include <asm/cacheflush.h>
+@@ -76,6 +77,9 @@
+       int SW7 = 0;  /* FIXME: get from SCR (Mst doc section 3.2.1.1) */
+       int ret = 0, i;
++      if (!machine_is_mainstone())
++              return -ENODEV;
++
+       mainstone_maps[0].bankwidth = (BOOT_DEF & 1) ? 2 : 4;
+       mainstone_maps[1].bankwidth = 4;
+--- linux-2.6.23.orig/drivers/net/irda/pxaficp_ir.c
++++ linux-2.6.23/drivers/net/irda/pxaficp_ir.c
+@@ -23,6 +23,7 @@
+ #include <linux/dma-mapping.h>
+ #include <linux/platform_device.h>
+ #include <linux/pm.h>
++#include <linux/clk.h>
+ #include <net/irda/irda.h>
+ #include <net/irda/irmod.h>
+@@ -87,8 +88,30 @@
+       struct device           *dev;
+       struct pxaficp_platform_data *pdata;
++      struct clk              *fir_clk;
++      struct clk              *sir_clk;
++      struct clk              *cur_clk;
+ };
++static inline void pxa_irda_disable_clk(struct pxa_irda *si)
++{
++      if (si->cur_clk)
++              clk_disable(si->cur_clk);
++      si->cur_clk = NULL;
++}
++
++static inline void pxa_irda_enable_firclk(struct pxa_irda *si)
++{
++      si->cur_clk = si->fir_clk;
++      clk_enable(si->fir_clk);
++}
++
++static inline void pxa_irda_enable_sirclk(struct pxa_irda *si)
++{
++      si->cur_clk = si->sir_clk;
++      clk_enable(si->sir_clk);
++}
++
+ #define IS_FIR(si)            ((si)->speed >= 4000000)
+ #define IRDA_FRAME_SIZE_LIMIT 2047
+@@ -134,7 +157,7 @@
+                       DCSR(si->rxdma) &= ~DCSR_RUN;
+                       /* disable FICP */
+                       ICCR0 = 0;
+-                      pxa_set_cken(CKEN_FICP, 0);
++                      pxa_irda_disable_clk(si);
+                       /* set board transceiver to SIR mode */
+                       si->pdata->transceiver_mode(si->dev, IR_SIRMODE);
+@@ -144,7 +167,7 @@
+                       pxa_gpio_mode(GPIO47_STTXD_MD);
+                       /* enable the STUART clock */
+-                      pxa_set_cken(CKEN_STUART, 1);
++                      pxa_irda_enable_sirclk(si);
+               }
+               /* disable STUART first */
+@@ -169,7 +192,7 @@
+               /* disable STUART */
+               STIER = 0;
+               STISR = 0;
+-              pxa_set_cken(CKEN_STUART, 0);
++              pxa_irda_disable_clk(si);
+               /* disable FICP first */
+               ICCR0 = 0;
+@@ -182,7 +205,7 @@
+               pxa_gpio_mode(GPIO47_ICPTXD_MD);
+               /* enable the FICP clock */
+-              pxa_set_cken(CKEN_FICP, 1);
++              pxa_irda_enable_firclk(si);
+               si->speed = speed;
+               pxa_irda_fir_dma_rx_start(si);
+@@ -592,16 +615,15 @@
+       STIER = 0;
+       /* disable STUART SIR mode */
+       STISR = 0;
+-      /* disable the STUART clock */
+-      pxa_set_cken(CKEN_STUART, 0);
+       /* disable DMA */
+       DCSR(si->txdma) &= ~DCSR_RUN;
+       DCSR(si->rxdma) &= ~DCSR_RUN;
+       /* disable FICP */
+       ICCR0 = 0;
+-      /* disable the FICP clock */
+-      pxa_set_cken(CKEN_FICP, 0);
++
++      /* disable the STUART or FICP clocks */
++      pxa_irda_disable_clk(si);
+       DRCMR17 = 0;
+       DRCMR18 = 0;
+@@ -792,6 +814,13 @@
+       si->dev = &pdev->dev;
+       si->pdata = pdev->dev.platform_data;
++      si->sir_clk = clk_get(&pdev->dev, "UARTCLK");
++      si->fir_clk = clk_get(&pdev->dev, "FICPCLK");
++      if (IS_ERR(si->sir_clk) || IS_ERR(si->fir_clk)) {
++              err = PTR_ERR(IS_ERR(si->sir_clk) ? si->sir_clk : si->fir_clk);
++              goto err_mem_4;
++      }
++
+       /*
+        * Initialise the SIR buffers
+        */
+@@ -831,6 +860,10 @@
+ err_mem_5:
+               kfree(si->rx_buff.head);
+ err_mem_4:
++              if (si->sir_clk && !IS_ERR(si->sir_clk))
++                      clk_put(si->sir_clk);
++              if (si->fir_clk && !IS_ERR(si->fir_clk))
++                      clk_put(si->fir_clk);
+               free_netdev(dev);
+ err_mem_3:
+               release_mem_region(__PREG(FICP), 0x1c);
+@@ -850,6 +883,8 @@
+               unregister_netdev(dev);
+               kfree(si->tx_buff.head);
+               kfree(si->rx_buff.head);
++              clk_put(si->fir_clk);
++              clk_put(si->sir_clk);
+               free_netdev(dev);
+       }
+--- linux-2.6.23.orig/drivers/net/smc91x.c
++++ linux-2.6.23/drivers/net/smc91x.c
+@@ -173,56 +173,6 @@
+  */
+ #define MII_DELAY             1
+-/* store this information for the driver.. */
+-struct smc_local {
+-      /*
+-       * If I have to wait until memory is available to send a
+-       * packet, I will store the skbuff here, until I get the
+-       * desired memory.  Then, I'll send it out and free it.
+-       */
+-      struct sk_buff *pending_tx_skb;
+-      struct tasklet_struct tx_task;
+-
+-      /*
+-       * 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 SMC91x chip */
+-      int     version;
+-
+-      /* Contains the current active transmission mode */
+-      int     tcr_cur_mode;
+-
+-      /* Contains the current active receive mode */
+-      int     rcr_cur_mode;
+-
+-      /* Contains the current active receive/phy mode */
+-      int     rpc_cur_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;
+-      struct net_device *dev;
+-      int     work_pending;
+-
+-      spinlock_t lock;
+-
+-#ifdef SMC_USE_PXA_DMA
+-      /* DMA needs the physical address of the chip */
+-      u_long physaddr;
+-#endif
+-      void __iomem *base;
+-      void __iomem *datacs;
+-};
+-
+ #if SMC_DEBUG > 0
+ #define DBG(n, args...)                                       \
+       do {                                            \
+@@ -2238,17 +2188,19 @@
+               goto out_release_attrib;
+       }
+-      platform_set_drvdata(pdev, ndev);
+-      ret = smc_probe(ndev, addr);
+-      if (ret != 0)
+-              goto out_iounmap;
+ #ifdef SMC_USE_PXA_DMA
+-      else {
++      {
+               struct smc_local *lp = netdev_priv(ndev);
++              lp->device = &pdev->dev;
+               lp->physaddr = res->start;
+       }
+ #endif
++      platform_set_drvdata(pdev, ndev);
++      ret = smc_probe(ndev, addr);
++      if (ret != 0)
++              goto out_iounmap;
++
+       smc_request_datacs(pdev, ndev);
+       return 0;
+--- linux-2.6.23.orig/drivers/net/smc91x.h
++++ linux-2.6.23/drivers/net/smc91x.h
+@@ -461,6 +461,59 @@
+ #endif
++
++/* store this information for the driver.. */
++struct smc_local {
++      /*
++       * If I have to wait until memory is available to send a
++       * packet, I will store the skbuff here, until I get the
++       * desired memory.  Then, I'll send it out and free it.
++       */
++      struct sk_buff *pending_tx_skb;
++      struct tasklet_struct tx_task;
++
++      /*
++       * 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 SMC91x chip */
++      int     version;
++
++      /* Contains the current active transmission mode */
++      int     tcr_cur_mode;
++
++      /* Contains the current active receive mode */
++      int     rcr_cur_mode;
++
++      /* Contains the current active receive/phy mode */
++      int     rpc_cur_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;
++      struct net_device *dev;
++      int     work_pending;
++
++      spinlock_t lock;
++
++#ifdef SMC_USE_PXA_DMA
++      /* DMA needs the physical address of the chip */
++      u_long physaddr;
++      struct device *device;
++#endif
++      void __iomem *base;
++      void __iomem *datacs;
++};
++
++
+ #ifdef SMC_USE_PXA_DMA
+ /*
+  * Let's use the DMA engine on the XScale PXA2xx for RX packets. This is
+@@ -475,11 +528,12 @@
+ #ifdef SMC_insl
+ #undef SMC_insl
+ #define SMC_insl(a, r, p, l) \
+-      smc_pxa_dma_insl(a, lp->physaddr, r, dev->dma, p, l)
++      smc_pxa_dma_insl(a, lp, r, dev->dma, p, l)
+ static inline void
+-smc_pxa_dma_insl(void __iomem *ioaddr, u_long physaddr, int reg, int dma,
++smc_pxa_dma_insl(void __iomem *ioaddr, struct smc_local *lp, int reg, int dma,
+                u_char *buf, int len)
+ {
++      u_long physaddr = lp->physaddr;
+       dma_addr_t dmabuf;
+       /* fallback if no DMA available */
+@@ -496,7 +550,7 @@
+       }
+       len *= 4;
+-      dmabuf = dma_map_single(NULL, buf, len, DMA_FROM_DEVICE);
++      dmabuf = dma_map_single(lp->device, buf, len, DMA_FROM_DEVICE);
+       DCSR(dma) = DCSR_NODESC;
+       DTADR(dma) = dmabuf;
+       DSADR(dma) = physaddr + reg;
+@@ -506,18 +560,19 @@
+       while (!(DCSR(dma) & DCSR_STOPSTATE))
+               cpu_relax();
+       DCSR(dma) = 0;
+-      dma_unmap_single(NULL, dmabuf, len, DMA_FROM_DEVICE);
++      dma_unmap_single(lp->device, dmabuf, len, DMA_FROM_DEVICE);
+ }
+ #endif
+ #ifdef SMC_insw
+ #undef SMC_insw
+ #define SMC_insw(a, r, p, l) \
+-      smc_pxa_dma_insw(a, lp->physaddr, r, dev->dma, p, l)
++      smc_pxa_dma_insw(a, lp, r, dev->dma, p, l)
+ static inline void
+-smc_pxa_dma_insw(void __iomem *ioaddr, u_long physaddr, int reg, int dma,
++smc_pxa_dma_insw(void __iomem *ioaddr, struct smc_local *lp, int reg, int dma,
+                u_char *buf, int len)
+ {
++      u_long physaddr = lp->physaddr;
+       dma_addr_t dmabuf;
+       /* fallback if no DMA available */
+@@ -534,7 +589,7 @@
+       }
+       len *= 2;
+-      dmabuf = dma_map_single(NULL, buf, len, DMA_FROM_DEVICE);
++      dmabuf = dma_map_single(lp->device, buf, len, DMA_FROM_DEVICE);
+       DCSR(dma) = DCSR_NODESC;
+       DTADR(dma) = dmabuf;
+       DSADR(dma) = physaddr + reg;
+@@ -544,7 +599,7 @@
+       while (!(DCSR(dma) & DCSR_STOPSTATE))
+               cpu_relax();
+       DCSR(dma) = 0;
+-      dma_unmap_single(NULL, dmabuf, len, DMA_FROM_DEVICE);
++      dma_unmap_single(lp->device, dmabuf, len, DMA_FROM_DEVICE);
+ }
+ #endif
+--- linux-2.6.23.orig/drivers/serial/pxa.c
++++ linux-2.6.23/drivers/serial/pxa.c
+@@ -42,6 +42,7 @@
+ #include <linux/tty.h>
+ #include <linux/tty_flip.h>
+ #include <linux/serial_core.h>
++#include <linux/clk.h>
+ #include <asm/io.h>
+ #include <asm/hardware.h>
+@@ -56,7 +57,7 @@
+       unsigned char           lcr;
+       unsigned char           mcr;
+       unsigned int            lsr_break_flag;
+-      unsigned int            cken;
++      struct clk              *clk;
+       char                    *name;
+ };
+@@ -363,6 +364,8 @@
+       else
+               up->mcr = 0;
++      up->port.uartclk = clk_get_rate(up->clk);
++
+       /*
+        * Allocate the IRQ
+        */
+@@ -568,9 +571,11 @@
+             unsigned int oldstate)
+ {
+       struct uart_pxa_port *up = (struct uart_pxa_port *)port;
+-      pxa_set_cken(up->cken, !state);
++
+       if (!state)
+-              udelay(1);
++              clk_enable(up->clk);
++      else
++              clk_disable(up->clk);
+ }
+ static void serial_pxa_release_port(struct uart_port *port)
+@@ -604,7 +609,7 @@
+ #ifdef CONFIG_SERIAL_PXA_CONSOLE
+-static struct uart_pxa_port serial_pxa_ports[];
++static struct uart_pxa_port *serial_pxa_ports[4];
+ static struct uart_driver serial_pxa_reg;
+ #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
+@@ -654,9 +659,11 @@
+ static void
+ serial_pxa_console_write(struct console *co, const char *s, unsigned int count)
+ {
+-      struct uart_pxa_port *up = &serial_pxa_ports[co->index];
++      struct uart_pxa_port *up = serial_pxa_ports[co->index];
+       unsigned int ier;
++      clk_enable(up->clk);
++
+       /*
+        *      First save the IER then disable the interrupts
+        */
+@@ -671,6 +678,8 @@
+        */
+       wait_for_xmitr(up);
+       serial_out(up, UART_IER, ier);
++
++      clk_disable(up->clk);
+ }
+ static int __init
+@@ -684,7 +693,9 @@
+       if (co->index == -1 || co->index >= serial_pxa_reg.nr)
+               co->index = 0;
+-              up = &serial_pxa_ports[co->index];
++      up = serial_pxa_ports[co->index];
++      if (!up)
++              return -ENODEV;
+       if (options)
+               uart_parse_options(options, &baud, &parity, &bits, &flow);
+@@ -702,15 +713,6 @@
+       .data           = &serial_pxa_reg,
+ };
+-static int __init
+-serial_pxa_console_init(void)
+-{
+-      register_console(&serial_pxa_console);
+-      return 0;
+-}
+-
+-console_initcall(serial_pxa_console_init);
+-
+ #define PXA_CONSOLE   &serial_pxa_console
+ #else
+ #define PXA_CONSOLE   NULL
+@@ -736,73 +738,13 @@
+       .verify_port    = serial_pxa_verify_port,
+ };
+-static struct uart_pxa_port serial_pxa_ports[] = {
+-     {        /* FFUART */
+-      .name   = "FFUART",
+-      .cken   = CKEN_FFUART,
+-      .port   = {
+-              .type           = PORT_PXA,
+-              .iotype         = UPIO_MEM,
+-              .membase        = (void *)&FFUART,
+-              .mapbase        = __PREG(FFUART),
+-              .irq            = IRQ_FFUART,
+-              .uartclk        = 921600 * 16,
+-              .fifosize       = 64,
+-              .ops            = &serial_pxa_pops,
+-              .line           = 0,
+-      },
+-  }, {        /* BTUART */
+-      .name   = "BTUART",
+-      .cken   = CKEN_BTUART,
+-      .port   = {
+-              .type           = PORT_PXA,
+-              .iotype         = UPIO_MEM,
+-              .membase        = (void *)&BTUART,
+-              .mapbase        = __PREG(BTUART),
+-              .irq            = IRQ_BTUART,
+-              .uartclk        = 921600 * 16,
+-              .fifosize       = 64,
+-              .ops            = &serial_pxa_pops,
+-              .line           = 1,
+-      },
+-  }, {        /* STUART */
+-      .name   = "STUART",
+-      .cken   = CKEN_STUART,
+-      .port   = {
+-              .type           = PORT_PXA,
+-              .iotype         = UPIO_MEM,
+-              .membase        = (void *)&STUART,
+-              .mapbase        = __PREG(STUART),
+-              .irq            = IRQ_STUART,
+-              .uartclk        = 921600 * 16,
+-              .fifosize       = 64,
+-              .ops            = &serial_pxa_pops,
+-              .line           = 2,
+-      },
+-  }, {  /* HWUART */
+-      .name   = "HWUART",
+-      .cken   = CKEN_HWUART,
+-      .port = {
+-              .type           = PORT_PXA,
+-              .iotype         = UPIO_MEM,
+-              .membase        = (void *)&HWUART,
+-              .mapbase        = __PREG(HWUART),
+-              .irq            = IRQ_HWUART,
+-              .uartclk        = 921600 * 16,
+-              .fifosize       = 64,
+-              .ops            = &serial_pxa_pops,
+-              .line           = 3,
+-      },
+-  }
+-};
+-
+ static struct uart_driver serial_pxa_reg = {
+       .owner          = THIS_MODULE,
+       .driver_name    = "PXA serial",
+       .dev_name       = "ttyS",
+       .major          = TTY_MAJOR,
+       .minor          = 64,
+-      .nr             = ARRAY_SIZE(serial_pxa_ports),
++      .nr             = 4,
+       .cons           = PXA_CONSOLE,
+ };
+@@ -828,10 +770,68 @@
+ static int serial_pxa_probe(struct platform_device *dev)
+ {
+-      serial_pxa_ports[dev->id].port.dev = &dev->dev;
+-      uart_add_one_port(&serial_pxa_reg, &serial_pxa_ports[dev->id].port);
+-      platform_set_drvdata(dev, &serial_pxa_ports[dev->id]);
++      struct uart_pxa_port *sport;
++      struct resource *mmres, *irqres;
++      int ret;
++
++      mmres = platform_get_resource(dev, IORESOURCE_MEM, 0);
++      irqres = platform_get_resource(dev, IORESOURCE_IRQ, 0);
++      if (!mmres || !irqres)
++              return -ENODEV;
++
++      sport = kzalloc(sizeof(struct uart_pxa_port), GFP_KERNEL);
++      if (!sport)
++              return -ENOMEM;
++
++      sport->clk = clk_get(&dev->dev, "UARTCLK");
++      if (IS_ERR(sport->clk)) {
++              ret = PTR_ERR(sport->clk);
++              goto err_free;
++      }
++
++      sport->port.type = PORT_PXA;
++      sport->port.iotype = UPIO_MEM;
++      sport->port.mapbase = mmres->start;
++      sport->port.irq = irqres->start;
++      sport->port.fifosize = 64;
++      sport->port.ops = &serial_pxa_pops;
++      sport->port.line = dev->id;
++      sport->port.dev = &dev->dev;
++      sport->port.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF;
++      sport->port.uartclk = clk_get_rate(sport->clk);
++
++      /*
++       * Is it worth keeping this?
++       */
++      if (mmres->start == __PREG(FFUART))
++              sport->name = "FFUART";
++      else if (mmres->start == __PREG(BTUART))
++              sport->name = "BTUART";
++      else if (mmres->start == __PREG(STUART))
++              sport->name = "STUART";
++      else if (mmres->start == __PREG(HWUART))
++              sport->name = "HWUART";
++      else
++              sport->name = "???";
++
++      sport->port.membase = ioremap(mmres->start, mmres->end - mmres->start + 1);
++      if (!sport->port.membase) {
++              ret = -ENOMEM;
++              goto err_clk;
++      }
++
++      serial_pxa_ports[dev->id] = sport;
++
++      uart_add_one_port(&serial_pxa_reg, &sport->port);
++      platform_set_drvdata(dev, sport);
++
+       return 0;
++
++ err_clk:
++      clk_put(sport->clk);
++ err_free:
++      kfree(sport);
++      return ret;
+ }
+ static int serial_pxa_remove(struct platform_device *dev)
+@@ -840,8 +840,9 @@
+       platform_set_drvdata(dev, NULL);
+-      if (sport)
+-              uart_remove_one_port(&serial_pxa_reg, &sport->port);
++      uart_remove_one_port(&serial_pxa_reg, &sport->port);
++      clk_put(sport->clk);
++      kfree(sport);
+       return 0;
+ }
+--- linux-2.6.23.orig/drivers/serial/serial_core.c
++++ linux-2.6.23/drivers/serial/serial_core.c
+@@ -2128,6 +2128,14 @@
+               spin_unlock_irqrestore(&port->lock, flags);
+               /*
++               * If this driver supports console, and it hasn't been
++               * successfully registered yet, try to re-register it.
++               * It may be that the port was not available.
++               */
++              if (port->cons && !(port->cons->flags & CON_ENABLED))
++                      register_console(port->cons);
++
++              /*
+                * Power down all ports by default, except the
+                * console if we have one.
+                */
+@@ -2288,6 +2296,7 @@
+       }
+       state->port = port;
++      state->pm_state = -1;
+       port->cons = drv->cons;
+       port->info = state->info;
+@@ -2310,15 +2319,6 @@
+       tty_register_device(drv->tty_driver, port->line, port->dev);
+       /*
+-       * If this driver supports console, and it hasn't been
+-       * successfully registered yet, try to re-register it.
+-       * It may be that the port was not available.
+-       */
+-      if (port->type != PORT_UNKNOWN &&
+-          port->cons && !(port->cons->flags & CON_ENABLED))
+-              register_console(port->cons);
+-
+-      /*
+        * Ensure UPF_DEAD is not set.
+        */
+       port->flags &= ~UPF_DEAD;
+--- linux-2.6.23.orig/drivers/usb/gadget/pxa2xx_udc.c
++++ linux-2.6.23/drivers/usb/gadget/pxa2xx_udc.c
+@@ -43,6 +43,8 @@
+ #include <linux/platform_device.h>
+ #include <linux/dma-mapping.h>
+ #include <linux/irq.h>
++#include <linux/clk.h>
++#include <linux/err.h>
+ #include <asm/byteorder.h>
+ #include <asm/dma.h>
+@@ -1157,7 +1159,7 @@
+ #ifdef        CONFIG_ARCH_PXA
+         /* Disable clock for USB device */
+-      pxa_set_cken(CKEN_USB, 0);
++      clk_disable(dev->clk);
+ #endif
+       ep0_idle (dev);
+@@ -1202,8 +1204,7 @@
+ #ifdef        CONFIG_ARCH_PXA
+         /* Enable clock for USB device */
+-      pxa_set_cken(CKEN_USB, 1);
+-      udelay(5);
++      clk_enable(dev->clk);
+ #endif
+       /* try to clear these bits before we enable the udc */
+@@ -2137,6 +2138,14 @@
+       if (irq < 0)
+               return -ENODEV;
++#ifdef        CONFIG_ARCH_PXA
++      dev->clk = clk_get(&pdev->dev, "UDCCLK");
++      if (IS_ERR(dev->clk)) {
++              retval = PTR_ERR(dev->clk);
++              goto err_clk;
++      }
++#endif
++
+       pr_debug("%s: IRQ %d%s%s\n", driver_name, irq,
+               dev->has_cfr ? "" : " (!cfr)",
+               SIZE_STR "(pio)"
+@@ -2152,11 +2161,10 @@
+                       dev_dbg(&pdev->dev,
+                               "can't get vbus gpio %d, err: %d\n",
+                               dev->mach->gpio_vbus, retval);
+-                      return -EBUSY;
++                      goto err_gpio_vbus;
+               }
+               gpio_direction_input(dev->mach->gpio_vbus);
+               vbus_irq = gpio_to_irq(dev->mach->gpio_vbus);
+-              set_irq_type(vbus_irq, IRQT_BOTHEDGE);
+       } else
+               vbus_irq = 0;
+@@ -2166,9 +2174,7 @@
+                       dev_dbg(&pdev->dev,
+                               "can't get pullup gpio %d, err: %d\n",
+                               dev->mach->gpio_pullup, retval);
+-                      if (dev->mach->gpio_vbus)
+-                              gpio_free(dev->mach->gpio_vbus);
+-                      return -EBUSY;
++                      goto err_gpio_pullup;
+               }
+               gpio_direction_output(dev->mach->gpio_pullup, 0);
+       }
+@@ -2195,11 +2201,7 @@
+       if (retval != 0) {
+               printk(KERN_ERR "%s: can't get irq %d, err %d\n",
+                       driver_name, irq, retval);
+-              if (dev->mach->gpio_pullup)
+-                      gpio_free(dev->mach->gpio_pullup);
+-              if (dev->mach->gpio_vbus)
+-                      gpio_free(dev->mach->gpio_vbus);
+-              return -EBUSY;
++              goto err_irq1;
+       }
+       dev->got_irq = 1;
+@@ -2213,12 +2215,7 @@
+                       printk(KERN_ERR "%s: can't get irq %i, err %d\n",
+                               driver_name, LUBBOCK_USB_DISC_IRQ, retval);
+ lubbock_fail0:
+-                      free_irq(irq, dev);
+-                      if (dev->mach->gpio_pullup)
+-                              gpio_free(dev->mach->gpio_pullup);
+-                      if (dev->mach->gpio_vbus)
+-                              gpio_free(dev->mach->gpio_vbus);
+-                      return -EBUSY;
++                      goto err_irq_lub;
+               }
+               retval = request_irq(LUBBOCK_USB_IRQ,
+                               lubbock_vbus_irq,
+@@ -2234,22 +2231,37 @@
+ #endif
+       if (vbus_irq) {
+               retval = request_irq(vbus_irq, udc_vbus_irq,
+-                              IRQF_DISABLED | IRQF_SAMPLE_RANDOM,
++                              IRQF_DISABLED | IRQF_SAMPLE_RANDOM |
++                              IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+                               driver_name, dev);
+               if (retval != 0) {
+                       printk(KERN_ERR "%s: can't get irq %i, err %d\n",
+                               driver_name, vbus_irq, retval);
+-                      free_irq(irq, dev);
+-                      if (dev->mach->gpio_pullup)
+-                              gpio_free(dev->mach->gpio_pullup);
+-                      if (dev->mach->gpio_vbus)
+-                              gpio_free(dev->mach->gpio_vbus);
+-                      return -EBUSY;
++                      goto err_vbus_irq;
+               }
+       }
+       create_proc_files();
+       return 0;
++
++ err_vbus_irq:
++#ifdef        CONFIG_ARCH_LUBBOCK
++      free_irq(LUBBOCK_USB_DISC_IRQ, dev);
++ err_irq_lub:
++#endif
++      free_irq(irq, dev);
++ err_irq1:
++      if (dev->mach->gpio_pullup)
++              gpio_free(dev->mach->gpio_pullup);
++ err_gpio_pullup:
++      if (dev->mach->gpio_vbus)
++              gpio_free(dev->mach->gpio_vbus);
++ err_gpio_vbus:
++#ifdef        CONFIG_ARCH_PXA
++      clk_put(dev->clk);
++ err_clk:
++#endif
++      return retval;
+ }
+ static void pxa2xx_udc_shutdown(struct platform_device *_dev)
+@@ -2284,6 +2296,10 @@
+       if (dev->mach->gpio_pullup)
+               gpio_free(dev->mach->gpio_pullup);
++#ifdef        CONFIG_ARCH_PXA
++      clk_put(dev->clk);
++#endif
++
+       platform_set_drvdata(pdev, NULL);
+       the_controller = NULL;
+       return 0;
+--- linux-2.6.23.orig/drivers/usb/gadget/pxa2xx_udc.h
++++ linux-2.6.23/drivers/usb/gadget/pxa2xx_udc.h
+@@ -125,6 +125,7 @@
+       struct timer_list                       timer;
+       struct device                           *dev;
++      struct clk                              *clk;
+       struct pxa2xx_udc_mach_info             *mach;
+       u64                                     dma_mask;
+       struct pxa2xx_ep                        ep [PXA_UDC_NUM_ENDPOINTS];
+--- linux-2.6.23.orig/drivers/video/pxafb.c
++++ linux-2.6.23/drivers/video/pxafb.c
+@@ -37,6 +37,8 @@
+ #include <linux/cpufreq.h>
+ #include <linux/platform_device.h>
+ #include <linux/dma-mapping.h>
++#include <linux/clk.h>
++#include <linux/err.h>
+ #include <asm/hardware.h>
+ #include <asm/io.h>
+@@ -574,15 +576,15 @@
+  *
+  * Factoring the 10^4 and 10^-12 out gives 10^-8 == 1 / 100000000 as used below.
+  */
+-static inline unsigned int get_pcd(unsigned int pixclock)
++static inline unsigned int get_pcd(struct pxafb_info *fbi, unsigned int pixclock)
+ {
+       unsigned long long pcd;
+       /* FIXME: Need to take into account Double Pixel Clock mode
+-         * (DPC) bit? or perhaps set it based on the various clock
+-         * speeds */
+-
+-      pcd = (unsigned long long)get_lcdclk_frequency_10khz() * pixclock;
++       * (DPC) bit? or perhaps set it based on the various clock
++       * speeds */
++      pcd = (unsigned long long)(clk_get_rate(fbi->clk) / 10000);
++      pcd *= pixclock;
+       do_div(pcd, 100000000 * 2);
+       /* no need for this, since we should subtract 1 anyway. they cancel */
+       /* pcd += 1; */ /* make up for integer math truncations */
+@@ -591,19 +593,21 @@
+ /*
+  * Some touchscreens need hsync information from the video driver to
+- * function correctly. We export it here.
++ * function correctly. We export it here.  Note that 'hsync_time' and
++ * the value returned from pxafb_get_hsync_time() is the *reciprocal*
++ * of the hsync period in seconds.
+  */
+ static inline void set_hsync_time(struct pxafb_info *fbi, unsigned int pcd)
+ {
+-      unsigned long long htime;
++      unsigned long htime;
+       if ((pcd == 0) || (fbi->fb.var.hsync_len == 0)) {
+               fbi->hsync_time=0;
+               return;
+       }
+-      htime = (unsigned long long)get_lcdclk_frequency_10khz() * 10000;
+-      do_div(htime, pcd * fbi->fb.var.hsync_len);
++      htime = clk_get_rate(fbi->clk) / (pcd * fbi->fb.var.hsync_len);
++
+       fbi->hsync_time = htime;
+ }
+@@ -628,7 +632,7 @@
+ {
+       struct pxafb_lcd_reg new_regs;
+       u_long flags;
+-      u_int lines_per_panel, pcd = get_pcd(var->pixclock);
++      u_int lines_per_panel, pcd = get_pcd(fbi, var->pixclock);
+       pr_debug("pxafb: Configuring PXA LCD\n");
+@@ -908,7 +912,7 @@
+       pr_debug("reg_lccr3 0x%08x\n", (unsigned int) fbi->reg_lccr3);
+       /* enable LCD controller clock */
+-      pxa_set_cken(CKEN_LCD, 1);
++      clk_enable(fbi->clk);
+       down(&fcs_lcd_sem);
+       /* Sequence from 11.7.10 */
+@@ -950,7 +954,7 @@
+       up(&fcs_lcd_sem);
+       /* disable LCD controller clock */
+-      pxa_set_cken(CKEN_LCD, 0);
++      clk_disable(fbi->clk);
+ }
+ /*
+@@ -1161,7 +1165,7 @@
+               if ((clkinfo->old == 13000))
+                       break;
+-              pcd = get_pcd(fbi->fb.var.pixclock);
++              pcd = get_pcd(fbi, fbi->fb.var.pixclock);
+               lccr3 = fbi->reg_lccr3;
+               set_hsync_time(fbi, pcd);
+               fbi->reg_lccr3 = (fbi->reg_lccr3 & ~0xff) | LCCR3_PixClkDiv(pcd);
+@@ -1293,6 +1297,12 @@
+       memset(fbi, 0, sizeof(struct pxafb_info));
+       fbi->dev = dev;
++      fbi->clk = clk_get(dev, "LCDCLK");
++      if (IS_ERR(fbi->clk)) {
++              kfree(fbi);
++              return NULL;
++      }
++
+       strcpy(fbi->fb.fix.id, PXA_NAME);
+       fbi->fb.fix.type        = FB_TYPE_PACKED_PIXELS;
+--- linux-2.6.23.orig/drivers/video/pxafb.h
++++ linux-2.6.23/drivers/video/pxafb.h
+@@ -94,6 +94,7 @@
+ struct pxafb_info {
+       struct fb_info          fb;
+       struct device           *dev;
++      struct clk              *clk;
+       /*
+        * These are the addresses we mapped
+--- linux-2.6.23.orig/include/asm-arm/arch-pxa/hardware.h
++++ linux-2.6.23/include/asm-arm/arch-pxa/hardware.h
+@@ -80,6 +80,24 @@
+               _id == 0x411;                           \
+       })
++#define __cpu_is_pxa300(id)                           \
++      ({                                              \
++              unsigned int _id = (id) >> 4 & 0xfff;   \
++              _id == 0x688;                           \
++       })
++
++#define __cpu_is_pxa310(id)                           \
++      ({                                              \
++              unsigned int _id = (id) >> 4 & 0xfff;   \
++              _id == 0x689;                           \
++       })
++
++#define __cpu_is_pxa320(id)                           \
++      ({                                              \
++              unsigned int _id = (id) >> 4 & 0xfff;   \
++              _id == 0x603 || _id == 0x682;           \
++       })
++
+ #define cpu_is_pxa21x()                                       \
+       ({                                              \
+               unsigned int id = read_cpuid(CPUID_ID); \
+@@ -98,6 +116,53 @@
+               __cpu_is_pxa27x(id);                    \
+       })
++#define cpu_is_pxa300()                                       \
++      ({                                              \
++              unsigned int id = read_cpuid(CPUID_ID); \
++              __cpu_is_pxa300(id);                    \
++       })
++
++#define cpu_is_pxa310()                                       \
++      ({                                              \
++              unsigned int id = read_cpuid(CPUID_ID); \
++              __cpu_is_pxa310(id);                    \
++       })
++
++#define cpu_is_pxa320()                                       \
++      ({                                              \
++              unsigned int id = read_cpuid(CPUID_ID); \
++              __cpu_is_pxa320(id);                    \
++       })
++
++/*
++ * CPUID Core Generation Bit
++ * <= 0x2 for pxa21x/pxa25x/pxa26x/pxa27x
++ * == 0x3 for pxa300/pxa310/pxa320
++ */
++#define __cpu_is_pxa2xx(id)                           \
++      ({                                              \
++              unsigned int _id = (id) >> 13 & 0x7;    \
++              _id <= 0x2;                             \
++       })
++
++#define __cpu_is_pxa3xx(id)                           \
++      ({                                              \
++              unsigned int _id = (id) >> 13 & 0x7;    \
++              _id == 0x3;                             \
++       })
++
++#define cpu_is_pxa2xx()                                       \
++      ({                                              \
++              unsigned int id = read_cpuid(CPUID_ID); \
++              __cpu_is_pxa2xx(id);                    \
++       })
++
++#define cpu_is_pxa3xx()                                       \
++      ({                                              \
++              unsigned int id = read_cpuid(CPUID_ID); \
++              __cpu_is_pxa3xx(id);                    \
++       })
++
+ /*
+  * Handy routine to set GPIO alternate functions
+  */
+@@ -116,13 +181,16 @@
+ /*
+  * Routine to enable or disable CKEN
+  */
+-extern void pxa_set_cken(int clock, int enable);
++static inline void __deprecated pxa_set_cken(int clock, int enable)
++{
++      extern void __pxa_set_cken(int clock, int enable);
++      __pxa_set_cken(clock, enable);
++}
+ /*
+  * return current memory and LCD clock frequency in units of 10kHz
+  */
+ extern unsigned int get_memclk_frequency_10khz(void);
+-extern unsigned int get_lcdclk_frequency_10khz(void);
+ #endif
+--- linux-2.6.23.orig/include/asm-arm/arch-pxa/irqs.h
++++ linux-2.6.23/include/asm-arm/arch-pxa/irqs.h
+@@ -66,12 +66,6 @@
+ #define IRQ_TO_GPIO_2_x(i)    ((i) - PXA_GPIO_IRQ_BASE)
+ #define IRQ_TO_GPIO(i)        (((i) < IRQ_GPIO(2)) ? ((i) - IRQ_GPIO0) : IRQ_TO_GPIO_2_x(i))
+-#if defined(CONFIG_PXA25x)
+-#define PXA_LAST_GPIO 84
+-#elif defined(CONFIG_PXA27x)
+-#define PXA_LAST_GPIO 127
+-#endif
+-
+ /*
+  * The next 16 interrupts are for board specific purposes.  Since
+  * the kernel can only run on one machine at a time, we can re-use
+--- /dev/null
++++ linux-2.6.23/include/asm-arm/arch-pxa/mfp-pxa300.h
+@@ -0,0 +1,574 @@
++/*
++ * linux/include/asm-arm/arch-pxa/mfp-pxa300.h
++ *
++ * PXA300/PXA310 specific MFP configuration definitions
++ *
++ * Copyright (C) 2007 Marvell International Ltd.
++ * 2007-08-21: eric miao <eric.y.miao@gmail.com>
++ *             initial version
++ *
++ *  This program is free software; you can 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_MFP_PXA300_H
++#define __ASM_ARCH_MFP_PXA300_H
++
++#include <asm/arch/mfp.h>
++
++/* GPIO */
++#define GPIO46_GPIO           MFP_CFG(GPIO46, AF1)
++#define GPIO49_GPIO           MFP_CFG(GPIO49, AF3)
++#define GPIO50_GPIO           MFP_CFG(GPIO50, AF2)
++#define GPIO51_GPIO           MFP_CFG(GPIO51, AF3)
++#define GPIO52_GPIO           MFP_CFG(GPIO52, AF3)
++#define GPIO56_GPIO           MFP_CFG(GPIO56, AF0)
++#define GPIO58_GPIO           MFP_CFG(GPIO58, AF0)
++#define GPIO59_GPIO           MFP_CFG(GPIO59, AF0)
++#define GPIO60_GPIO           MFP_CFG(GPIO60, AF0)
++#define GPIO61_GPIO           MFP_CFG(GPIO61, AF0)
++#define GPIO62_GPIO           MFP_CFG(GPIO62, AF0)
++
++#ifdef CONFIG_CPU_PXA310
++#define GPIO7_2_GPIO          MFP_CFG(GPIO7_2, AF0)
++#define GPIO8_2_GPIO          MFP_CFG(GPIO8_2, AF0)
++#define GPIO9_2_GPIO          MFP_CFG(GPIO9_2, AF0)
++#define GPIO10_2_GPIO         MFP_CFG(GPIO10_2, AF0)
++#define GPIO11_2_GPIO         MFP_CFG(GPIO11_2, AF0)
++#define GPIO12_2_GPIO         MFP_CFG(GPIO12_2, AF0)
++#endif
++
++/* Chip Select */
++#define GPIO2_nCS3            MFP_CFG(GPIO2,  AF1)
++
++/* AC97 */
++#define GPIO23_AC97_nACRESET  MFP_CFG(GPIO23, AF1)
++#define GPIO24_AC97_SYSCLK    MFP_CFG(GPIO24, AF1)
++#define GPIO29_AC97_BITCLK    MFP_CFG(GPIO29, AF1)
++#define GPIO25_AC97_SDATA_IN_0        MFP_CFG(GPIO25, AF1)
++#define GPIO26_AC97_SDATA_IN_1        MFP_CFG(GPIO26, AF1)
++#define GPIO17_AC97_SDATA_IN_2        MFP_CFG(GPIO17, AF3)
++#define GPIO21_AC97_SDATA_IN_2        MFP_CFG(GPIO21, AF2)
++#define GPIO18_AC97_SDATA_IN_3        MFP_CFG(GPIO18, AF3)
++#define GPIO22_AC97_SDATA_IN_3        MFP_CFG(GPIO22, AF2)
++#define GPIO27_AC97_SDATA_OUT MFP_CFG(GPIO27, AF1)
++#define GPIO28_AC97_SYNC      MFP_CFG(GPIO28, AF1)
++
++/* I2C */
++#define GPIO21_I2C_SCL                MFP_CFG_LPM(GPIO21, AF1, PULL_HIGH)
++#define GPIO22_I2C_SDA                MFP_CFG_LPM(GPIO22, AF1, PULL_HIGH)
++
++/* QCI */
++#define GPIO39_CI_DD_0                MFP_CFG_DRV(GPIO39, AF1, DS04X)
++#define GPIO40_CI_DD_1                MFP_CFG_DRV(GPIO40, AF1, DS04X)
++#define GPIO41_CI_DD_2                MFP_CFG_DRV(GPIO41, AF1, DS04X)
++#define GPIO42_CI_DD_3                MFP_CFG_DRV(GPIO42, AF1, DS04X)
++#define GPIO43_CI_DD_4                MFP_CFG_DRV(GPIO43, AF1, DS04X)
++#define GPIO44_CI_DD_5                MFP_CFG_DRV(GPIO44, AF1, DS04X)
++#define GPIO45_CI_DD_6                MFP_CFG_DRV(GPIO45, AF1, DS04X)
++#define GPIO46_CI_DD_7                MFP_CFG_DRV(GPIO46, AF0, DS04X)
++#define GPIO47_CI_DD_8                MFP_CFG_DRV(GPIO47, AF1, DS04X)
++#define GPIO48_CI_DD_9                MFP_CFG_DRV(GPIO48, AF1, DS04X)
++#define GPIO52_CI_HSYNC               MFP_CFG_DRV(GPIO52, AF0, DS04X)
++#define GPIO51_CI_VSYNC               MFP_CFG_DRV(GPIO51, AF0, DS04X)
++#define GPIO49_CI_MCLK                MFP_CFG_DRV(GPIO49, AF0, DS04X)
++#define GPIO50_CI_PCLK                MFP_CFG_DRV(GPIO50, AF0, DS04X)
++
++/* KEYPAD */
++#define GPIO3_KP_DKIN_6               MFP_CFG_LPM(GPIO3,   AF2, FLOAT)
++#define GPIO4_KP_DKIN_7               MFP_CFG_LPM(GPIO4,   AF2, FLOAT)
++#define GPIO16_KP_DKIN_6      MFP_CFG_LPM(GPIO16,  AF6, FLOAT)
++#define GPIO83_KP_DKIN_2      MFP_CFG_LPM(GPIO83,  AF5, FLOAT)
++#define GPIO84_KP_DKIN_1      MFP_CFG_LPM(GPIO84,  AF5, FLOAT)
++#define GPIO85_KP_DKIN_0      MFP_CFG_LPM(GPIO85,  AF3, FLOAT)
++#define GPIO86_KP_DKIN_1      MFP_CFG_LPM(GPIO86,  AF3, FLOAT)
++#define GPIO87_KP_DKIN_2      MFP_CFG_LPM(GPIO87,  AF3, FLOAT)
++#define GPIO88_KP_DKIN_3      MFP_CFG_LPM(GPIO88,  AF3, FLOAT)
++#define GPIO89_KP_DKIN_3      MFP_CFG_LPM(GPIO89,  AF3, FLOAT)
++#define GPIO107_KP_DKIN_0     MFP_CFG_LPM(GPIO107, AF2, FLOAT)
++#define GPIO108_KP_DKIN_1     MFP_CFG_LPM(GPIO108, AF2, FLOAT)
++#define GPIO109_KP_DKIN_2     MFP_CFG_LPM(GPIO109, AF2, FLOAT)
++#define GPIO110_KP_DKIN_3     MFP_CFG_LPM(GPIO110, AF2, FLOAT)
++#define GPIO111_KP_DKIN_4     MFP_CFG_LPM(GPIO111, AF2, FLOAT)
++#define GPIO112_KP_DKIN_5     MFP_CFG_LPM(GPIO112, AF2, FLOAT)
++#define GPIO113_KP_DKIN_6     MFP_CFG_LPM(GPIO113, AF2, FLOAT)
++#define GPIO114_KP_DKIN_7     MFP_CFG_LPM(GPIO114, AF2, FLOAT)
++#define GPIO115_KP_DKIN_0     MFP_CFG_LPM(GPIO115, AF2, FLOAT)
++#define GPIO116_KP_DKIN_1     MFP_CFG_LPM(GPIO116, AF2, FLOAT)
++#define GPIO117_KP_DKIN_2     MFP_CFG_LPM(GPIO117, AF2, FLOAT)
++#define GPIO118_KP_DKIN_3     MFP_CFG_LPM(GPIO118, AF2, FLOAT)
++#define GPIO119_KP_DKIN_4     MFP_CFG_LPM(GPIO119, AF2, FLOAT)
++#define GPIO120_KP_DKIN_5     MFP_CFG_LPM(GPIO120, AF2, FLOAT)
++#define GPIO121_KP_DKIN_6     MFP_CFG_LPM(GPIO121, AF2, FLOAT)
++#define GPIO122_KP_DKIN_5     MFP_CFG_LPM(GPIO122, AF2, FLOAT)
++#define GPIO123_KP_DKIN_4     MFP_CFG_LPM(GPIO123, AF2, FLOAT)
++#define GPIO124_KP_DKIN_3     MFP_CFG_LPM(GPIO124, AF2, FLOAT)
++#define GPIO127_KP_DKIN_0     MFP_CFG_LPM(GPIO127, AF5, FLOAT)
++#define GPIO0_2_KP_DKIN_0     MFP_CFG_LPM(GPIO0_2, AF2, FLOAT)
++#define GPIO1_2_KP_DKIN_1     MFP_CFG_LPM(GPIO1_2, AF2, FLOAT)
++#define GPIO2_2_KP_DKIN_6     MFP_CFG_LPM(GPIO2_2, AF2, FLOAT)
++#define GPIO3_2_KP_DKIN_7     MFP_CFG_LPM(GPIO3_2, AF2, FLOAT)
++#define GPIO4_2_KP_DKIN_1     MFP_CFG_LPM(GPIO4_2, AF2, FLOAT)
++#define GPIO5_2_KP_DKIN_0     MFP_CFG_LPM(GPIO5_2, AF2, FLOAT)
++
++#define GPIO5_KP_MKIN_0               MFP_CFG_LPM(GPIO5,   AF2, FLOAT)
++#define GPIO6_KP_MKIN_1               MFP_CFG_LPM(GPIO6,   AF2, FLOAT)
++#define GPIO9_KP_MKIN_6               MFP_CFG_LPM(GPIO9,   AF3, FLOAT)
++#define GPIO10_KP_MKIN_7      MFP_CFG_LPM(GPIO10,  AF3, FLOAT)
++#define GPIO70_KP_MKIN_6      MFP_CFG_LPM(GPIO70,  AF3, FLOAT)
++#define GPIO71_KP_MKIN_7      MFP_CFG_LPM(GPIO71,  AF3, FLOAT)
++#define GPIO100_KP_MKIN_6     MFP_CFG_LPM(GPIO100, AF7, FLOAT)
++#define GPIO101_KP_MKIN_7     MFP_CFG_LPM(GPIO101, AF7, FLOAT)
++#define GPIO112_KP_MKIN_6     MFP_CFG_LPM(GPIO112, AF4, FLOAT)
++#define GPIO113_KP_MKIN_7     MFP_CFG_LPM(GPIO113, AF4, FLOAT)
++#define GPIO115_KP_MKIN_0     MFP_CFG_LPM(GPIO115, AF1, FLOAT)
++#define GPIO116_KP_MKIN_1     MFP_CFG_LPM(GPIO116, AF1, FLOAT)
++#define GPIO117_KP_MKIN_2     MFP_CFG_LPM(GPIO117, AF1, FLOAT)
++#define GPIO118_KP_MKIN_3     MFP_CFG_LPM(GPIO118, AF1, FLOAT)
++#define GPIO119_KP_MKIN_4     MFP_CFG_LPM(GPIO119, AF1, FLOAT)
++#define GPIO120_KP_MKIN_5     MFP_CFG_LPM(GPIO120, AF1, FLOAT)
++#define GPIO125_KP_MKIN_2     MFP_CFG_LPM(GPIO125, AF2, FLOAT)
++#define GPIO2_2_KP_MKIN_6     MFP_CFG_LPM(GPIO2_2, AF1, FLOAT)
++#define GPIO3_2_KP_MKIN_7     MFP_CFG_LPM(GPIO3_2, AF1, FLOAT)
++
++#define GPIO7_KP_MKOUT_5      MFP_CFG_LPM(GPIO7,   AF1, DRIVE_HIGH)
++#define GPIO11_KP_MKOUT_5     MFP_CFG_LPM(GPIO11,  AF3, DRIVE_HIGH)
++#define GPIO12_KP_MKOUT_6     MFP_CFG_LPM(GPIO12,  AF3, DRIVE_HIGH)
++#define GPIO13_KP_MKOUT_7     MFP_CFG_LPM(GPIO13,  AF3, DRIVE_HIGH)
++#define GPIO19_KP_MKOUT_4     MFP_CFG_LPM(GPIO19,  AF3, DRIVE_HIGH)
++#define GPIO20_KP_MKOUT_5     MFP_CFG_LPM(GPIO20,  AF3, DRIVE_HIGH)
++#define GPIO38_KP_MKOUT_5     MFP_CFG_LPM(GPIO38,  AF5, DRIVE_HIGH)
++#define GPIO53_KP_MKOUT_6     MFP_CFG_LPM(GPIO53,  AF5, DRIVE_HIGH)
++#define GPIO78_KP_MKOUT_7     MFP_CFG_LPM(GPIO78,  AF5, DRIVE_HIGH)
++#define GPIO85_KP_MKOUT_0     MFP_CFG_LPM(GPIO85,  AF2, DRIVE_HIGH)
++#define GPIO86_KP_MKOUT_1     MFP_CFG_LPM(GPIO86,  AF2, DRIVE_HIGH)
++#define GPIO87_KP_MKOUT_2     MFP_CFG_LPM(GPIO87,  AF2, DRIVE_HIGH)
++#define GPIO88_KP_MKOUT_3     MFP_CFG_LPM(GPIO88,  AF2, DRIVE_HIGH)
++#define GPIO104_KP_MKOUT_6    MFP_CFG_LPM(GPIO104, AF5, DRIVE_HIGH)
++#define GPIO105_KP_MKOUT_7    MFP_CFG_LPM(GPIO105, AF5, DRIVE_HIGH)
++#define GPIO121_KP_MKOUT_0    MFP_CFG_LPM(GPIO121, AF1, DRIVE_HIGH)
++#define GPIO122_KP_MKOUT_1    MFP_CFG_LPM(GPIO122, AF1, DRIVE_HIGH)
++#define GPIO123_KP_MKOUT_2    MFP_CFG_LPM(GPIO123, AF1, DRIVE_HIGH)
++#define GPIO124_KP_MKOUT_3    MFP_CFG_LPM(GPIO124, AF1, DRIVE_HIGH)
++#define GPIO125_KP_MKOUT_4    MFP_CFG_LPM(GPIO125, AF1, DRIVE_HIGH)
++#define GPIO126_KP_MKOUT_7    MFP_CFG_LPM(GPIO126, AF4, DRIVE_HIGH)
++#define GPIO5_2_KP_MKOUT_6    MFP_CFG_LPM(GPIO5_2, AF1, DRIVE_HIGH)
++#define GPIO4_2_KP_MKOUT_5    MFP_CFG_LPM(GPIO4_2, AF1, DRIVE_HIGH)
++#define GPIO6_2_KP_MKOUT_7    MFP_CFG_LPM(GPIO6_2, AF1, DRIVE_HIGH)
++
++/* LCD */
++#define GPIO54_LCD_LDD_0      MFP_CFG_DRV(GPIO54, AF1, DS01X)
++#define GPIO55_LCD_LDD_1      MFP_CFG_DRV(GPIO55, AF1, DS01X)
++#define GPIO56_LCD_LDD_2      MFP_CFG_DRV(GPIO56, AF1, DS01X)
++#define GPIO57_LCD_LDD_3      MFP_CFG_DRV(GPIO57, AF1, DS01X)
++#define GPIO58_LCD_LDD_4      MFP_CFG_DRV(GPIO58, AF1, DS01X)
++#define GPIO59_LCD_LDD_5      MFP_CFG_DRV(GPIO59, AF1, DS01X)
++#define GPIO60_LCD_LDD_6      MFP_CFG_DRV(GPIO60, AF1, DS01X)
++#define GPIO61_LCD_LDD_7      MFP_CFG_DRV(GPIO61, AF1, DS01X)
++#define GPIO62_LCD_LDD_8      MFP_CFG_DRV(GPIO62, AF1, DS01X)
++#define GPIO63_LCD_LDD_9      MFP_CFG_DRV(GPIO63, AF1, DS01X)
++#define GPIO64_LCD_LDD_10     MFP_CFG_DRV(GPIO64, AF1, DS01X)
++#define GPIO65_LCD_LDD_11     MFP_CFG_DRV(GPIO65, AF1, DS01X)
++#define GPIO66_LCD_LDD_12     MFP_CFG_DRV(GPIO66, AF1, DS01X)
++#define GPIO67_LCD_LDD_13     MFP_CFG_DRV(GPIO67, AF1, DS01X)
++#define GPIO68_LCD_LDD_14     MFP_CFG_DRV(GPIO68, AF1, DS01X)
++#define GPIO69_LCD_LDD_15     MFP_CFG_DRV(GPIO69, AF1, DS01X)
++#define GPIO70_LCD_LDD_16     MFP_CFG_DRV(GPIO70, AF1, DS01X)
++#define GPIO71_LCD_LDD_17     MFP_CFG_DRV(GPIO71, AF1, DS01X)
++#define GPIO62_LCD_CS_N               MFP_CFG_DRV(GPIO62, AF2, DS01X)
++#define GPIO72_LCD_FCLK               MFP_CFG_DRV(GPIO72, AF1, DS01X)
++#define GPIO73_LCD_LCLK               MFP_CFG_DRV(GPIO73, AF1, DS01X)
++#define GPIO74_LCD_PCLK               MFP_CFG_DRV(GPIO74, AF1, DS01X)
++#define GPIO75_LCD_BIAS               MFP_CFG_DRV(GPIO75, AF1, DS01X)
++#define GPIO76_LCD_VSYNC      MFP_CFG_DRV(GPIO76, AF2, DS01X)
++
++#define GPIO15_LCD_CS_N               MFP_CFG_DRV(GPIO15,  AF2, DS01X)
++#define GPIO127_LCD_CS_N      MFP_CFG_DRV(GPIO127, AF1, DS01X)
++#define GPIO63_LCD_VSYNC      MFP_CFG_DRV(GPIO63,  AF2, DS01X)
++
++/* Mini-LCD */
++#define GPIO72_MLCD_FCLK      MFP_CFG_DRV(GPIO72, AF7, DS08X)
++#define GPIO73_MLCD_LCLK      MFP_CFG_DRV(GPIO73, AF7, DS08X)
++#define GPIO54_MLCD_LDD_0     MFP_CFG_DRV(GPIO54, AF7, DS08X)
++#define GPIO55_MLCD_LDD_1     MFP_CFG_DRV(GPIO55, AF7, DS08X)
++#define GPIO56_MLCD_LDD_2     MFP_CFG_DRV(GPIO56, AF7, DS08X)
++#define GPIO57_MLCD_LDD_3     MFP_CFG_DRV(GPIO57, AF7, DS08X)
++#define GPIO58_MLCD_LDD_4     MFP_CFG_DRV(GPIO58, AF7, DS08X)
++#define GPIO59_MLCD_LDD_5     MFP_CFG_DRV(GPIO59, AF7, DS08X)
++#define GPIO60_MLCD_LDD_6     MFP_CFG_DRV(GPIO60, AF7, DS08X)
++#define GPIO61_MLCD_LDD_7     MFP_CFG_DRV(GPIO61, AF7, DS08X)
++#define GPIO62_MLCD_LDD_8     MFP_CFG_DRV(GPIO62, AF7, DS08X)
++#define GPIO63_MLCD_LDD_9     MFP_CFG_DRV(GPIO63, AF7, DS08X)
++#define GPIO64_MLCD_LDD_10    MFP_CFG_DRV(GPIO64, AF7, DS08X)
++#define GPIO65_MLCD_LDD_11    MFP_CFG_DRV(GPIO65, AF7, DS08X)
++#define GPIO66_MLCD_LDD_12    MFP_CFG_DRV(GPIO66, AF7, DS08X)
++#define GPIO67_MLCD_LDD_13    MFP_CFG_DRV(GPIO67, AF7, DS08X)
++#define GPIO68_MLCD_LDD_14    MFP_CFG_DRV(GPIO68, AF7, DS08X)
++#define GPIO69_MLCD_LDD_15    MFP_CFG_DRV(GPIO69, AF7, DS08X)
++#define GPIO74_MLCD_PCLK      MFP_CFG_DRV(GPIO74, AF7, DS08X)
++#define GPIO75_MLCD_BIAS      MFP_CFG_DRV(GPIO75, AF2, DS08X)
++
++/* MMC1 */
++#define GPIO7_MMC1_CLK                MFP_CFG_LPM(GPIO7,  AF4, DRIVE_HIGH)
++#define GPIO8_MMC1_CMD                MFP_CFG_LPM(GPIO8,  AF4, DRIVE_HIGH)
++#define GPIO14_MMC1_CMD               MFP_CFG_LPM(GPIO14, AF5, DRIVE_HIGH)
++#define GPIO15_MMC1_CMD               MFP_CFG_LPM(GPIO15, AF5, DRIVE_HIGH)
++#define GPIO3_MMC1_DAT0               MFP_CFG_LPM(GPIO3,  AF4, DRIVE_HIGH)
++#define GPIO4_MMC1_DAT1               MFP_CFG_LPM(GPIO4,  AF4, DRIVE_HIGH)
++#define GPIO5_MMC1_DAT2               MFP_CFG_LPM(GPIO5,  AF4, DRIVE_HIGH)
++#define GPIO6_MMC1_DAT3               MFP_CFG_LPM(GPIO6,  AF4, DRIVE_HIGH)
++
++/* MMC2 */
++#define GPIO9_MMC2_DAT0               MFP_CFG_LPM(GPIO9,  AF4, PULL_HIGH)
++#define GPIO10_MMC2_DAT1      MFP_CFG_LPM(GPIO10, AF4, PULL_HIGH)
++#define GPIO11_MMC2_DAT2      MFP_CFG_LPM(GPIO11, AF4, PULL_HIGH)
++#define GPIO12_MMC2_DAT3      MFP_CFG_LPM(GPIO12, AF4, PULL_HIGH)
++#define GPIO13_MMC2_CLK               MFP_CFG_LPM(GPIO13, AF4, PULL_HIGH)
++#define GPIO14_MMC2_CMD               MFP_CFG_LPM(GPIO14, AF4, PULL_HIGH)
++#define GPIO77_MMC2_DAT0      MFP_CFG_LPM(GPIO77, AF4, PULL_HIGH)
++#define GPIO78_MMC2_DAT1      MFP_CFG_LPM(GPIO78, AF4, PULL_HIGH)
++#define GPIO79_MMC2_DAT2      MFP_CFG_LPM(GPIO79, AF4, PULL_HIGH)
++#define GPIO80_MMC2_DAT3      MFP_CFG_LPM(GPIO80, AF4, PULL_HIGH)
++#define GPIO81_MMC2_CLK               MFP_CFG_LPM(GPIO81, AF4, PULL_HIGH)
++#define GPIO82_MMC2_CMD               MFP_CFG_LPM(GPIO82, AF4, PULL_HIGH)
++
++/* SSP1 */
++#define GPIO89_SSP1_EXTCLK    MFP_CFG(GPIO89, AF1)
++#define GPIO90_SSP1_SYSCLK    MFP_CFG(GPIO90, AF1)
++#define GPIO15_SSP1_SCLK      MFP_CFG(GPIO15, AF6)
++#define GPIO16_SSP1_FRM               MFP_CFG(GPIO16, AF2)
++#define GPIO33_SSP1_SCLK      MFP_CFG(GPIO33, AF5)
++#define GPIO34_SSP1_FRM               MFP_CFG(GPIO34, AF5)
++#define GPIO85_SSP1_SCLK      MFP_CFG(GPIO85, AF1)
++#define GPIO86_SSP1_FRM               MFP_CFG(GPIO86, AF1)
++#define GPIO18_SSP1_TXD               MFP_CFG(GPIO18, AF7)
++#define GPIO18_SSP1_RXD               MFP_CFG(GPIO18, AF2)
++#define GPIO20_SSP1_TXD               MFP_CFG(GPIO20, AF2)
++#define GPIO20_SSP1_RXD               MFP_CFG(GPIO20, AF7)
++#define GPIO35_SSP1_TXD               MFP_CFG(GPIO35, AF5)
++#define GPIO35_SSP1_RXD               MFP_CFG(GPIO35, AF4)
++#define GPIO36_SSP1_TXD               MFP_CFG(GPIO36, AF5)
++#define GPIO36_SSP1_RXD               MFP_CFG(GPIO36, AF6)
++#define GPIO87_SSP1_TXD               MFP_CFG(GPIO87, AF1)
++#define GPIO87_SSP1_RXD               MFP_CFG(GPIO87, AF6)
++#define GPIO88_SSP1_TXD               MFP_CFG(GPIO88, AF6)
++#define GPIO88_SSP1_RXD               MFP_CFG(GPIO88, AF1)
++
++/* SSP2 */
++#define GPIO29_SSP2_EXTCLK    MFP_CFG(GPIO29, AF2)
++#define GPIO23_SSP2_SCLK      MFP_CFG(GPIO23, AF2)
++#define GPIO17_SSP2_FRM               MFP_CFG(GPIO17, AF2)
++#define GPIO25_SSP2_SCLK      MFP_CFG(GPIO25, AF2)
++#define GPIO26_SSP2_FRM               MFP_CFG(GPIO26, AF2)
++#define GPIO33_SSP2_SCLK      MFP_CFG(GPIO33, AF6)
++#define GPIO34_SSP2_FRM               MFP_CFG(GPIO34, AF6)
++#define GPIO64_SSP2_SCLK      MFP_CFG(GPIO64, AF2)
++#define GPIO65_SSP2_FRM               MFP_CFG(GPIO65, AF2)
++#define GPIO19_SSP2_TXD               MFP_CFG(GPIO19, AF2)
++#define GPIO19_SSP2_RXD               MFP_CFG(GPIO19, AF7)
++#define GPIO24_SSP2_TXD               MFP_CFG(GPIO24, AF5)
++#define GPIO24_SSP2_RXD               MFP_CFG(GPIO24, AF4)
++#define GPIO27_SSP2_TXD               MFP_CFG(GPIO27, AF2)
++#define GPIO27_SSP2_RXD               MFP_CFG(GPIO27, AF5)
++#define GPIO28_SSP2_TXD               MFP_CFG(GPIO28, AF5)
++#define GPIO28_SSP2_RXD               MFP_CFG(GPIO28, AF2)
++#define GPIO35_SSP2_TXD               MFP_CFG(GPIO35, AF7)
++#define GPIO35_SSP2_RXD               MFP_CFG(GPIO35, AF6)
++#define GPIO66_SSP2_TXD               MFP_CFG(GPIO66, AF4)
++#define GPIO66_SSP2_RXD               MFP_CFG(GPIO66, AF2)
++#define GPIO67_SSP2_TXD               MFP_CFG(GPIO67, AF2)
++#define GPIO67_SSP2_RXD               MFP_CFG(GPIO67, AF4)
++#define GPIO36_SSP2_TXD               MFP_CFG(GPIO36, AF7)
++
++/* SSP3 */
++#define GPIO69_SSP3_FRM               MFP_CFG_X(GPIO69, AF2, DS08X, DRIVE_LOW)
++#define GPIO68_SSP3_SCLK      MFP_CFG_X(GPIO68, AF2, DS08X, FLOAT)
++#define GPIO92_SSP3_FRM               MFP_CFG_X(GPIO92, AF1, DS08X, DRIVE_LOW)
++#define GPIO91_SSP3_SCLK      MFP_CFG_X(GPIO91, AF1, DS08X, FLOAT)
++#define GPIO70_SSP3_TXD               MFP_CFG_X(GPIO70, AF2, DS08X, DRIVE_LOW)
++#define GPIO70_SSP3_RXD               MFP_CFG_X(GPIO70, AF5, DS08X, FLOAT)
++#define GPIO71_SSP3_TXD               MFP_CFG_X(GPIO71, AF5, DS08X, DRIVE_LOW)
++#define GPIO71_SSP3_RXD               MFP_CFG_X(GPIO71, AF2, DS08X, FLOAT)
++#define GPIO93_SSP3_TXD               MFP_CFG_X(GPIO93, AF1, DS08X, DRIVE_LOW)
++#define GPIO93_SSP3_RXD               MFP_CFG_X(GPIO93, AF5, DS08X, FLOAT)
++#define GPIO94_SSP3_TXD               MFP_CFG_X(GPIO94, AF5, DS08X, DRIVE_LOW)
++#define GPIO94_SSP3_RXD               MFP_CFG_X(GPIO94, AF1, DS08X, FLOAT)
++
++/* SSP4 */
++#define GPIO95_SSP4_SCLK      MFP_CFG_LPM(GPIO95, AF1, PULL_HIGH)
++#define GPIO96_SSP4_FRM               MFP_CFG_LPM(GPIO96, AF1, PULL_HIGH)
++#define GPIO97_SSP4_TXD               MFP_CFG_LPM(GPIO97, AF1, PULL_HIGH)
++#define GPIO97_SSP4_RXD               MFP_CFG_LPM(GPIO97, AF5, PULL_HIGH)
++#define GPIO98_SSP4_TXD               MFP_CFG_LPM(GPIO98, AF5, PULL_HIGH)
++#define GPIO98_SSP4_RXD               MFP_CFG_LPM(GPIO98, AF1, PULL_HIGH)
++
++/* UART1 */
++#define GPIO32_UART1_CTS      MFP_CFG_LPM(GPIO32,  AF2, FLOAT)
++#define GPIO37_UART1_CTS      MFP_CFG_LPM(GPIO37,  AF4, FLOAT)
++#define GPIO79_UART1_CTS      MFP_CFG_LPM(GPIO79,  AF1, FLOAT)
++#define GPIO84_UART1_CTS      MFP_CFG_LPM(GPIO84,  AF3, FLOAT)
++#define GPIO101_UART1_CTS     MFP_CFG_LPM(GPIO101, AF1, FLOAT)
++#define GPIO106_UART1_CTS     MFP_CFG_LPM(GPIO106, AF6, FLOAT)
++
++#define GPIO32_UART1_RTS      MFP_CFG_LPM(GPIO32,  AF4, FLOAT)
++#define GPIO37_UART1_RTS      MFP_CFG_LPM(GPIO37,  AF2, FLOAT)
++#define GPIO79_UART1_RTS      MFP_CFG_LPM(GPIO79,  AF3, FLOAT)
++#define GPIO84_UART1_RTS      MFP_CFG_LPM(GPIO84,  AF1, FLOAT)
++#define GPIO101_UART1_RTS     MFP_CFG_LPM(GPIO101, AF6, FLOAT)
++#define GPIO106_UART1_RTS     MFP_CFG_LPM(GPIO106, AF1, FLOAT)
++
++#define GPIO34_UART1_DSR      MFP_CFG_LPM(GPIO34,  AF2, FLOAT)
++#define GPIO36_UART1_DSR      MFP_CFG_LPM(GPIO36,  AF4, FLOAT)
++#define GPIO81_UART1_DSR      MFP_CFG_LPM(GPIO81,  AF1, FLOAT)
++#define GPIO83_UART1_DSR      MFP_CFG_LPM(GPIO83,  AF3, FLOAT)
++#define GPIO103_UART1_DSR     MFP_CFG_LPM(GPIO103, AF1, FLOAT)
++#define GPIO105_UART1_DSR     MFP_CFG_LPM(GPIO105, AF6, FLOAT)
++
++#define GPIO34_UART1_DTR      MFP_CFG_LPM(GPIO34,  AF4, FLOAT)
++#define GPIO36_UART1_DTR      MFP_CFG_LPM(GPIO36,  AF2, FLOAT)
++#define GPIO81_UART1_DTR      MFP_CFG_LPM(GPIO81,  AF3, FLOAT)
++#define GPIO83_UART1_DTR      MFP_CFG_LPM(GPIO83,  AF1, FLOAT)
++#define GPIO103_UART1_DTR     MFP_CFG_LPM(GPIO103, AF6, FLOAT)
++#define GPIO105_UART1_DTR     MFP_CFG_LPM(GPIO105, AF1, FLOAT)
++
++#define GPIO35_UART1_RI               MFP_CFG_LPM(GPIO35,  AF2, FLOAT)
++#define GPIO82_UART1_RI               MFP_CFG_LPM(GPIO82,  AF1, FLOAT)
++#define GPIO104_UART1_RI      MFP_CFG_LPM(GPIO104, AF1, FLOAT)
++
++#define GPIO33_UART1_DCD      MFP_CFG_LPM(GPIO33,  AF2, FLOAT)
++#define GPIO80_UART1_DCD      MFP_CFG_LPM(GPIO80,  AF1, FLOAT)
++#define GPIO102_UART1_DCD     MFP_CFG_LPM(GPIO102, AF1, FLOAT)
++
++#define GPIO30_UART1_RXD      MFP_CFG_LPM(GPIO30,  AF2, FLOAT)
++#define GPIO31_UART1_RXD      MFP_CFG_LPM(GPIO31,  AF4, FLOAT)
++#define GPIO77_UART1_RXD      MFP_CFG_LPM(GPIO77,  AF1, FLOAT)
++#define GPIO78_UART1_RXD      MFP_CFG_LPM(GPIO78,  AF3, FLOAT)
++#define GPIO99_UART1_RXD      MFP_CFG_LPM(GPIO99,  AF1, FLOAT)
++#define GPIO100_UART1_RXD     MFP_CFG_LPM(GPIO100, AF6, FLOAT)
++#define GPIO102_UART1_RXD     MFP_CFG_LPM(GPIO102, AF6, FLOAT)
++#define GPIO104_UART1_RXD     MFP_CFG_LPM(GPIO104, AF4, FLOAT)
++
++#define GPIO30_UART1_TXD      MFP_CFG_LPM(GPIO30,  AF4, FLOAT)
++#define GPIO31_UART1_TXD      MFP_CFG_LPM(GPIO31,  AF2, FLOAT)
++#define GPIO77_UART1_TXD      MFP_CFG_LPM(GPIO77,  AF3, FLOAT)
++#define GPIO78_UART1_TXD      MFP_CFG_LPM(GPIO78,  AF1, FLOAT)
++#define GPIO99_UART1_TXD      MFP_CFG_LPM(GPIO99,  AF6, FLOAT)
++#define GPIO100_UART1_TXD     MFP_CFG_LPM(GPIO100, AF1, FLOAT)
++#define GPIO102_UART1_TXD     MFP_CFG_LPM(GPIO102, AF4, FLOAT)
++
++/* UART2 */
++#define GPIO15_UART2_CTS      MFP_CFG_LPM(GPIO15,  AF3, FLOAT)
++#define GPIO16_UART2_CTS      MFP_CFG_LPM(GPIO16,  AF5, FLOAT)
++#define GPIO111_UART2_CTS     MFP_CFG_LPM(GPIO111, AF3, FLOAT)
++#define GPIO114_UART2_CTS     MFP_CFG_LPM(GPIO114, AF1, FLOAT)
++
++#define GPIO15_UART2_RTS      MFP_CFG_LPM(GPIO15,  AF4, FLOAT)
++#define GPIO16_UART2_RTS      MFP_CFG_LPM(GPIO16,  AF4, FLOAT)
++#define GPIO114_UART2_RTS     MFP_CFG_LPM(GPIO114, AF3, FLOAT)
++#define GPIO111_UART2_RTS     MFP_CFG_LPM(GPIO111, AF1, FLOAT)
++
++#define GPIO18_UART2_RXD      MFP_CFG_LPM(GPIO18,  AF5, FLOAT)
++#define GPIO19_UART2_RXD      MFP_CFG_LPM(GPIO19,  AF4, FLOAT)
++#define GPIO112_UART2_RXD     MFP_CFG_LPM(GPIO112, AF1, FLOAT)
++#define GPIO113_UART2_RXD     MFP_CFG_LPM(GPIO113, AF3, FLOAT)
++
++#define GPIO18_UART2_TXD      MFP_CFG_LPM(GPIO18,  AF4, FLOAT)
++#define GPIO19_UART2_TXD      MFP_CFG_LPM(GPIO19,  AF5, FLOAT)
++#define GPIO112_UART2_TXD     MFP_CFG_LPM(GPIO112, AF3, FLOAT)
++#define GPIO113_UART2_TXD     MFP_CFG_LPM(GPIO113, AF1, FLOAT)
++
++/* UART3 */
++#define GPIO91_UART3_CTS      MFP_CFG_LPM(GPIO91,  AF2, FLOAT)
++#define GPIO92_UART3_CTS      MFP_CFG_LPM(GPIO92,  AF4, FLOAT)
++#define GPIO107_UART3_CTS     MFP_CFG_LPM(GPIO107, AF1, FLOAT)
++#define GPIO108_UART3_CTS     MFP_CFG_LPM(GPIO108, AF3, FLOAT)
++
++#define GPIO91_UART3_RTS      MFP_CFG_LPM(GPIO91,  AF4, FLOAT)
++#define GPIO92_UART3_RTS      MFP_CFG_LPM(GPIO92,  AF2, FLOAT)
++#define GPIO107_UART3_RTS     MFP_CFG_LPM(GPIO107, AF3, FLOAT)
++#define GPIO108_UART3_RTS     MFP_CFG_LPM(GPIO108, AF1, FLOAT)
++
++#define GPIO7_UART3_RXD               MFP_CFG_LPM(GPIO7,   AF2, FLOAT)
++#define GPIO8_UART3_RXD               MFP_CFG_LPM(GPIO8,   AF6, FLOAT)
++#define GPIO93_UART3_RXD      MFP_CFG_LPM(GPIO93,  AF4, FLOAT)
++#define GPIO94_UART3_RXD      MFP_CFG_LPM(GPIO94,  AF2, FLOAT)
++#define GPIO109_UART3_RXD     MFP_CFG_LPM(GPIO109, AF3, FLOAT)
++#define GPIO110_UART3_RXD     MFP_CFG_LPM(GPIO110, AF1, FLOAT)
++
++#define GPIO7_UART3_TXD               MFP_CFG_LPM(GPIO7,   AF6, FLOAT)
++#define GPIO8_UART3_TXD               MFP_CFG_LPM(GPIO8,   AF2, FLOAT)
++#define GPIO93_UART3_TXD      MFP_CFG_LPM(GPIO93,  AF2, FLOAT)
++#define GPIO94_UART3_TXD      MFP_CFG_LPM(GPIO94,  AF4, FLOAT)
++#define GPIO109_UART3_TXD     MFP_CFG_LPM(GPIO109, AF1, FLOAT)
++#define GPIO110_UART3_TXD     MFP_CFG_LPM(GPIO110, AF3, FLOAT)
++
++/* USB Host */
++#define GPIO0_2_USBH_PEN      MFP_CFG(GPIO0_2, AF1)
++#define GPIO1_2_USBH_PWR      MFP_CFG(GPIO1_2, AF1)
++
++/* USB P3 */
++#define GPIO77_USB_P3_1               MFP_CFG(GPIO77,  AF2)
++#define GPIO78_USB_P3_2               MFP_CFG(GPIO78,  AF2)
++#define GPIO79_USB_P3_3               MFP_CFG(GPIO79,  AF2)
++#define GPIO80_USB_P3_4               MFP_CFG(GPIO80,  AF2)
++#define GPIO81_USB_P3_5               MFP_CFG(GPIO81,  AF2)
++#define GPIO82_USB_P3_6               MFP_CFG(GPIO82,  AF2)
++
++/* PWM */
++#define GPIO17_PWM0_OUT               MFP_CFG(GPIO17, AF1)
++#define GPIO18_PWM1_OUT               MFP_CFG(GPIO18, AF1)
++#define GPIO19_PWM2_OUT               MFP_CFG(GPIO19, AF1)
++#define GPIO20_PWM3_OUT               MFP_CFG(GPIO20, AF1)
++
++/* CIR */
++#define GPIO8_CIR_OUT         MFP_CFG(GPIO8, AF5)
++#define GPIO16_CIR_OUT                MFP_CFG(GPIO16, AF3)
++
++#define GPIO20_OW_DQ_IN               MFP_CFG(GPIO20, AF5)
++#define GPIO126_OW_DQ         MFP_CFG(GPIO126, AF2)
++
++#define GPIO0_DF_RDY          MFP_CFG(GPIO0, AF1)
++#define GPIO7_CLK_BYPASS_XSC  MFP_CFG(GPIO7, AF7)
++#define GPIO17_EXT_SYNC_MVT_0 MFP_CFG(GPIO17, AF6)
++#define GPIO18_EXT_SYNC_MVT_1 MFP_CFG(GPIO18, AF6)
++#define GPIO19_OST_CHOUT_MVT_0        MFP_CFG(GPIO19, AF6)
++#define GPIO20_OST_CHOUT_MVT_1        MFP_CFG(GPIO20, AF6)
++#define GPIO49_48M_CLK                MFP_CFG(GPIO49, AF2)
++#define GPIO126_EXT_CLK               MFP_CFG(GPIO126, AF3)
++#define GPIO127_CLK_BYPASS_GB MFP_CFG(GPIO127, AF7)
++#define GPIO71_EXT_MATCH_MVT  MFP_CFG(GPIO71, AF6)
++
++#define GPIO3_uIO_IN          MFP_CFG(GPIO3, AF1)
++
++#define GPIO4_uSIM_CARD_STATE MFP_CFG(GPIO4, AF1)
++#define GPIO5_uSIM_uCLK               MFP_CFG(GPIO5, AF1)
++#define GPIO6_uSIM_uRST               MFP_CFG(GPIO6, AF1)
++#define GPIO16_uSIM_UVS_0     MFP_CFG(GPIO16, AF1)
++
++#define GPIO9_SCIO            MFP_CFG(GPIO9, AF1)
++#define GPIO20_RTC_MVT                MFP_CFG(GPIO20, AF4)
++#define GPIO126_RTC_MVT               MFP_CFG(GPIO126, AF1)
++
++/*
++ * PXA300 specific MFP configurations
++ */
++#ifdef CONFIG_CPU_PXA300
++#define GPIO99_USB_P2_2               MFP_CFG(GPIO99, AF2)
++#define GPIO99_USB_P2_5               MFP_CFG(GPIO99, AF3)
++#define GPIO99_USB_P2_6               MFP_CFG(GPIO99, AF4)
++#define GPIO100_USB_P2_2      MFP_CFG(GPIO100, AF4)
++#define GPIO100_USB_P2_5      MFP_CFG(GPIO100, AF5)
++#define GPIO101_USB_P2_1      MFP_CFG(GPIO101, AF2)
++#define GPIO102_USB_P2_4      MFP_CFG(GPIO102, AF2)
++#define GPIO104_USB_P2_3      MFP_CFG(GPIO104, AF2)
++#define GPIO105_USB_P2_5      MFP_CFG(GPIO105, AF2)
++#define GPIO100_USB_P2_6      MFP_CFG(GPIO100, AF2)
++#define GPIO106_USB_P2_7      MFP_CFG(GPIO106, AF2)
++#define GPIO103_USB_P2_8      MFP_CFG(GPIO103, AF2)
++
++/* U2D UTMI */
++#define GPIO38_UTM_CLK                MFP_CFG(GPIO38,  AF1)
++#define GPIO26_U2D_RXERROR    MFP_CFG(GPIO26,  AF3)
++#define GPIO50_U2D_RXERROR    MFP_CFG(GPIO50,  AF1)
++#define GPIO89_U2D_RXERROR    MFP_CFG(GPIO89,  AF5)
++#define GPIO24_UTM_RXVALID    MFP_CFG(GPIO24,  AF3)
++#define GPIO48_UTM_RXVALID    MFP_CFG(GPIO48,  AF2)
++#define GPIO87_UTM_RXVALID    MFP_CFG(GPIO87,  AF5)
++#define GPIO25_UTM_RXACTIVE   MFP_CFG(GPIO25,  AF3)
++#define GPIO47_UTM_RXACTIVE   MFP_CFG(GPIO47,  AF2)
++#define GPIO49_UTM_RXACTIVE   MFP_CFG(GPIO49,  AF1)
++#define GPIO88_UTM_RXACTIVE   MFP_CFG(GPIO88,  AF5)
++#define GPIO53_UTM_TXREADY    MFP_CFG(GPIO53,  AF1)
++#define GPIO67_UTM_LINESTATE_0        MFP_CFG(GPIO67,  AF3)
++#define GPIO92_UTM_LINESTATE_0        MFP_CFG(GPIO92,  AF3)
++#define GPIO104_UTM_LINESTATE_0       MFP_CFG(GPIO104, AF3)
++#define GPIO109_UTM_LINESTATE_0       MFP_CFG(GPIO109, AF4)
++#define GPIO68_UTM_LINESTATE_1        MFP_CFG(GPIO68,  AF3)
++#define GPIO93_UTM_LINESTATE_1        MFP_CFG(GPIO93,  AF3)
++#define GPIO105_UTM_LINESTATE_1       MFP_CFG(GPIO105, AF3)
++#define GPIO27_U2D_OPMODE_0   MFP_CFG(GPIO27,  AF4)
++#define GPIO51_U2D_OPMODE_0   MFP_CFG(GPIO51,  AF2)
++#define GPIO90_U2D_OPMODE_0   MFP_CFG(GPIO90,  AF7)
++#define GPIO28_U2D_OPMODE_1   MFP_CFG(GPIO28,  AF4)
++#define GPIO52_U2D_OPMODE_1   MFP_CFG(GPIO52,  AF2)
++#define GPIO106_U2D_OPMODE_1  MFP_CFG(GPIO106, AF3)
++#define GPIO110_U2D_OPMODE_1  MFP_CFG(GPIO110, AF5)
++#define GPIO76_U2D_RESET      MFP_CFG(GPIO76,  AF1)
++#define GPIO95_U2D_RESET      MFP_CFG(GPIO95,  AF2)
++#define GPIO100_U2D_RESET     MFP_CFG(GPIO100, AF3)
++#define GPIO66_U2D_SUSPEND    MFP_CFG(GPIO66,  AF3)
++#define GPIO98_U2D_SUSPEND    MFP_CFG(GPIO98,  AF2)
++#define GPIO103_U2D_SUSPEND   MFP_CFG(GPIO103, AF3)
++#define GPIO65_U2D_TERM_SEL   MFP_CFG(GPIO65,  AF5)
++#define GPIO97_U2D_TERM_SEL   MFP_CFG(GPIO97,  AF3)
++#define GPIO102_U2D_TERM_SEL  MFP_CFG(GPIO102, AF5)
++#define GPIO29_U2D_TXVALID    MFP_CFG(GPIO29,  AF3)
++#define GPIO52_U2D_TXVALID    MFP_CFG(GPIO52,  AF4)
++#define GPIO69_U2D_TXVALID    MFP_CFG(GPIO69,  AF3)
++#define GPIO85_U2D_TXVALID    MFP_CFG(GPIO85,  AF7)
++#define GPIO64_U2D_XCVR_SEL   MFP_CFG(GPIO64,  AF5)
++#define GPIO96_U2D_XCVR_SEL   MFP_CFG(GPIO96,  AF3)
++#define GPIO101_U2D_XCVR_SEL  MFP_CFG(GPIO101, AF5)
++#define GPIO30_UTM_PHYDATA_0  MFP_CFG(GPIO30,  AF3)
++#define GPIO31_UTM_PHYDATA_1  MFP_CFG(GPIO31,  AF3)
++#define GPIO32_UTM_PHYDATA_2  MFP_CFG(GPIO32,  AF3)
++#define GPIO33_UTM_PHYDATA_3  MFP_CFG(GPIO33,  AF3)
++#define GPIO34_UTM_PHYDATA_4  MFP_CFG(GPIO34,  AF3)
++#define GPIO35_UTM_PHYDATA_5  MFP_CFG(GPIO35,  AF3)
++#define GPIO36_UTM_PHYDATA_6  MFP_CFG(GPIO36,  AF3)
++#define GPIO37_UTM_PHYDATA_7  MFP_CFG(GPIO37,  AF3)
++#define GPIO39_UTM_PHYDATA_0  MFP_CFG(GPIO39,  AF3)
++#define GPIO40_UTM_PHYDATA_1  MFP_CFG(GPIO40,  AF3)
++#define GPIO41_UTM_PHYDATA_2  MFP_CFG(GPIO41,  AF3)
++#define GPIO42_UTM_PHYDATA_3  MFP_CFG(GPIO42,  AF3)
++#define GPIO43_UTM_PHYDATA_4  MFP_CFG(GPIO43,  AF3)
++#define GPIO44_UTM_PHYDATA_5  MFP_CFG(GPIO44,  AF3)
++#define GPIO45_UTM_PHYDATA_6  MFP_CFG(GPIO45,  AF3)
++#define GPIO46_UTM_PHYDATA_7  MFP_CFG(GPIO46,  AF3)
++#endif /* CONFIG_CPU_PXA300 */
++
++/*
++ * PXA310 specific MFP configurations
++ */
++#ifdef CONFIG_CPU_PXA310
++/* USB P2 */
++#define GPIO36_USB_P2_1               MFP_CFG(GPIO36, AF1)
++#define GPIO30_USB_P2_2               MFP_CFG(GPIO30, AF1)
++#define GPIO35_USB_P2_3               MFP_CFG(GPIO35, AF1)
++#define GPIO32_USB_P2_4               MFP_CFG(GPIO32, AF1)
++#define GPIO34_USB_P2_5               MFP_CFG(GPIO34, AF1)
++#define GPIO31_USB_P2_6               MFP_CFG(GPIO31, AF1)
++
++/* MMC1 */
++#define GPIO24_MMC1_CMD               MFP_CFG(GPIO24, AF3)
++#define GPIO29_MMC1_DAT0      MFP_CFG(GPIO29, AF3)
++
++/* MMC3 */
++#define GPIO103_MMC3_CLK      MFP_CFG(GPIO103, AF2)
++#define GPIO105_MMC3_CMD      MFP_CFG(GPIO105, AF2)
++#define GPIO11_2_MMC3_CLK     MFP_CFG(GPIO11_2, AF1)
++#define GPIO12_2_MMC3_CMD     MFP_CFG(GPIO12_2, AF1)
++#define GPIO7_2_MMC3_DAT0     MFP_CFG(GPIO7_2, AF1)
++#define GPIO8_2_MMC3_DAT1     MFP_CFG(GPIO8_2, AF1)
++#define GPIO9_2_MMC3_DAT2     MFP_CFG(GPIO9_2, AF1)
++#define GPIO10_2_MMC3_DAT3    MFP_CFG(GPIO10_2, AF1)
++
++/* ULPI */
++#define GPIO38_ULPI_CLK               MFP_CFG(GPIO38, AF1)
++#define GPIO30_ULPI_DATA_OUT_0        MFP_CFG(GPIO30, AF3)
++#define GPIO31_ULPI_DATA_OUT_1        MFP_CFG(GPIO31, AF3)
++#define GPIO32_ULPI_DATA_OUT_2        MFP_CFG(GPIO32, AF3)
++#define GPIO33_ULPI_DATA_OUT_3        MFP_CFG(GPIO33, AF3)
++#define GPIO34_ULPI_DATA_OUT_4        MFP_CFG(GPIO34, AF3)
++#define GPIO35_ULPI_DATA_OUT_5        MFP_CFG(GPIO35, AF3)
++#define GPIO36_ULPI_DATA_OUT_6        MFP_CFG(GPIO36, AF3)
++#define GPIO37_ULPI_DATA_OUT_7        MFP_CFG(GPIO37, AF3)
++#define GPIO33_ULPI_OTG_INTR  MFP_CFG(GPIO33, AF1)
++
++#define ULPI_DIR      MFP_CFG_DRV(ULPI_DIR, MFP_AF0, MFP_DS01X)
++#define ULPI_NXT      MFP_CFG_DRV(ULPI_NXT, MFP_AF0, MFP_DS01X)
++#define ULPI_STP      MFP_CFG_DRV(ULPI_STP, MFP_AF0, MFP_DS01X)
++#endif /* CONFIG_CPU_PXA310 */
++
++#endif /* __ASM_ARCH_MFP_PXA300_H */
+--- /dev/null
++++ linux-2.6.23/include/asm-arm/arch-pxa/mfp-pxa320.h
+@@ -0,0 +1,446 @@
++/*
++ * linux/include/asm-arm/arch-pxa/mfp-pxa320.h
++ *
++ * PXA320 specific MFP configuration definitions
++ *
++ * Copyright (C) 2007 Marvell International Ltd.
++ * 2007-08-21: eric miao <eric.y.miao@gmail.com>
++ *             initial version
++ *
++ *  This program is free software; you can 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_MFP_PXA320_H
++#define __ASM_ARCH_MFP_PXA320_H
++
++#include <asm/arch/mfp.h>
++
++/* GPIO */
++#define GPIO46_GPIO           MFP_CFG(GPIO6, AF0)
++#define GPIO49_GPIO           MFP_CFG(GPIO49, AF0)
++#define GPIO50_GPIO           MFP_CFG(GPIO50, AF0)
++#define GPIO51_GPIO           MFP_CFG(GPIO51, AF0)
++#define GPIO52_GPIO           MFP_CFG(GPIO52, AF0)
++
++#define GPIO7_2_GPIO          MFP_CFG(GPIO7_2, AF0)
++#define GPIO8_2_GPIO          MFP_CFG(GPIO8_2, AF0)
++#define GPIO9_2_GPIO          MFP_CFG(GPIO9_2, AF0)
++#define GPIO10_2_GPIO         MFP_CFG(GPIO10_2, AF0)
++#define GPIO11_2_GPIO         MFP_CFG(GPIO11_2, AF0)
++#define GPIO12_2_GPIO         MFP_CFG(GPIO12_2, AF0)
++#define GPIO13_2_GPIO         MFP_CFG(GPIO13_2, AF0)
++#define GPIO14_2_GPIO         MFP_CFG(GPIO14_2, AF0)
++#define GPIO15_2_GPIO         MFP_CFG(GPIO15_2, AF0)
++#define GPIO16_2_GPIO         MFP_CFG(GPIO16_2, AF0)
++#define GPIO17_2_GPIO         MFP_CFG(GPIO17_2, AF0)
++
++/* Chip Select */
++#define GPIO4_nCS3            MFP_CFG(GPIO4, AF1)
++
++/* AC97 */
++#define GPIO34_AC97_SYSCLK    MFP_CFG(GPIO34, AF1)
++#define GPIO39_AC97_BITCLK    MFP_CFG(GPIO39, AF1)
++#define GPIO40_AC97_nACRESET  MFP_CFG(GPIO40, AF1)
++#define GPIO35_AC97_SDATA_IN_0        MFP_CFG(GPIO35, AF1)
++#define GPIO36_AC97_SDATA_IN_1        MFP_CFG(GPIO36, AF1)
++#define GPIO32_AC97_SDATA_IN_2        MFP_CFG(GPIO32, AF2)
++#define GPIO33_AC97_SDATA_IN_3        MFP_CFG(GPIO33, AF2)
++#define GPIO11_AC97_SDATA_IN_2        MFP_CFG(GPIO11, AF3)
++#define GPIO12_AC97_SDATA_IN_3        MFP_CFG(GPIO12, AF3)
++#define GPIO37_AC97_SDATA_OUT MFP_CFG(GPIO37, AF1)
++#define GPIO38_AC97_SYNC      MFP_CFG(GPIO38, AF1)
++
++/* I2C */
++#define GPIO32_I2C_SCL                MFP_CFG_LPM(GPIO32, AF1, PULL_HIGH)
++#define GPIO33_I2C_SDA                MFP_CFG_LPM(GPIO33, AF1, PULL_HIGH)
++
++/* QCI */
++#define GPIO49_CI_DD_0                MFP_CFG_DRV(GPIO49, AF1, DS04X)
++#define GPIO50_CI_DD_1                MFP_CFG_DRV(GPIO50, AF1, DS04X)
++#define GPIO51_CI_DD_2                MFP_CFG_DRV(GPIO51, AF1, DS04X)
++#define GPIO52_CI_DD_3                MFP_CFG_DRV(GPIO52, AF1, DS04X)
++#define GPIO53_CI_DD_4                MFP_CFG_DRV(GPIO53, AF1, DS04X)
++#define GPIO54_CI_DD_5                MFP_CFG_DRV(GPIO54, AF1, DS04X)
++#define GPIO55_CI_DD_6                MFP_CFG_DRV(GPIO55, AF1, DS04X)
++#define GPIO56_CI_DD_7                MFP_CFG_DRV(GPIO56, AF0, DS04X)
++#define GPIO57_CI_DD_8                MFP_CFG_DRV(GPIO57, AF1, DS04X)
++#define GPIO58_CI_DD_9                MFP_CFG_DRV(GPIO58, AF1, DS04X)
++#define GPIO59_CI_MCLK                MFP_CFG_DRV(GPIO59, AF0, DS04X)
++#define GPIO60_CI_PCLK                MFP_CFG_DRV(GPIO60, AF0, DS04X)
++#define GPIO61_CI_HSYNC               MFP_CFG_DRV(GPIO61, AF0, DS04X)
++#define GPIO62_CI_VSYNC               MFP_CFG_DRV(GPIO62, AF0, DS04X)
++
++#define GPIO31_CIR_OUT                MFP_CFG(GPIO31, AF5)
++
++#define GPIO0_2_CLK_EXT               MFP_CFG(GPIO0_2, AF3)
++#define GPIO0_DRQ             MFP_CFG(GPIO0, AF2)
++#define GPIO11_EXT_SYNC0      MFP_CFG(GPIO11, AF5)
++#define GPIO12_EXT_SYNC1      MFP_CFG(GPIO12, AF6)
++#define GPIO0_2_HZ_CLK                MFP_CFG(GPIO0_2, AF1)
++#define GPIO14_HZ_CLK         MFP_CFG(GPIO14, AF4)
++#define GPIO30_ICP_RXD                MFP_CFG(GPIO30, AF1)
++#define GPIO31_ICP_TXD                MFP_CFG(GPIO31, AF1)
++
++#define GPIO83_KP_DKIN_0      MFP_CFG_LPM(GPIO83, AF3, FLOAT)
++#define GPIO84_KP_DKIN_1      MFP_CFG_LPM(GPIO84, AF3, FLOAT)
++#define GPIO85_KP_DKIN_2      MFP_CFG_LPM(GPIO85, AF3, FLOAT)
++#define GPIO86_KP_DKIN_3      MFP_CFG_LPM(GPIO86, AF3, FLOAT)
++
++#define GPIO105_KP_DKIN_0     MFP_CFG_LPM(GPIO105, AF2, FLOAT)
++#define GPIO106_KP_DKIN_1     MFP_CFG_LPM(GPIO106, AF2, FLOAT)
++#define GPIO107_KP_DKIN_2     MFP_CFG_LPM(GPIO107, AF2, FLOAT)
++#define GPIO108_KP_DKIN_3     MFP_CFG_LPM(GPIO108, AF2, FLOAT)
++#define GPIO109_KP_DKIN_4     MFP_CFG_LPM(GPIO109, AF2, FLOAT)
++#define GPIO110_KP_DKIN_5     MFP_CFG_LPM(GPIO110, AF2, FLOAT)
++#define GPIO111_KP_DKIN_6     MFP_CFG_LPM(GPIO111, AF2, FLOAT)
++#define GPIO112_KP_DKIN_7     MFP_CFG_LPM(GPIO112, AF2, FLOAT)
++
++#define GPIO113_KP_DKIN_0     MFP_CFG_LPM(GPIO113, AF2, FLOAT)
++#define GPIO114_KP_DKIN_1     MFP_CFG_LPM(GPIO114, AF2, FLOAT)
++#define GPIO115_KP_DKIN_2     MFP_CFG_LPM(GPIO115, AF2, FLOAT)
++#define GPIO116_KP_DKIN_3     MFP_CFG_LPM(GPIO116, AF2, FLOAT)
++#define GPIO117_KP_DKIN_4     MFP_CFG_LPM(GPIO117, AF2, FLOAT)
++#define GPIO118_KP_DKIN_5     MFP_CFG_LPM(GPIO118, AF2, FLOAT)
++#define GPIO119_KP_DKIN_6     MFP_CFG_LPM(GPIO119, AF2, FLOAT)
++#define GPIO120_KP_DKIN_7     MFP_CFG_LPM(GPIO120, AF2, FLOAT)
++
++#define GPIO127_KP_DKIN_0     MFP_CFG_LPM(GPIO127, AF2, FLOAT)
++#define GPIO126_KP_DKIN_1     MFP_CFG_LPM(GPIO126, AF2, FLOAT)
++
++#define GPIO2_2_KP_DKIN_0     MFP_CFG_LPM(GPIO2_2, AF2, FLOAT)
++#define GPIO3_2_KP_DKIN_1     MFP_CFG_LPM(GPIO3_2, AF2, FLOAT)
++#define GPIO125_KP_DKIN_2     MFP_CFG_LPM(GPIO125, AF2, FLOAT)
++#define GPIO124_KP_DKIN_3     MFP_CFG_LPM(GPIO124, AF2, FLOAT)
++#define GPIO123_KP_DKIN_4     MFP_CFG_LPM(GPIO123, AF2, FLOAT)
++#define GPIO122_KP_DKIN_5     MFP_CFG_LPM(GPIO122, AF2, FLOAT)
++#define GPIO121_KP_DKIN_6     MFP_CFG_LPM(GPIO121, AF2, FLOAT)
++#define GPIO4_2_KP_DKIN_7     MFP_CFG_LPM(GPIO4_2, AF2, FLOAT)
++
++#define GPIO113_KP_MKIN_0     MFP_CFG_LPM(GPIO113, AF1, FLOAT)
++#define GPIO114_KP_MKIN_1     MFP_CFG_LPM(GPIO114, AF1, FLOAT)
++#define GPIO115_KP_MKIN_2     MFP_CFG_LPM(GPIO115, AF1, FLOAT)
++#define GPIO116_KP_MKIN_3     MFP_CFG_LPM(GPIO116, AF1, FLOAT)
++#define GPIO117_KP_MKIN_4     MFP_CFG_LPM(GPIO117, AF1, FLOAT)
++#define GPIO118_KP_MKIN_5     MFP_CFG_LPM(GPIO118, AF1, FLOAT)
++#define GPIO119_KP_MKIN_6     MFP_CFG_LPM(GPIO119, AF1, FLOAT)
++#define GPIO120_KP_MKIN_7     MFP_CFG_LPM(GPIO120, AF1, FLOAT)
++
++#define GPIO83_KP_MKOUT_0     MFP_CFG_LPM(GPIO83, AF2, DRIVE_HIGH)
++#define GPIO84_KP_MKOUT_1     MFP_CFG_LPM(GPIO84, AF2, DRIVE_HIGH)
++#define GPIO85_KP_MKOUT_2     MFP_CFG_LPM(GPIO85, AF2, DRIVE_HIGH)
++#define GPIO86_KP_MKOUT_3     MFP_CFG_LPM(GPIO86, AF2, DRIVE_HIGH)
++#define GPIO13_KP_MKOUT_4     MFP_CFG_LPM(GPIO13, AF3, DRIVE_HIGH)
++#define GPIO14_KP_MKOUT_5     MFP_CFG_LPM(GPIO14, AF3, DRIVE_HIGH)
++
++#define GPIO121_KP_MKOUT_0    MFP_CFG_LPM(GPIO121, AF1, DRIVE_HIGH)
++#define GPIO122_KP_MKOUT_1    MFP_CFG_LPM(GPIO122, AF1, DRIVE_HIGH)
++#define GPIO123_KP_MKOUT_2    MFP_CFG_LPM(GPIO123, AF1, DRIVE_HIGH)
++#define GPIO124_KP_MKOUT_3    MFP_CFG_LPM(GPIO124, AF1, DRIVE_HIGH)
++#define GPIO125_KP_MKOUT_4    MFP_CFG_LPM(GPIO125, AF1, DRIVE_HIGH)
++#define GPIO126_KP_MKOUT_5    MFP_CFG_LPM(GPIO126, AF1, DRIVE_HIGH)
++#define GPIO127_KP_MKOUT_6    MFP_CFG_LPM(GPIO127, AF1, DRIVE_HIGH)
++#define GPIO5_2_KP_MKOUT_7    MFP_CFG_LPM(GPIO5_2, AF1, DRIVE_HIGH)
++
++/* LCD */
++#define GPIO6_2_LCD_LDD_0     MFP_CFG_DRV(GPIO6_2, AF1, DS01X)
++#define GPIO7_2_LCD_LDD_1     MFP_CFG_DRV(GPIO7_2, AF1, DS01X)
++#define GPIO8_2_LCD_LDD_2     MFP_CFG_DRV(GPIO8_2, AF1, DS01X)
++#define GPIO9_2_LCD_LDD_3     MFP_CFG_DRV(GPIO9_2, AF1, DS01X)
++#define GPIO10_2_LCD_LDD_4    MFP_CFG_DRV(GPIO10_2, AF1, DS01X)
++#define GPIO11_2_LCD_LDD_5    MFP_CFG_DRV(GPIO11_2, AF1, DS01X)
++#define GPIO12_2_LCD_LDD_6    MFP_CFG_DRV(GPIO12_2, AF1, DS01X)
++#define GPIO13_2_LCD_LDD_7    MFP_CFG_DRV(GPIO13_2, AF1, DS01X)
++#define GPIO63_LCD_LDD_8      MFP_CFG_DRV(GPIO63, AF1, DS01X)
++#define GPIO64_LCD_LDD_9      MFP_CFG_DRV(GPIO64, AF1, DS01X)
++#define GPIO65_LCD_LDD_10     MFP_CFG_DRV(GPIO65, AF1, DS01X)
++#define GPIO66_LCD_LDD_11     MFP_CFG_DRV(GPIO66, AF1, DS01X)
++#define GPIO67_LCD_LDD_12     MFP_CFG_DRV(GPIO67, AF1, DS01X)
++#define GPIO68_LCD_LDD_13     MFP_CFG_DRV(GPIO68, AF1, DS01X)
++#define GPIO69_LCD_LDD_14     MFP_CFG_DRV(GPIO69, AF1, DS01X)
++#define GPIO70_LCD_LDD_15     MFP_CFG_DRV(GPIO70, AF1, DS01X)
++#define GPIO71_LCD_LDD_16     MFP_CFG_DRV(GPIO71, AF1, DS01X)
++#define GPIO72_LCD_LDD_17     MFP_CFG_DRV(GPIO72, AF1, DS01X)
++#define GPIO73_LCD_CS_N               MFP_CFG_DRV(GPIO73, AF2, DS01X)
++#define GPIO74_LCD_VSYNC      MFP_CFG_DRV(GPIO74, AF2, DS01X)
++#define GPIO14_2_LCD_FCLK     MFP_CFG_DRV(GPIO14_2, AF1, DS01X)
++#define GPIO15_2_LCD_LCLK     MFP_CFG_DRV(GPIO15_2, AF1, DS01X)
++#define GPIO16_2_LCD_PCLK     MFP_CFG_DRV(GPIO16_2, AF1, DS01X)
++#define GPIO17_2_LCD_BIAS     MFP_CFG_DRV(GPIO17_2, AF1, DS01X)
++#define GPIO64_LCD_VSYNC      MFP_CFG_DRV(GPIO64, AF2, DS01X)
++#define GPIO63_LCD_CS_N               MFP_CFG_DRV(GPIO63, AF2, DS01X)
++
++#define GPIO6_2_MLCD_DD_0     MFP_CFG_DRV(GPIO6_2, AF7, DS08X)
++#define GPIO7_2_MLCD_DD_1     MFP_CFG_DRV(GPIO7_2, AF7, DS08X)
++#define GPIO8_2_MLCD_DD_2     MFP_CFG_DRV(GPIO8_2, AF7, DS08X)
++#define GPIO9_2_MLCD_DD_3     MFP_CFG_DRV(GPIO9_2, AF7, DS08X)
++#define GPIO10_2_MLCD_DD_4    MFP_CFG_DRV(GPIO10_2, AF7, DS08X)
++#define GPIO11_2_MLCD_DD_5    MFP_CFG_DRV(GPIO11_2, AF7, DS08X)
++#define GPIO12_2_MLCD_DD_6    MFP_CFG_DRV(GPIO12_2, AF7, DS08X)
++#define GPIO13_2_MLCD_DD_7    MFP_CFG_DRV(GPIO13_2, AF7, DS08X)
++#define GPIO63_MLCD_DD_8      MFP_CFG_DRV(GPIO63, AF7, DS08X)
++#define GPIO64_MLCD_DD_9      MFP_CFG_DRV(GPIO64, AF7, DS08X)
++#define GPIO65_MLCD_DD_10     MFP_CFG_DRV(GPIO65, AF7, DS08X)
++#define GPIO66_MLCD_DD_11     MFP_CFG_DRV(GPIO66, AF7, DS08X)
++#define GPIO67_MLCD_DD_12     MFP_CFG_DRV(GPIO67, AF7, DS08X)
++#define GPIO68_MLCD_DD_13     MFP_CFG_DRV(GPIO68, AF7, DS08X)
++#define GPIO69_MLCD_DD_14     MFP_CFG_DRV(GPIO69, AF7, DS08X)
++#define GPIO70_MLCD_DD_15     MFP_CFG_DRV(GPIO70, AF7, DS08X)
++#define GPIO71_MLCD_DD_16     MFP_CFG_DRV(GPIO71, AF7, DS08X)
++#define GPIO72_MLCD_DD_17     MFP_CFG_DRV(GPIO72, AF7, DS08X)
++#define GPIO73_MLCD_CS                MFP_CFG_DRV(GPIO73, AF7, DS08X)
++#define GPIO74_MLCD_VSYNC     MFP_CFG_DRV(GPIO74, AF7, DS08X)
++#define GPIO14_2_MLCD_FCLK    MFP_CFG_DRV(GPIO14_2, AF7, DS08X)
++#define GPIO15_2_MLCD_LCLK    MFP_CFG_DRV(GPIO15_2, AF7, DS08X)
++#define GPIO16_2_MLCD_PCLK    MFP_CFG_DRV(GPIO16_2, AF7, DS08X)
++#define GPIO17_2_MLCD_BIAS    MFP_CFG_DRV(GPIO17_2, AF7, DS08X)
++
++/* MMC1 */
++#define GPIO9_MMC1_CMD                MFP_CFG_LPM(GPIO9,  AF4, DRIVE_HIGH)
++#define GPIO22_MMC1_CLK               MFP_CFG_LPM(GPIO22, AF4, DRIVE_HIGH)
++#define GPIO23_MMC1_CMD               MFP_CFG_LPM(GPIO23, AF4, DRIVE_HIGH)
++#define GPIO30_MMC1_CLK               MFP_CFG_LPM(GPIO30, AF4, DRIVE_HIGH)
++#define GPIO31_MMC1_CMD               MFP_CFG_LPM(GPIO31, AF4, DRIVE_HIGH)
++#define GPIO5_MMC1_DAT0               MFP_CFG_LPM(GPIO5,  AF4, DRIVE_HIGH)
++#define GPIO6_MMC1_DAT1               MFP_CFG_LPM(GPIO6,  AF4, DRIVE_HIGH)
++#define GPIO7_MMC1_DAT2               MFP_CFG_LPM(GPIO7,  AF4, DRIVE_HIGH)
++#define GPIO8_MMC1_DAT3               MFP_CFG_LPM(GPIO8,  AF4, DRIVE_HIGH)
++#define GPIO18_MMC1_DAT0      MFP_CFG_LPM(GPIO18, AF4, DRIVE_HIGH)
++#define GPIO19_MMC1_DAT1      MFP_CFG_LPM(GPIO19, AF4, DRIVE_HIGH)
++#define GPIO20_MMC1_DAT2      MFP_CFG_LPM(GPIO20, AF4, DRIVE_HIGH)
++#define GPIO21_MMC1_DAT3      MFP_CFG_LPM(GPIO21, AF4, DRIVE_HIGH)
++
++#define GPIO28_MMC2_CLK               MFP_CFG_LPM(GPIO28, AF4, PULL_HIGH)
++#define GPIO29_MMC2_CMD               MFP_CFG_LPM(GPIO29, AF4, PULL_HIGH)
++#define GPIO30_MMC2_CLK               MFP_CFG_LPM(GPIO30, AF3, PULL_HIGH)
++#define GPIO31_MMC2_CMD               MFP_CFG_LPM(GPIO31, AF3, PULL_HIGH)
++#define GPIO79_MMC2_CLK               MFP_CFG_LPM(GPIO79, AF4, PULL_HIGH)
++#define GPIO80_MMC2_CMD               MFP_CFG_LPM(GPIO80, AF4, PULL_HIGH)
++
++#define GPIO5_MMC2_DAT0               MFP_CFG_LPM(GPIO5, AF2, PULL_HIGH)
++#define GPIO6_MMC2_DAT1               MFP_CFG_LPM(GPIO6, AF2, PULL_HIGH)
++#define GPIO7_MMC2_DAT2               MFP_CFG_LPM(GPIO7, AF2, PULL_HIGH)
++#define GPIO8_MMC2_DAT3               MFP_CFG_LPM(GPIO8, AF2, PULL_HIGH)
++#define GPIO24_MMC2_DAT0      MFP_CFG_LPM(GPIO24, AF4, PULL_HIGH)
++#define GPIO75_MMC2_DAT0      MFP_CFG_LPM(GPIO75, AF4, PULL_HIGH)
++#define GPIO25_MMC2_DAT1      MFP_CFG_LPM(GPIO25, AF4, PULL_HIGH)
++#define GPIO76_MMC2_DAT1      MFP_CFG_LPM(GPIO76, AF4, PULL_HIGH)
++#define GPIO26_MMC2_DAT2      MFP_CFG_LPM(GPIO26, AF4, PULL_HIGH)
++#define GPIO77_MMC2_DAT2      MFP_CFG_LPM(GPIO77, AF4, PULL_HIGH)
++#define GPIO27_MMC2_DAT3      MFP_CFG_LPM(GPIO27, AF4, PULL_HIGH)
++#define GPIO78_MMC2_DAT3      MFP_CFG_LPM(GPIO78, AF4, PULL_HIGH)
++
++/* 1-Wire */
++#define GPIO14_ONE_WIRE               MFP_CFG_LPM(GPIO14,  AF5, FLOAT)
++#define GPIO0_2_ONE_WIRE      MFP_CFG_LPM(GPIO0_2, AF2, FLOAT)
++
++/* SSP1 */
++#define GPIO87_SSP1_EXTCLK    MFP_CFG(GPIO87, AF1)
++#define GPIO88_SSP1_SYSCLK    MFP_CFG(GPIO88, AF1)
++#define GPIO83_SSP1_SCLK      MFP_CFG(GPIO83, AF1)
++#define GPIO84_SSP1_SFRM      MFP_CFG(GPIO84, AF1)
++#define GPIO85_SSP1_RXD               MFP_CFG(GPIO85, AF6)
++#define GPIO85_SSP1_TXD               MFP_CFG(GPIO85, AF1)
++#define GPIO86_SSP1_RXD               MFP_CFG(GPIO86, AF1)
++#define GPIO86_SSP1_TXD               MFP_CFG(GPIO86, AF6)
++
++/* SSP2 */
++#define GPIO39_SSP2_EXTCLK    MFP_CFG(GPIO39, AF2)
++#define GPIO40_SSP2_SYSCLK    MFP_CFG(GPIO40, AF2)
++#define GPIO12_SSP2_SCLK      MFP_CFG(GPIO12, AF2)
++#define GPIO35_SSP2_SCLK      MFP_CFG(GPIO35, AF2)
++#define GPIO36_SSP2_SFRM      MFP_CFG(GPIO36, AF2)
++#define GPIO37_SSP2_RXD               MFP_CFG(GPIO37, AF5)
++#define GPIO37_SSP2_TXD               MFP_CFG(GPIO37, AF2)
++#define GPIO38_SSP2_RXD               MFP_CFG(GPIO38, AF2)
++#define GPIO38_SSP2_TXD               MFP_CFG(GPIO38, AF5)
++
++#define GPIO69_SSP3_SCLK      MFP_CFG(GPIO69, AF2, DS08X, FLOAT)
++#define GPIO70_SSP3_FRM               MFP_CFG(GPIO70, AF2, DS08X, DRIVE_LOW)
++#define GPIO89_SSP3_SCLK      MFP_CFG(GPIO89, AF1, DS08X, FLOAT)
++#define GPIO90_SSP3_FRM               MFP_CFG(GPIO90, AF1, DS08X, DRIVE_LOW)
++#define GPIO71_SSP3_RXD               MFP_CFG_X(GPIO71, AF5, DS08X, FLOAT)
++#define GPIO71_SSP3_TXD               MFP_CFG_X(GPIO71, AF2, DS08X, DRIVE_LOW)
++#define GPIO72_SSP3_RXD               MFP_CFG_X(GPIO72, AF2, DS08X, FLOAT)
++#define GPIO72_SSP3_TXD               MFP_CFG_X(GPIO72, AF5, DS08X, DRIVE_LOW)
++#define GPIO91_SSP3_RXD               MFP_CFG_X(GPIO91, AF5, DS08X, FLOAT)
++#define GPIO91_SSP3_TXD               MFP_CFG_X(GPIO91, AF1, DS08X, DRIVE_LOW)
++#define GPIO92_SSP3_RXD               MFP_CFG_X(GPIO92, AF1, DS08X, FLOAT)
++#define GPIO92_SSP3_TXD               MFP_CFG_X(GPIO92, AF5, DS08X, DRIVE_LOW)
++
++#define GPIO93_SSP4_SCLK      MFP_CFG_LPM(GPIO93, AF1, PULL_HIGH)
++#define GPIO94_SSP4_FRM               MFP_CFG_LPM(GPIO94, AF1, PULL_HIGH)
++#define GPIO94_SSP4_RXD               MFP_CFG_LPM(GPIO94, AF5, PULL_HIGH)
++#define GPIO95_SSP4_RXD               MFP_CFG_LPM(GPIO95, AF5, PULL_HIGH)
++#define GPIO95_SSP4_TXD               MFP_CFG_LPM(GPIO95, AF1, PULL_HIGH)
++#define GPIO96_SSP4_RXD               MFP_CFG_LPM(GPIO96, AF1, PULL_HIGH)
++#define GPIO96_SSP4_TXD               MFP_CFG_LPM(GPIO96, AF5, PULL_HIGH)
++
++/* UART1 */
++#define GPIO41_UART1_RXD      MFP_CFG_LPM(GPIO41, AF2, FLOAT)
++#define GPIO41_UART1_TXD      MFP_CFG_LPM(GPIO41, AF4, FLOAT)
++#define GPIO42_UART1_RXD      MFP_CFG_LPM(GPIO42, AF4, FLOAT)
++#define GPIO42_UART1_TXD      MFP_CFG_LPM(GPIO42, AF2, FLOAT)
++#define GPIO97_UART1_RXD      MFP_CFG_LPM(GPIO97, AF1, FLOAT)
++#define GPIO97_UART1_TXD      MFP_CFG_LPM(GPIO97, AF6, FLOAT)
++#define GPIO98_UART1_RXD      MFP_CFG_LPM(GPIO98, AF6, FLOAT)
++#define GPIO98_UART1_TXD      MFP_CFG_LPM(GPIO98, AF1, FLOAT)
++#define GPIO43_UART1_CTS      MFP_CFG_LPM(GPIO43, AF2, FLOAT)
++#define GPIO43_UART1_RTS      MFP_CFG_LPM(GPIO43, AF4, FLOAT)
++#define GPIO48_UART1_CTS      MFP_CFG_LPM(GPIO48, AF4, FLOAT)
++#define GPIO48_UART1_RTS      MFP_CFG_LPM(GPIO48, AF2, FLOAT)
++#define GPIO99_UART1_CTS      MFP_CFG_LPM(GPIO99, AF1, FLOAT)
++#define GPIO99_UART1_RTS      MFP_CFG_LPM(GPIO99, AF6, FLOAT)
++#define GPIO104_UART1_CTS     MFP_CFG_LPM(GPIO104, AF6, FLOAT)
++#define GPIO104_UART1_RTS     MFP_CFG_LPM(GPIO104, AF1, FLOAT)
++#define GPIO45_UART1_DTR      MFP_CFG_LPM(GPIO45, AF4, FLOAT)
++#define GPIO45_UART1_DSR      MFP_CFG_LPM(GPIO45, AF2, FLOAT)
++#define GPIO47_UART1_DTR      MFP_CFG_LPM(GPIO47, AF2, FLOAT)
++#define GPIO47_UART1_DSR      MFP_CFG_LPM(GPIO47, AF4, FLOAT)
++#define GPIO101_UART1_DTR     MFP_CFG_LPM(GPIO101, AF6, FLOAT)
++#define GPIO101_UART1_DSR     MFP_CFG_LPM(GPIO101, AF1, FLOAT)
++#define GPIO103_UART1_DTR     MFP_CFG_LPM(GPIO103, AF1, FLOAT)
++#define GPIO103_UART1_DSR     MFP_CFG_LPM(GPIO103, AF6, FLOAT)
++#define GPIO44_UART1_DCD      MFP_CFG_LPM(GPIO44, AF2, FLOAT)
++#define GPIO100_UART1_DCD     MFP_CFG_LPM(GPIO100, AF1, FLOAT)
++#define GPIO46_UART1_RI               MFP_CFG_LPM(GPIO46, AF2, FLOAT)
++#define GPIO102_UART1_RI      MFP_CFG_LPM(GPIO102, AF1, FLOAT)
++
++/* UART2 */
++#define GPIO109_UART2_CTS     MFP_CFG_LPM(GPIO109, AF3, FLOAT)
++#define GPIO109_UART2_RTS     MFP_CFG_LPM(GPIO109, AF1, FLOAT)
++#define GPIO112_UART2_CTS     MFP_CFG_LPM(GPIO112, AF1, FLOAT)
++#define GPIO112_UART2_RTS     MFP_CFG_LPM(GPIO112, AF3, FLOAT)
++#define GPIO110_UART2_RXD     MFP_CFG_LPM(GPIO110, AF1, FLOAT)
++#define GPIO110_UART2_TXD     MFP_CFG_LPM(GPIO110, AF3, FLOAT)
++#define GPIO111_UART2_RXD     MFP_CFG_LPM(GPIO111, AF3, FLOAT)
++#define GPIO111_UART2_TXD     MFP_CFG_LPM(GPIO111, AF1, FLOAT)
++
++/* UART3 */
++#define GPIO89_UART3_CTS      MFP_CFG_LPM(GPIO89, AF2, FLOAT)
++#define GPIO89_UART3_RTS      MFP_CFG_LPM(GPIO89, AF4, FLOAT)
++#define GPIO90_UART3_CTS      MFP_CFG_LPM(GPIO90, AF4, FLOAT)
++#define GPIO90_UART3_RTS      MFP_CFG_LPM(GPIO90, AF2, FLOAT)
++#define GPIO105_UART3_CTS     MFP_CFG_LPM(GPIO105, AF1, FLOAT)
++#define GPIO105_UART3_RTS     MFP_CFG_LPM(GPIO105, AF3, FLOAT)
++#define GPIO106_UART3_CTS     MFP_CFG_LPM(GPIO106, AF3, FLOAT)
++#define GPIO106_UART3_RTS     MFP_CFG_LPM(GPIO106, AF1, FLOAT)
++#define GPIO30_UART3_RXD      MFP_CFG_LPM(GPIO30, AF2, FLOAT)
++#define GPIO30_UART3_TXD      MFP_CFG_LPM(GPIO30, AF6, FLOAT)
++#define GPIO31_UART3_RXD      MFP_CFG_LPM(GPIO31, AF6, FLOAT)
++#define GPIO31_UART3_TXD      MFP_CFG_LPM(GPIO31, AF2, FLOAT)
++#define GPIO91_UART3_RXD      MFP_CFG_LPM(GPIO91, AF4, FLOAT)
++#define GPIO91_UART3_TXD      MFP_CFG_LPM(GPIO91, AF2, FLOAT)
++#define GPIO92_UART3_RXD      MFP_CFG_LPM(GPIO92, AF2, FLOAT)
++#define GPIO92_UART3_TXD      MFP_CFG_LPM(GPIO92, AF4, FLOAT)
++#define GPIO107_UART3_RXD     MFP_CFG_LPM(GPIO107, AF3, FLOAT)
++#define GPIO107_UART3_TXD     MFP_CFG_LPM(GPIO107, AF1, FLOAT)
++#define GPIO108_UART3_RXD     MFP_CFG_LPM(GPIO108, AF1, FLOAT)
++#define GPIO108_UART3_TXD     MFP_CFG_LPM(GPIO108, AF3, FLOAT)
++
++
++/* USB 2.0 UTMI */
++#define GPIO10_UTM_CLK                MFP_CFG(GPIO10, AF1)
++#define GPIO36_U2D_RXERROR    MFP_CFG(GPIO36, AF3)
++#define GPIO60_U2D_RXERROR    MFP_CFG(GPIO60, AF1)
++#define GPIO87_U2D_RXERROR    MFP_CFG(GPIO87, AF5)
++#define GPIO34_UTM_RXVALID    MFP_CFG(GPIO34, AF3)
++#define GPIO58_UTM_RXVALID    MFP_CFG(GPIO58, AF2)
++#define GPIO85_UTM_RXVALID    MFP_CFG(GPIO85, AF5)
++#define GPIO35_UTM_RXACTIVE   MFP_CFG(GPIO35, AF3)
++#define GPIO59_UTM_RXACTIVE   MFP_CFG(GPIO59, AF1)
++#define GPIO86_UTM_RXACTIVE   MFP_CFG(GPIO86, AF5)
++#define GPIO73_UTM_TXREADY    MFP_CFG(GPIO73, AF1)
++#define GPIO68_UTM_LINESTATE_0        MFP_CFG(GPIO68, AF3)
++#define GPIO90_UTM_LINESTATE_0        MFP_CFG(GPIO90, AF3)
++#define GPIO102_UTM_LINESTATE_0       MFP_CFG(GPIO102, AF3)
++#define GPIO107_UTM_LINESTATE_0       MFP_CFG(GPIO107, AF4)
++#define GPIO69_UTM_LINESTATE_1        MFP_CFG(GPIO69, AF3)
++#define GPIO91_UTM_LINESTATE_1        MFP_CFG(GPIO91, AF3)
++#define GPIO103_UTM_LINESTATE_1       MFP_CFG(GPIO103, AF3)
++
++#define GPIO41_U2D_PHYDATA_0  MFP_CFG(GPIO41, AF3)
++#define GPIO42_U2D_PHYDATA_1  MFP_CFG(GPIO42, AF3)
++#define GPIO43_U2D_PHYDATA_2  MFP_CFG(GPIO43, AF3)
++#define GPIO44_U2D_PHYDATA_3  MFP_CFG(GPIO44, AF3)
++#define GPIO45_U2D_PHYDATA_4  MFP_CFG(GPIO45, AF3)
++#define GPIO46_U2D_PHYDATA_5  MFP_CFG(GPIO46, AF3)
++#define GPIO47_U2D_PHYDATA_6  MFP_CFG(GPIO47, AF3)
++#define GPIO48_U2D_PHYDATA_7  MFP_CFG(GPIO48, AF3)
++
++#define GPIO49_U2D_PHYDATA_0  MFP_CFG(GPIO49, AF3)
++#define GPIO50_U2D_PHYDATA_1  MFP_CFG(GPIO50, AF3)
++#define GPIO51_U2D_PHYDATA_2  MFP_CFG(GPIO51, AF3)
++#define GPIO52_U2D_PHYDATA_3  MFP_CFG(GPIO52, AF3)
++#define GPIO53_U2D_PHYDATA_4  MFP_CFG(GPIO53, AF3)
++#define GPIO54_U2D_PHYDATA_5  MFP_CFG(GPIO54, AF3)
++#define GPIO55_U2D_PHYDATA_6  MFP_CFG(GPIO55, AF3)
++#define GPIO56_U2D_PHYDATA_7  MFP_CFG(GPIO56, AF3)
++
++#define GPIO37_U2D_OPMODE0    MFP_CFG(GPIO37, AF4)
++#define GPIO61_U2D_OPMODE0    MFP_CFG(GPIO61, AF2)
++#define GPIO88_U2D_OPMODE0    MFP_CFG(GPIO88, AF7)
++
++#define GPIO38_U2D_OPMODE1    MFP_CFG(GPIO38, AF4)
++#define GPIO62_U2D_OPMODE1    MFP_CFG(GPIO62, AF2)
++#define GPIO104_U2D_OPMODE1   MFP_CFG(GPIO104, AF4)
++#define GPIO108_U2D_OPMODE1   MFP_CFG(GPIO108, AF5)
++
++#define GPIO74_U2D_RESET      MFP_CFG(GPIO74, AF1)
++#define GPIO93_U2D_RESET      MFP_CFG(GPIO93, AF2)
++#define GPIO98_U2D_RESET      MFP_CFG(GPIO98, AF3)
++
++#define GPIO67_U2D_SUSPEND    MFP_CFG(GPIO67, AF3)
++#define GPIO96_U2D_SUSPEND    MFP_CFG(GPIO96, AF2)
++#define GPIO101_U2D_SUSPEND   MFP_CFG(GPIO101, AF3)
++
++#define GPIO66_U2D_TERM_SEL   MFP_CFG(GPIO66, AF5)
++#define GPIO95_U2D_TERM_SEL   MFP_CFG(GPIO95, AF3)
++#define GPIO97_U2D_TERM_SEL   MFP_CFG(GPIO97, AF7)
++#define GPIO100_U2D_TERM_SEL  MFP_CFG(GPIO100, AF5)
++
++#define GPIO39_U2D_TXVALID    MFP_CFG(GPIO39, AF4)
++#define GPIO70_U2D_TXVALID    MFP_CFG(GPIO70, AF5)
++#define GPIO83_U2D_TXVALID    MFP_CFG(GPIO83, AF7)
++
++#define GPIO65_U2D_XCVR_SEL   MFP_CFG(GPIO65, AF5)
++#define GPIO94_U2D_XCVR_SEL   MFP_CFG(GPIO94, AF3)
++#define GPIO99_U2D_XCVR_SEL   MFP_CFG(GPIO99, AF5)
++
++/* USB Host 1.1 */
++#define GPIO2_2_USBH_PEN      MFP_CFG(GPIO2_2, AF1)
++#define GPIO3_2_USBH_PWR      MFP_CFG(GPIO3_2, AF1)
++
++/* USB P2 */
++#define GPIO97_USB_P2_2               MFP_CFG(GPIO97, AF2)
++#define GPIO97_USB_P2_6               MFP_CFG(GPIO97, AF4)
++#define GPIO98_USB_P2_2               MFP_CFG(GPIO98, AF4)
++#define GPIO98_USB_P2_6               MFP_CFG(GPIO98, AF2)
++#define GPIO99_USB_P2_1               MFP_CFG(GPIO99, AF2)
++#define GPIO100_USB_P2_4      MFP_CFG(GPIO100, AF2)
++#define GPIO101_USB_P2_8      MFP_CFG(GPIO101, AF2)
++#define GPIO102_USB_P2_3      MFP_CFG(GPIO102, AF2)
++#define GPIO103_USB_P2_5      MFP_CFG(GPIO103, AF2)
++#define GPIO104_USB_P2_7      MFP_CFG(GPIO104, AF2)
++
++/* USB P3 */
++#define GPIO75_USB_P3_1               MFP_CFG(GPIO75, AF2)
++#define GPIO76_USB_P3_2               MFP_CFG(GPIO76, AF2)
++#define GPIO77_USB_P3_3               MFP_CFG(GPIO77, AF2)
++#define GPIO78_USB_P3_4               MFP_CFG(GPIO78, AF2)
++#define GPIO79_USB_P3_5               MFP_CFG(GPIO79, AF2)
++#define GPIO80_USB_P3_6               MFP_CFG(GPIO80, AF2)
++
++#define GPIO13_CHOUT0         MFP_CFG(GPIO13, AF6)
++#define GPIO14_CHOUT1         MFP_CFG(GPIO14, AF6)
++
++#define GPIO2_RDY             MFP_CFG(GPIO2, AF1)
++#define GPIO5_NPIOR           MFP_CFG(GPIO5, AF3)
++
++#define GPIO11_PWM0_OUT               MFP_CFG(GPIO11, AF1)
++#define GPIO12_PWM1_OUT               MFP_CFG(GPIO12, AF1)
++#define GPIO13_PWM2_OUT               MFP_CFG(GPIO13, AF1)
++#define GPIO14_PWM3_OUT               MFP_CFG(GPIO14, AF1)
++
++#endif /* __ASM_ARCH_MFP_PXA320_H */
+--- /dev/null
++++ linux-2.6.23/include/asm-arm/arch-pxa/mfp.h
+@@ -0,0 +1,576 @@
++/*
++ * linux/include/asm-arm/arch-pxa/mfp.h
++ *
++ * Multi-Function Pin Definitions
++ *
++ * Copyright (C) 2007 Marvell International Ltd.
++ *
++ * 2007-8-21: eric miao <eric.y.miao@gmail.com>
++ *            initial version
++ *
++ *  This program is free software; you can 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_MFP_H
++#define __ASM_ARCH_MFP_H
++
++#define MFPR_BASE     (0x40e10000)
++#define MFPR_SIZE     (PAGE_SIZE)
++
++#define mfp_to_gpio(m)        ((m) % 128)
++
++/* list of all the configurable MFP pins */
++enum {
++      MFP_PIN_INVALID = -1,
++
++      MFP_PIN_GPIO0 = 0,
++      MFP_PIN_GPIO1,
++      MFP_PIN_GPIO2,
++      MFP_PIN_GPIO3,
++      MFP_PIN_GPIO4,
++      MFP_PIN_GPIO5,
++      MFP_PIN_GPIO6,
++      MFP_PIN_GPIO7,
++      MFP_PIN_GPIO8,
++      MFP_PIN_GPIO9,
++      MFP_PIN_GPIO10,
++      MFP_PIN_GPIO11,
++      MFP_PIN_GPIO12,
++      MFP_PIN_GPIO13,
++      MFP_PIN_GPIO14,
++      MFP_PIN_GPIO15,
++      MFP_PIN_GPIO16,
++      MFP_PIN_GPIO17,
++      MFP_PIN_GPIO18,
++      MFP_PIN_GPIO19,
++      MFP_PIN_GPIO20,
++      MFP_PIN_GPIO21,
++      MFP_PIN_GPIO22,
++      MFP_PIN_GPIO23,
++      MFP_PIN_GPIO24,
++      MFP_PIN_GPIO25,
++      MFP_PIN_GPIO26,
++      MFP_PIN_GPIO27,
++      MFP_PIN_GPIO28,
++      MFP_PIN_GPIO29,
++      MFP_PIN_GPIO30,
++      MFP_PIN_GPIO31,
++      MFP_PIN_GPIO32,
++      MFP_PIN_GPIO33,
++      MFP_PIN_GPIO34,
++      MFP_PIN_GPIO35,
++      MFP_PIN_GPIO36,
++      MFP_PIN_GPIO37,
++      MFP_PIN_GPIO38,
++      MFP_PIN_GPIO39,
++      MFP_PIN_GPIO40,
++      MFP_PIN_GPIO41,
++      MFP_PIN_GPIO42,
++      MFP_PIN_GPIO43,
++      MFP_PIN_GPIO44,
++      MFP_PIN_GPIO45,
++      MFP_PIN_GPIO46,
++      MFP_PIN_GPIO47,
++      MFP_PIN_GPIO48,
++      MFP_PIN_GPIO49,
++      MFP_PIN_GPIO50,
++      MFP_PIN_GPIO51,
++      MFP_PIN_GPIO52,
++      MFP_PIN_GPIO53,
++      MFP_PIN_GPIO54,
++      MFP_PIN_GPIO55,
++      MFP_PIN_GPIO56,
++      MFP_PIN_GPIO57,
++      MFP_PIN_GPIO58,
++      MFP_PIN_GPIO59,
++      MFP_PIN_GPIO60,
++      MFP_PIN_GPIO61,
++      MFP_PIN_GPIO62,
++      MFP_PIN_GPIO63,
++      MFP_PIN_GPIO64,
++      MFP_PIN_GPIO65,
++      MFP_PIN_GPIO66,
++      MFP_PIN_GPIO67,
++      MFP_PIN_GPIO68,
++      MFP_PIN_GPIO69,
++      MFP_PIN_GPIO70,
++      MFP_PIN_GPIO71,
++      MFP_PIN_GPIO72,
++      MFP_PIN_GPIO73,
++      MFP_PIN_GPIO74,
++      MFP_PIN_GPIO75,
++      MFP_PIN_GPIO76,
++      MFP_PIN_GPIO77,
++      MFP_PIN_GPIO78,
++      MFP_PIN_GPIO79,
++      MFP_PIN_GPIO80,
++      MFP_PIN_GPIO81,
++      MFP_PIN_GPIO82,
++      MFP_PIN_GPIO83,
++      MFP_PIN_GPIO84,
++      MFP_PIN_GPIO85,
++      MFP_PIN_GPIO86,
++      MFP_PIN_GPIO87,
++      MFP_PIN_GPIO88,
++      MFP_PIN_GPIO89,
++      MFP_PIN_GPIO90,
++      MFP_PIN_GPIO91,
++      MFP_PIN_GPIO92,
++      MFP_PIN_GPIO93,
++      MFP_PIN_GPIO94,
++      MFP_PIN_GPIO95,
++      MFP_PIN_GPIO96,
++      MFP_PIN_GPIO97,
++      MFP_PIN_GPIO98,
++      MFP_PIN_GPIO99,
++      MFP_PIN_GPIO100,
++      MFP_PIN_GPIO101,
++      MFP_PIN_GPIO102,
++      MFP_PIN_GPIO103,
++      MFP_PIN_GPIO104,
++      MFP_PIN_GPIO105,
++      MFP_PIN_GPIO106,
++      MFP_PIN_GPIO107,
++      MFP_PIN_GPIO108,
++      MFP_PIN_GPIO109,
++      MFP_PIN_GPIO110,
++      MFP_PIN_GPIO111,
++      MFP_PIN_GPIO112,
++      MFP_PIN_GPIO113,
++      MFP_PIN_GPIO114,
++      MFP_PIN_GPIO115,
++      MFP_PIN_GPIO116,
++      MFP_PIN_GPIO117,
++      MFP_PIN_GPIO118,
++      MFP_PIN_GPIO119,
++      MFP_PIN_GPIO120,
++      MFP_PIN_GPIO121,
++      MFP_PIN_GPIO122,
++      MFP_PIN_GPIO123,
++      MFP_PIN_GPIO124,
++      MFP_PIN_GPIO125,
++      MFP_PIN_GPIO126,
++      MFP_PIN_GPIO127,
++      MFP_PIN_GPIO0_2,
++      MFP_PIN_GPIO1_2,
++      MFP_PIN_GPIO2_2,
++      MFP_PIN_GPIO3_2,
++      MFP_PIN_GPIO4_2,
++      MFP_PIN_GPIO5_2,
++      MFP_PIN_GPIO6_2,
++      MFP_PIN_GPIO7_2,
++      MFP_PIN_GPIO8_2,
++      MFP_PIN_GPIO9_2,
++      MFP_PIN_GPIO10_2,
++      MFP_PIN_GPIO11_2,
++      MFP_PIN_GPIO12_2,
++      MFP_PIN_GPIO13_2,
++      MFP_PIN_GPIO14_2,
++      MFP_PIN_GPIO15_2,
++      MFP_PIN_GPIO16_2,
++      MFP_PIN_GPIO17_2,
++
++      MFP_PIN_ULPI_STP,
++      MFP_PIN_ULPI_NXT,
++      MFP_PIN_ULPI_DIR,
++
++      MFP_PIN_nXCVREN,
++      MFP_PIN_DF_CLE_nOE,
++      MFP_PIN_DF_nADV1_ALE,
++      MFP_PIN_DF_SCLK_E,
++      MFP_PIN_DF_SCLK_S,
++      MFP_PIN_nBE0,
++      MFP_PIN_nBE1,
++      MFP_PIN_DF_nADV2_ALE,
++      MFP_PIN_DF_INT_RnB,
++      MFP_PIN_DF_nCS0,
++      MFP_PIN_DF_nCS1,
++      MFP_PIN_nLUA,
++      MFP_PIN_nLLA,
++      MFP_PIN_DF_nWE,
++      MFP_PIN_DF_ALE_nWE,
++      MFP_PIN_DF_nRE_nOE,
++      MFP_PIN_DF_ADDR0,
++      MFP_PIN_DF_ADDR1,
++      MFP_PIN_DF_ADDR2,
++      MFP_PIN_DF_ADDR3,
++      MFP_PIN_DF_IO0,
++      MFP_PIN_DF_IO1,
++      MFP_PIN_DF_IO2,
++      MFP_PIN_DF_IO3,
++      MFP_PIN_DF_IO4,
++      MFP_PIN_DF_IO5,
++      MFP_PIN_DF_IO6,
++      MFP_PIN_DF_IO7,
++      MFP_PIN_DF_IO8,
++      MFP_PIN_DF_IO9,
++      MFP_PIN_DF_IO10,
++      MFP_PIN_DF_IO11,
++      MFP_PIN_DF_IO12,
++      MFP_PIN_DF_IO13,
++      MFP_PIN_DF_IO14,
++      MFP_PIN_DF_IO15,
++
++      MFP_PIN_MAX,
++};
++
++/*
++ * Table that determines the low power modes outputs, with actual settings
++ * used in parentheses for don't-care values. Except for the float output,
++ * the configured driven and pulled levels match, so if there is a need for
++ * non-LPM pulled output, the same configuration could probably be used.
++ *
++ * Output value  sleep_oe_n  sleep_data  pullup_en  pulldown_en  pull_sel
++ *                 (bit 7)    (bit 8)    (bit 14d)   (bit 13d)
++ *
++ * Drive 0          0          0           0           X (1)      0
++ * Drive 1          0          1           X (1)       0        0
++ * Pull hi (1)      1          X(1)        1           0        0
++ * Pull lo (0)      1          X(0)        0           1        0
++ * Z (float)        1          X(0)        0           0        0
++ */
++#define MFP_LPM_DRIVE_LOW     0x8
++#define MFP_LPM_DRIVE_HIGH            0x6
++#define MFP_LPM_PULL_HIGH             0x7
++#define MFP_LPM_PULL_LOW              0x9
++#define MFP_LPM_FLOAT                 0x1
++#define MFP_LPM_PULL_NEITHER  0x0
++
++/*
++ * The pullup and pulldown state of the MFP pin is by default determined by
++ * selected alternate function. In case some buggy devices need to override
++ * this default behavior,  pxa3xx_mfp_set_pull() can be invoked with one of
++ * the following definition as the parameter.
++ *
++ * Definition       pull_sel  pullup_en  pulldown_en
++ * MFP_PULL_HIGH        1         1        0
++ * MFP_PULL_LOW         1         0        1
++ * MFP_PULL_BOTH        1         1        1
++ * MFP_PULL_NONE        1         0        0
++ * MFP_PULL_DEFAULT     0         X        X
++ *
++ * NOTE: pxa3xx_mfp_set_pull() will modify the PULLUP_EN and PULLDOWN_EN
++ * bits,  which will cause potential conflicts with the low power mode
++ * setting, device drivers should take care of this
++ */
++#define MFP_PULL_BOTH         (0x7u)
++#define MFP_PULL_HIGH         (0x6u)
++#define MFP_PULL_LOW          (0x5u)
++#define MFP_PULL_NONE         (0x4u)
++#define MFP_PULL_DEFAULT      (0x0u)
++
++#define MFP_AF0                       (0)
++#define MFP_AF1                       (1)
++#define MFP_AF2                       (2)
++#define MFP_AF3                       (3)
++#define MFP_AF4                       (4)
++#define MFP_AF5                       (5)
++#define MFP_AF6                       (6)
++#define MFP_AF7                       (7)
++
++#define MFP_DS01X             (0)
++#define MFP_DS02X             (1)
++#define MFP_DS03X             (2)
++#define MFP_DS04X             (3)
++#define MFP_DS06X             (4)
++#define MFP_DS08X             (5)
++#define MFP_DS10X             (6)
++#define MFP_DS12X             (7)
++
++#define MFP_EDGE_BOTH         0x3
++#define MFP_EDGE_RISE         0x2
++#define MFP_EDGE_FALL         0x1
++#define MFP_EDGE_NONE         0x0
++
++#define MFPR_AF_MASK          0x0007
++#define MFPR_DRV_MASK         0x1c00
++#define MFPR_RDH_MASK         0x0200
++#define MFPR_LPM_MASK         0xe180
++#define MFPR_PULL_MASK                0xe000
++#define MFPR_EDGE_MASK                0x0070
++
++#define MFPR_ALT_OFFSET               0
++#define MFPR_ERE_OFFSET               4
++#define MFPR_EFE_OFFSET               5
++#define MFPR_EC_OFFSET                6
++#define MFPR_SON_OFFSET               7
++#define MFPR_SD_OFFSET                8
++#define MFPR_SS_OFFSET                9
++#define MFPR_DRV_OFFSET               10
++#define MFPR_PD_OFFSET                13
++#define MFPR_PU_OFFSET                14
++#define MFPR_PS_OFFSET                15
++
++#define MFPR(af, drv, rdh, lpm, edge) \
++      (((af) & 0x7) | (((drv) & 0x7) << 10) |\
++       (((rdh) & 0x1) << 9) |\
++       (((lpm) & 0x3) << 7) |\
++       (((lpm) & 0x4) << 12)|\
++       (((lpm) & 0x8) << 10)|\
++       ((!(edge)) << 6) |\
++       (((edge) & 0x1) << 5) |\
++       (((edge) & 0x2) << 3))
++
++/*
++ * a possible MFP configuration is represented by a 32-bit integer
++ * bit  0..15 - MFPR value (16-bit)
++ * bit 16..31 - mfp pin index (used to obtain the MFPR offset)
++ *
++ * to facilitate the definition, the following macros are provided
++ *
++ * MFPR_DEFAULT - default MFPR value, with
++ *              alternate function = 0,
++ *              drive strength = fast 1mA (MFP_DS01X)
++ *              low power mode = default
++ *              release dalay hold = false (RDH bit)
++ *              edge detection = none
++ *
++ * MFP_CFG    - default MFPR value with alternate function
++ * MFP_CFG_DRV        - default MFPR value with alternate function and
++ *              pin drive strength
++ * MFP_CFG_LPM        - default MFPR value with alternate function and
++ *              low power mode
++ * MFP_CFG_X  - default MFPR value with alternate function,
++ *              pin drive strength and low power mode
++ *
++ * use
++ *
++ * MFP_CFG_PIN        - to get the MFP pin index
++ * MFP_CFG_VAL        - to get the corresponding MFPR value
++ */
++
++typedef uint32_t mfp_cfg_t;
++
++#define MFP_CFG_PIN(mfp_cfg)  (((mfp_cfg) >> 16) & 0xffff)
++#define MFP_CFG_VAL(mfp_cfg)  ((mfp_cfg) & 0xffff)
++
++#define MFPR_DEFAULT  (0x0000)
++
++#define MFP_CFG(pin, af)              \
++      ((MFP_PIN_##pin << 16) | MFPR_DEFAULT | (MFP_##af))
++
++#define MFP_CFG_DRV(pin, af, drv)     \
++      ((MFP_PIN_##pin << 16) | MFPR_DEFAULT |\
++       ((MFP_##drv) << 10) | (MFP_##af))
++
++#define MFP_CFG_LPM(pin, af, lpm)     \
++      ((MFP_PIN_##pin << 16) | MFPR_DEFAULT | (MFP_##af) |\
++       (((MFP_LPM_##lpm) & 0x3) << 7)  |\
++       (((MFP_LPM_##lpm) & 0x4) << 12) |\
++       (((MFP_LPM_##lpm) & 0x8) << 10))
++
++#define MFP_CFG_X(pin, af, drv, lpm)  \
++      ((MFP_PIN_##pin << 16) | MFPR_DEFAULT |\
++       ((MFP_##drv) << 10) | (MFP_##af) |\
++       (((MFP_LPM_##lpm) & 0x3) << 7)  |\
++       (((MFP_LPM_##lpm) & 0x4) << 12) |\
++       (((MFP_LPM_##lpm) & 0x8) << 10))
++
++/* common MFP configurations - processor specific ones defined
++ * in mfp-pxa3xx.h
++ */
++#define GPIO0_GPIO            MFP_CFG(GPIO0, AF0)
++#define GPIO1_GPIO            MFP_CFG(GPIO1, AF0)
++#define GPIO2_GPIO            MFP_CFG(GPIO2, AF0)
++#define GPIO3_GPIO            MFP_CFG(GPIO3, AF0)
++#define GPIO4_GPIO            MFP_CFG(GPIO4, AF0)
++#define GPIO5_GPIO            MFP_CFG(GPIO5, AF0)
++#define GPIO6_GPIO            MFP_CFG(GPIO6, AF0)
++#define GPIO7_GPIO            MFP_CFG(GPIO7, AF0)
++#define GPIO8_GPIO            MFP_CFG(GPIO8, AF0)
++#define GPIO9_GPIO            MFP_CFG(GPIO9, AF0)
++#define GPIO10_GPIO           MFP_CFG(GPIO10, AF0)
++#define GPIO11_GPIO           MFP_CFG(GPIO11, AF0)
++#define GPIO12_GPIO           MFP_CFG(GPIO12, AF0)
++#define GPIO13_GPIO           MFP_CFG(GPIO13, AF0)
++#define GPIO14_GPIO           MFP_CFG(GPIO14, AF0)
++#define GPIO15_GPIO           MFP_CFG(GPIO15, AF0)
++#define GPIO16_GPIO           MFP_CFG(GPIO16, AF0)
++#define GPIO17_GPIO           MFP_CFG(GPIO17, AF0)
++#define GPIO18_GPIO           MFP_CFG(GPIO18, AF0)
++#define GPIO19_GPIO           MFP_CFG(GPIO19, AF0)
++#define GPIO20_GPIO           MFP_CFG(GPIO20, AF0)
++#define GPIO21_GPIO           MFP_CFG(GPIO21, AF0)
++#define GPIO22_GPIO           MFP_CFG(GPIO22, AF0)
++#define GPIO23_GPIO           MFP_CFG(GPIO23, AF0)
++#define GPIO24_GPIO           MFP_CFG(GPIO24, AF0)
++#define GPIO25_GPIO           MFP_CFG(GPIO25, AF0)
++#define GPIO26_GPIO           MFP_CFG(GPIO26, AF0)
++#define GPIO27_GPIO           MFP_CFG(GPIO27, AF0)
++#define GPIO28_GPIO           MFP_CFG(GPIO28, AF0)
++#define GPIO29_GPIO           MFP_CFG(GPIO29, AF0)
++#define GPIO30_GPIO           MFP_CFG(GPIO30, AF0)
++#define GPIO31_GPIO           MFP_CFG(GPIO31, AF0)
++#define GPIO32_GPIO           MFP_CFG(GPIO32, AF0)
++#define GPIO33_GPIO           MFP_CFG(GPIO33, AF0)
++#define GPIO34_GPIO           MFP_CFG(GPIO34, AF0)
++#define GPIO35_GPIO           MFP_CFG(GPIO35, AF0)
++#define GPIO36_GPIO           MFP_CFG(GPIO36, AF0)
++#define GPIO37_GPIO           MFP_CFG(GPIO37, AF0)
++#define GPIO38_GPIO           MFP_CFG(GPIO38, AF0)
++#define GPIO39_GPIO           MFP_CFG(GPIO39, AF0)
++#define GPIO40_GPIO           MFP_CFG(GPIO40, AF0)
++#define GPIO41_GPIO           MFP_CFG(GPIO41, AF0)
++#define GPIO42_GPIO           MFP_CFG(GPIO42, AF0)
++#define GPIO43_GPIO           MFP_CFG(GPIO43, AF0)
++#define GPIO44_GPIO           MFP_CFG(GPIO44, AF0)
++#define GPIO45_GPIO           MFP_CFG(GPIO45, AF0)
++
++#define GPIO47_GPIO           MFP_CFG(GPIO47, AF0)
++#define GPIO48_GPIO           MFP_CFG(GPIO48, AF0)
++
++#define GPIO53_GPIO           MFP_CFG(GPIO53, AF0)
++#define GPIO54_GPIO           MFP_CFG(GPIO54, AF0)
++#define GPIO55_GPIO           MFP_CFG(GPIO55, AF0)
++
++#define GPIO57_GPIO           MFP_CFG(GPIO57, AF0)
++
++#define GPIO63_GPIO           MFP_CFG(GPIO63, AF0)
++#define GPIO64_GPIO           MFP_CFG(GPIO64, AF0)
++#define GPIO65_GPIO           MFP_CFG(GPIO65, AF0)
++#define GPIO66_GPIO           MFP_CFG(GPIO66, AF0)
++#define GPIO67_GPIO           MFP_CFG(GPIO67, AF0)
++#define GPIO68_GPIO           MFP_CFG(GPIO68, AF0)
++#define GPIO69_GPIO           MFP_CFG(GPIO69, AF0)
++#define GPIO70_GPIO           MFP_CFG(GPIO70, AF0)
++#define GPIO71_GPIO           MFP_CFG(GPIO71, AF0)
++#define GPIO72_GPIO           MFP_CFG(GPIO72, AF0)
++#define GPIO73_GPIO           MFP_CFG(GPIO73, AF0)
++#define GPIO74_GPIO           MFP_CFG(GPIO74, AF0)
++#define GPIO75_GPIO           MFP_CFG(GPIO75, AF0)
++#define GPIO76_GPIO           MFP_CFG(GPIO76, AF0)
++#define GPIO77_GPIO           MFP_CFG(GPIO77, AF0)
++#define GPIO78_GPIO           MFP_CFG(GPIO78, AF0)
++#define GPIO79_GPIO           MFP_CFG(GPIO79, AF0)
++#define GPIO80_GPIO           MFP_CFG(GPIO80, AF0)
++#define GPIO81_GPIO           MFP_CFG(GPIO81, AF0)
++#define GPIO82_GPIO           MFP_CFG(GPIO82, AF0)
++#define GPIO83_GPIO           MFP_CFG(GPIO83, AF0)
++#define GPIO84_GPIO           MFP_CFG(GPIO84, AF0)
++#define GPIO85_GPIO           MFP_CFG(GPIO85, AF0)
++#define GPIO86_GPIO           MFP_CFG(GPIO86, AF0)
++#define GPIO87_GPIO           MFP_CFG(GPIO87, AF0)
++#define GPIO88_GPIO           MFP_CFG(GPIO88, AF0)
++#define GPIO89_GPIO           MFP_CFG(GPIO89, AF0)
++#define GPIO90_GPIO           MFP_CFG(GPIO90, AF0)
++#define GPIO91_GPIO           MFP_CFG(GPIO91, AF0)
++#define GPIO92_GPIO           MFP_CFG(GPIO92, AF0)
++#define GPIO93_GPIO           MFP_CFG(GPIO93, AF0)
++#define GPIO94_GPIO           MFP_CFG(GPIO94, AF0)
++#define GPIO95_GPIO           MFP_CFG(GPIO95, AF0)
++#define GPIO96_GPIO           MFP_CFG(GPIO96, AF0)
++#define GPIO97_GPIO           MFP_CFG(GPIO97, AF0)
++#define GPIO98_GPIO           MFP_CFG(GPIO98, AF0)
++#define GPIO99_GPIO           MFP_CFG(GPIO99, AF0)
++#define GPIO100_GPIO          MFP_CFG(GPIO100, AF0)
++#define GPIO101_GPIO          MFP_CFG(GPIO101, AF0)
++#define GPIO102_GPIO          MFP_CFG(GPIO102, AF0)
++#define GPIO103_GPIO          MFP_CFG(GPIO103, AF0)
++#define GPIO104_GPIO          MFP_CFG(GPIO104, AF0)
++#define GPIO105_GPIO          MFP_CFG(GPIO105, AF0)
++#define GPIO106_GPIO          MFP_CFG(GPIO106, AF0)
++#define GPIO107_GPIO          MFP_CFG(GPIO107, AF0)
++#define GPIO108_GPIO          MFP_CFG(GPIO108, AF0)
++#define GPIO109_GPIO          MFP_CFG(GPIO109, AF0)
++#define GPIO110_GPIO          MFP_CFG(GPIO110, AF0)
++#define GPIO111_GPIO          MFP_CFG(GPIO111, AF0)
++#define GPIO112_GPIO          MFP_CFG(GPIO112, AF0)
++#define GPIO113_GPIO          MFP_CFG(GPIO113, AF0)
++#define GPIO114_GPIO          MFP_CFG(GPIO114, AF0)
++#define GPIO115_GPIO          MFP_CFG(GPIO115, AF0)
++#define GPIO116_GPIO          MFP_CFG(GPIO116, AF0)
++#define GPIO117_GPIO          MFP_CFG(GPIO117, AF0)
++#define GPIO118_GPIO          MFP_CFG(GPIO118, AF0)
++#define GPIO119_GPIO          MFP_CFG(GPIO119, AF0)
++#define GPIO120_GPIO          MFP_CFG(GPIO120, AF0)
++#define GPIO121_GPIO          MFP_CFG(GPIO121, AF0)
++#define GPIO122_GPIO          MFP_CFG(GPIO122, AF0)
++#define GPIO123_GPIO          MFP_CFG(GPIO123, AF0)
++#define GPIO124_GPIO          MFP_CFG(GPIO124, AF0)
++#define GPIO125_GPIO          MFP_CFG(GPIO125, AF0)
++#define GPIO126_GPIO          MFP_CFG(GPIO126, AF0)
++#define GPIO127_GPIO          MFP_CFG(GPIO127, AF0)
++
++#define GPIO0_2_GPIO          MFP_CFG(GPIO0_2, AF0)
++#define GPIO1_2_GPIO          MFP_CFG(GPIO1_2, AF0)
++#define GPIO2_2_GPIO          MFP_CFG(GPIO2_2, AF0)
++#define GPIO3_2_GPIO          MFP_CFG(GPIO3_2, AF0)
++#define GPIO4_2_GPIO          MFP_CFG(GPIO4_2, AF0)
++#define GPIO5_2_GPIO          MFP_CFG(GPIO5_2, AF0)
++#define GPIO6_2_GPIO          MFP_CFG(GPIO6_2, AF0)
++
++/*
++ * each MFP pin will have a MFPR register, since the offset of the
++ * register varies between processors, the processor specific code
++ * should initialize the pin offsets by pxa3xx_mfp_init_addr()
++ *
++ * pxa3xx_mfp_init_addr - accepts a table of "pxa3xx_mfp_addr_map"
++ * structure, which represents a range of MFP pins from "start" to
++ * "end", with the offset begining at "offset", to define a single
++ * pin, let "end" = -1
++ *
++ * use
++ *
++ * MFP_ADDR_X() to define a range of pins
++ * MFP_ADDR()   to define a single pin
++ * MFP_ADDR_END to signal the end of pin offset definitions
++ */
++struct pxa3xx_mfp_addr_map {
++      unsigned int    start;
++      unsigned int    end;
++      unsigned long   offset;
++};
++
++#define MFP_ADDR_X(start, end, offset) \
++      { MFP_PIN_##start, MFP_PIN_##end, offset }
++
++#define MFP_ADDR(pin, offset) \
++      { MFP_PIN_##pin, -1, offset }
++
++#define MFP_ADDR_END  { MFP_PIN_INVALID, 0 }
++
++struct pxa3xx_mfp_pin {
++      unsigned long   mfpr_off;       /* MFPRxx register offset */
++      unsigned long   mfpr_val;       /* MFPRxx register value */
++};
++
++/*
++ * pxa3xx_mfp_read()/pxa3xx_mfp_write() - for direct read/write access
++ * to the MFPR register
++ */
++unsigned long pxa3xx_mfp_read(int mfp);
++void pxa3xx_mfp_write(int mfp, unsigned long mfpr_val);
++
++/*
++ * pxa3xx_mfp_set_afds - set MFP alternate function and drive strength
++ * pxa3xx_mfp_set_rdh  - set MFP release delay hold on/off
++ * pxa3xx_mfp_set_lpm  - set MFP low power mode state
++ * pxa3xx_mfp_set_edge - set MFP edge detection in low power mode
++ *
++ * use these functions to override/change the default configuration
++ * done by pxa3xx_mfp_set_config(s)
++ */
++void pxa3xx_mfp_set_afds(int mfp, int af, int ds);
++void pxa3xx_mfp_set_rdh(int mfp, int rdh);
++void pxa3xx_mfp_set_lpm(int mfp, int lpm);
++void pxa3xx_mfp_set_edge(int mfp, int edge);
++
++/*
++ * pxa3xx_mfp_config - configure the MFPR registers
++ *
++ * used by board specific initialization code
++ */
++void pxa3xx_mfp_config(mfp_cfg_t *mfp_cfgs, int num);
++
++/*
++ * pxa3xx_mfp_init_addr() - initialize the mapping between mfp pin
++ * index and MFPR register offset
++ *
++ * used by processor specific code
++ */
++void __init pxa3xx_mfp_init_addr(struct pxa3xx_mfp_addr_map *);
++void __init pxa3xx_init_mfp(void);
++
++#endif /* __ASM_ARCH_MFP_H */
+--- linux-2.6.23.orig/include/asm-arm/arch-pxa/pxa-regs.h
++++ linux-2.6.23/include/asm-arm/arch-pxa/pxa-regs.h
+@@ -1184,7 +1184,7 @@
+ #define GPIO_bit(x)   (1 << ((x) & 0x1f))
+-#ifdef CONFIG_PXA27x
++#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
+ /* Interrupt Controller */
+--- /dev/null
++++ linux-2.6.23/include/asm-arm/arch-pxa/pxa3xx-regs.h
+@@ -0,0 +1,75 @@
++/*
++ * linux/include/asm-arm/arch-pxa/pxa3xx-regs.h
++ *
++ * PXA3xx specific register definitions
++ *
++ * Copyright (C) 2007 Marvell International Ltd.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#ifndef __ASM_ARCH_PXA3XX_REGS_H
++#define __ASM_ARCH_PXA3XX_REGS_H
++
++/*
++ * Application Subsystem Clock
++ */
++#define ACCR          __REG(0x41340000)       /* Application Subsystem Clock Configuration Register */
++#define ACSR          __REG(0x41340004)       /* Application Subsystem Clock Status Register */
++#define AICSR         __REG(0x41340008)       /* Application Subsystem Interrupt Control/Status Register */
++#define CKENA         __REG(0x4134000C)       /* A Clock Enable Register */
++#define CKENB         __REG(0x41340010)       /* B Clock Enable Register */
++#define AC97_DIV      __REG(0x41340014)       /* AC97 clock divisor value register */
++
++/*
++ * Clock Enable Bit
++ */
++#define CKEN_LCD      1       /* < LCD Clock Enable */
++#define CKEN_USBH     2       /* < USB host clock enable */
++#define CKEN_CAMERA   3       /* < Camera interface clock enable */
++#define CKEN_NAND     4       /* < NAND Flash Controller Clock Enable */
++#define CKEN_USB2     6       /* < USB 2.0 client clock enable. */
++#define CKEN_DMC      8       /* < Dynamic Memory Controller clock enable */
++#define CKEN_SMC      9       /* < Static Memory Controller clock enable */
++#define CKEN_ISC      10      /* < Internal SRAM Controller clock enable */
++#define CKEN_BOOT     11      /* < Boot rom clock enable */
++#define CKEN_MMC1     12      /* < MMC1 Clock enable */
++#define CKEN_MMC2     13      /* < MMC2 clock enable */
++#define CKEN_KEYPAD   14      /* < Keypand Controller Clock Enable */
++#define CKEN_CIR      15      /* < Consumer IR Clock Enable */
++#define CKEN_USIM0    17      /* < USIM[0] Clock Enable */
++#define CKEN_USIM1    18      /* < USIM[1] Clock Enable */
++#define CKEN_TPM      19      /* < TPM clock enable */
++#define CKEN_UDC      20      /* < UDC clock enable */
++#define CKEN_BTUART   21      /* < BTUART clock enable */
++#define CKEN_FFUART   22      /* < FFUART clock enable */
++#define CKEN_STUART   23      /* < STUART clock enable */
++#define CKEN_AC97     24      /* < AC97 clock enable */
++#define CKEN_TOUCH    25      /* < Touch screen Interface Clock Enable */
++#define CKEN_SSP1     26      /* < SSP1 clock enable */
++#define CKEN_SSP2     27      /* < SSP2 clock enable */
++#define CKEN_SSP3     28      /* < SSP3 clock enable */
++#define CKEN_SSP4     29      /* < SSP4 clock enable */
++#define CKEN_MSL0     30      /* < MSL0 clock enable */
++#define CKEN_PWM0     32      /* < PWM[0] clock enable */
++#define CKEN_PWM1     33      /* < PWM[1] clock enable */
++#define CKEN_I2C      36      /* < I2C clock enable */
++#define CKEN_INTC     38      /* < Interrupt controller clock enable */
++#define CKEN_GPIO     39      /* < GPIO clock enable */
++#define CKEN_1WIRE    40      /* < 1-wire clock enable */
++#define CKEN_HSIO2    41      /* < HSIO2 clock enable */
++#define CKEN_MINI_IM  48      /* < Mini-IM */
++#define CKEN_MINI_LCD 49      /* < Mini LCD */
++
++#if defined(CONFIG_CPU_PXA310)
++#define CKEN_MMC3     5       /* < MMC3 Clock Enable */
++#define CKEN_MVED     43      /* < MVED clock enable */
++#endif
++
++/* Note: GCU clock enable bit differs on PXA300/PXA310 and PXA320 */
++#define PXA300_CKEN_GRAPHICS  42      /* Graphics controller clock enable */
++#define PXA320_CKEN_GRAPHICS  7       /* Graphics controller clock enable */
++
++#endif /* __ASM_ARCH_PXA3XX_REGS_H */
+--- linux-2.6.23.orig/include/asm-arm/arch-pxa/timex.h
++++ linux-2.6.23/include/asm-arm/arch-pxa/timex.h
+@@ -21,4 +21,6 @@
+ #else
+ #define CLOCK_TICK_RATE 3250000
+ #endif
++#else
++#define CLOCK_TICK_RATE 3250000
+ #endif
+--- /dev/null
++++ linux-2.6.23/include/asm-arm/arch-pxa/zylonite.h
+@@ -0,0 +1,35 @@
++#ifndef __ASM_ARCH_ZYLONITE_H
++#define __ASM_ARCH_ZYLONITE_H
++
++#define ZYLONITE_ETH_PHYS     0x14000000
++
++/* the following variables are processor specific and initialized
++ * by the corresponding zylonite_pxa3xx_init()
++ */
++extern int gpio_backlight;
++extern int gpio_eth_irq;
++
++extern int lcd_id;
++extern int lcd_orientation;
++
++#ifdef CONFIG_CPU_PXA300
++extern void zylonite_pxa300_init(void);
++#else
++static inline void zylonite_pxa300_init(void)
++{
++      if (cpu_is_pxa300() || cpu_is_pxa310())
++              panic("%s: PXA300/PXA310 not supported\n", __FUNCTION__);
++}
++#endif
++
++#ifdef CONFIG_CPU_PXA320
++extern void zylonite_pxa320_init(void);
++#else
++static inline void zylonite_pxa320_init(void)
++{
++      if (cpu_is_pxa320())
++              panic("%s: PXA320 not supported\n", __FUNCTION__);
++}
++#endif
++
++#endif /* __ASM_ARCH_ZYLONITE_H */
diff --git a/packages/kexecboot/linux-kexecboot-2.6.23/binutils-buildid-arm.patch b/packages/kexecboot/linux-kexecboot-2.6.23/binutils-buildid-arm.patch
new file mode 100644 (file)
index 0000000..68e35e8
--- /dev/null
@@ -0,0 +1,16 @@
+---
+ arch/arm/kernel/vmlinux.lds.S |    1 +
+ 1 file changed, 1 insertion(+)
+
+Index: linux-2.6.22/arch/arm/kernel/vmlinux.lds.S
+===================================================================
+--- linux-2.6.22.orig/arch/arm/kernel/vmlinux.lds.S    2007-09-11 18:32:29.000000000 +0200
++++ linux-2.6.22/arch/arm/kernel/vmlinux.lds.S 2007-09-11 18:33:42.000000000 +0200
+@@ -94,6 +94,7 @@
+                       TEXT_TEXT
+                       SCHED_TEXT
+                       LOCK_TEXT
++                      *(.note.*)
+ #ifdef CONFIG_MMU
+                       *(.fixup)
+ #endif
diff --git a/packages/kexecboot/linux-kexecboot-2.6.23/bootcdx86/defconfig b/packages/kexecboot/linux-kexecboot-2.6.23/bootcdx86/defconfig
new file mode 100644 (file)
index 0000000..244df73
--- /dev/null
@@ -0,0 +1,1579 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.23
+# Wed Feb  6 18:24:38 2008
+#
+CONFIG_X86_32=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_CLOCKSOURCE_WATCHDOG=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_SEMAPHORE_SLEEPERS=y
+CONFIG_X86=y
+CONFIG_MMU=y
+CONFIG_ZONE_DMA=y
+CONFIG_QUICKLIST=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_GENERIC_IOMAP=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_DMI=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_USER_NS is not set
+CONFIG_AUDIT=y
+CONFIG_AUDITSYSCALL=y
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=15
+# CONFIG_CPUSETS is not set
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_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_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+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_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_SMP=y
+CONFIG_X86_PC=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_PARAVIRT 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 is not set
+CONFIG_MPENTIUMII=y
+# CONFIG_MPENTIUMIII is not set
+# CONFIG_MPENTIUMM is not set
+# CONFIG_MCORE2 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_MVIAC7 is not set
+CONFIG_X86_GENERIC=y
+CONFIG_X86_CMPXCHG=y
+CONFIG_X86_L1_CACHE_SHIFT=7
+CONFIG_X86_XADD=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_X86_WP_WORKS_OK=y
+CONFIG_X86_INVLPG=y
+CONFIG_X86_BSWAP=y
+CONFIG_X86_POPAD_OK=y
+CONFIG_X86_GOOD_APIC=y
+CONFIG_X86_INTEL_USERCOPY=y
+CONFIG_X86_USE_PPRO_CHECKSUM=y
+CONFIG_X86_TSC=y
+CONFIG_X86_CMOV=y
+CONFIG_X86_MINIMUM_CPU_FAMILY=4
+CONFIG_HPET_TIMER=y
+CONFIG_NR_CPUS=8
+CONFIG_SCHED_SMT=y
+CONFIG_SCHED_MC=y
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_PREEMPT_BKL=y
+CONFIG_X86_LOCAL_APIC=y
+CONFIG_X86_IO_APIC=y
+CONFIG_X86_MCE=y
+CONFIG_X86_MCE_NONFATAL=y
+CONFIG_X86_MCE_P4THERMAL=y
+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 is not set
+# CONFIG_X86_CPUID is not set
+
+#
+# Firmware Drivers
+#
+# CONFIG_EDD is not set
+# CONFIG_DELL_RBU is not set
+# CONFIG_DCDBAS is not set
+CONFIG_DMIID=y
+CONFIG_NOHIGHMEM=y
+# CONFIG_HIGHMEM4G is not set
+# CONFIG_HIGHMEM64G is not set
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_3G_OPT is not set
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_2G_OPT is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+# CONFIG_X86_PAE is not set
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_SPARSEMEM_STATIC=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_NR_QUICK=1
+CONFIG_VIRT_TO_BUS=y
+# CONFIG_MATH_EMULATION is not set
+CONFIG_MTRR=y
+# CONFIG_EFI is not set
+CONFIG_IRQBALANCE=y
+CONFIG_SECCOMP=y
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_KEXEC=y
+CONFIG_PHYSICAL_START=0x100000
+# CONFIG_RELOCATABLE is not set
+CONFIG_PHYSICAL_ALIGN=0x100000
+CONFIG_HOTPLUG_CPU=y
+# CONFIG_COMPAT_VDSO is not set
+
+#
+# Power management options (ACPI, APM)
+#
+CONFIG_PM=y
+CONFIG_PM_LEGACY=y
+# CONFIG_PM_DEBUG is not set
+CONFIG_PM_SLEEP_SMP=y
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND_SMP_POSSIBLE=y
+CONFIG_SUSPEND=y
+CONFIG_HIBERNATION_SMP_POSSIBLE=y
+# CONFIG_HIBERNATION is not set
+CONFIG_ACPI=y
+CONFIG_ACPI_SLEEP=y
+CONFIG_ACPI_PROCFS=y
+CONFIG_ACPI_PROC_EVENT=y
+CONFIG_ACPI_AC=y
+CONFIG_ACPI_BATTERY=y
+CONFIG_ACPI_BUTTON=y
+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_ASUS is not set
+# CONFIG_ACPI_TOSHIBA is not set
+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 is not set
+# CONFIG_APM is not set
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ 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_GOANY=y
+CONFIG_PCI_BIOS=y
+CONFIG_PCI_DIRECT=y
+CONFIG_PCI_MMCONFIG=y
+CONFIG_PCIEPORTBUS=y
+CONFIG_PCIEAER=y
+CONFIG_ARCH_SUPPORTS_MSI=y
+CONFIG_PCI_MSI=y
+CONFIG_HT_IRQ=y
+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 is not set
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=m
+# 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=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK is not set
+# CONFIG_NF_CONNTRACK_ENABLED is not set
+# CONFIG_NF_CONNTRACK is not set
+CONFIG_NETFILTER_XTABLES=m
+# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
+# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
+# CONFIG_NETFILTER_XT_TARGET_MARK is not set
+# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
+# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
+# CONFIG_NETFILTER_XT_TARGET_TRACE is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
+# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
+# CONFIG_NETFILTER_XT_MATCH_ESP is not set
+# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
+# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_MAC is not set
+# CONFIG_NETFILTER_XT_MATCH_MARK is not set
+# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
+# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
+# CONFIG_NETFILTER_XT_MATCH_REALM is not set
+# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
+# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
+# CONFIG_NETFILTER_XT_MATCH_STRING is not set
+# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_U32 is not set
+# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=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_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# 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_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=m
+# CONFIG_SYS_HYPERVISOR is not set
+CONFIG_CONNECTOR=y
+CONFIG_PROC_EVENTS=y
+# CONFIG_MTD is not set
+# CONFIG_PARPORT is not set
+CONFIG_PNP=y
+# CONFIG_PNP_DEBUG is not set
+
+#
+# Protocols
+#
+# CONFIG_ISAPNP is not set
+# CONFIG_PNPBIOS is not set
+CONFIG_PNPACPI=y
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_FD is not set
+# 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 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=1
+CONFIG_BLK_DEV_RAM_SIZE=81920
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_IBM_ASM is not set
+# CONFIG_PHANTOM is not set
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+# CONFIG_SONY_LAPTOP is not set
+# CONFIG_THINKPAD_ACPI is not set
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+CONFIG_CHR_DEV_SG=y
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_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_AIC94XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_IN2000 is not set
+# CONFIG_SCSI_ARCMSR is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_SCSI_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_STEX is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_PAS16 is not set
+# CONFIG_SCSI_PSI240I is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_SEAGATE 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_ULTRASTOR is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
+# CONFIG_ATA is not set
+# 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_FIREWIRE is not set
+# CONFIG_IEEE1394 is not set
+# CONFIG_I2O is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_NET_SB1000 is not set
+# CONFIG_ARCNET is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+CONFIG_NET_VENDOR_3COM=y
+# CONFIG_EL1 is not set
+# CONFIG_EL2 is not set
+# CONFIG_ELPLUS is not set
+# CONFIG_EL16 is not set
+# CONFIG_EL3 is not set
+# CONFIG_3C515 is not set
+CONFIG_VORTEX=m
+CONFIG_TYPHOON=m
+CONFIG_LANCE=m
+CONFIG_NET_VENDOR_SMC=y
+CONFIG_WD80x3=m
+CONFIG_ULTRA=m
+CONFIG_SMC9194=m
+# CONFIG_NET_VENDOR_RACAL is not set
+CONFIG_NET_TULIP=y
+# CONFIG_DE2104X is not set
+CONFIG_TULIP=m
+CONFIG_TULIP_MWI=y
+CONFIG_TULIP_MMIO=y
+CONFIG_TULIP_NAPI=y
+CONFIG_TULIP_NAPI_HW_MITIGATION=y
+CONFIG_DE4X5=m
+CONFIG_WINBOND_840=m
+CONFIG_DM9102=m
+CONFIG_ULI526X=m
+CONFIG_AT1700=m
+CONFIG_DEPCA=m
+CONFIG_HP100=m
+CONFIG_NET_ISA=y
+# CONFIG_E2100 is not set
+# CONFIG_EWRK3 is not set
+# 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=y
+# CONFIG_ZNET is not set
+# CONFIG_SEEQ8005 is not set
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=m
+CONFIG_PCNET32_NAPI=y
+CONFIG_AMD8111_ETH=m
+CONFIG_AMD8111E_NAPI=y
+CONFIG_ADAPTEC_STARFIRE=m
+CONFIG_ADAPTEC_STARFIRE_NAPI=y
+CONFIG_AC3200=m
+CONFIG_APRICOT=m
+CONFIG_B44=m
+CONFIG_FORCEDETH=m
+CONFIG_FORCEDETH_NAPI=y
+CONFIG_CS89x0=m
+CONFIG_DGRS=m
+CONFIG_EEPRO100=m
+CONFIG_E100=m
+CONFIG_FEALNX=m
+CONFIG_NATSEMI=m
+CONFIG_NE2K_PCI=y
+CONFIG_8139CP=m
+CONFIG_8139TOO=m
+CONFIG_8139TOO_PIO=y
+CONFIG_8139TOO_TUNE_TWISTER=y
+CONFIG_8139TOO_8129=y
+# CONFIG_8139_OLD_RX_RESET is not set
+CONFIG_SIS900=m
+CONFIG_EPIC100=m
+CONFIG_SUNDANCE=m
+CONFIG_SUNDANCE_MMIO=y
+CONFIG_TLAN=m
+CONFIG_VIA_RHINE=m
+CONFIG_VIA_RHINE_MMIO=y
+CONFIG_VIA_RHINE_NAPI=y
+CONFIG_SC92031=m
+CONFIG_NETDEV_1000=y
+CONFIG_ACENIC=m
+CONFIG_ACENIC_OMIT_TIGON_I=y
+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_SIS190=m
+CONFIG_SKGE=m
+CONFIG_SKY2=m
+CONFIG_SK98LIN=m
+CONFIG_VIA_VELOCITY=m
+CONFIG_TIGON3=m
+CONFIG_BNX2=m
+CONFIG_QLA3XXX=m
+CONFIG_ATL1=m
+CONFIG_NETDEV_10000=y
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
+# CONFIG_MLX4_CORE is not set
+# CONFIG_TR is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 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_MII is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=m
+# 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=y
+# CONFIG_INPUT_EVBUG is not set
+# CONFIG_INPUT_POWER is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_LIFEBOOK=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_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_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=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 is not set
+CONFIG_FIX_EARLYCON_MEM=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_PNP=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_JSM is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_WATCHDOG is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_SONYPI is not set
+CONFIG_AGP=m
+CONFIG_AGP_ALI=m
+CONFIG_AGP_ATI=m
+CONFIG_AGP_AMD=m
+CONFIG_AGP_AMD64=m
+CONFIG_AGP_INTEL=m
+CONFIG_AGP_NVIDIA=m
+CONFIG_AGP_SIS=m
+CONFIG_AGP_SWORKS=m
+CONFIG_AGP_VIA=m
+CONFIG_AGP_EFFICEON=m
+# CONFIG_DRM is not set
+# CONFIG_MWAVE is not set
+# CONFIG_PC8736x_GPIO is not set
+# CONFIG_NSC_GPIO is not set
+# CONFIG_CS5535_GPIO is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_HPET is not set
+# CONFIG_HANGCHECK_TIMER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+CONFIG_DEVPORT=y
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_ASIC3 is not set
+# CONFIG_HTC_ASIC3_DS1WM is not set
+
+#
+# Multi-Function Devices
+#
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_VIDEO_V4L2=y
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+# CONFIG_VIDEO_VIVI is not set
+# CONFIG_VIDEO_PMS is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_VIDEO_STRADIS is not set
+CONFIG_V4L_USB_DRIVERS=y
+# CONFIG_USB_VICAM is not set
+# CONFIG_USB_IBMCAM is not set
+# CONFIG_USB_KONICAWC is not set
+# CONFIG_USB_QUICKCAM_MESSENGER is not set
+# CONFIG_USB_ET61X251 is not set
+# CONFIG_USB_OV511 is not set
+# CONFIG_USB_SE401 is not set
+# CONFIG_USB_SN9C102 is not set
+# CONFIG_USB_STV680 is not set
+# CONFIG_USB_ZC0301 is not set
+# CONFIG_USB_PWC is not set
+# CONFIG_USB_ZR364XX is not set
+CONFIG_RADIO_ADAPTERS=y
+# 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 is not set
+# CONFIG_RADIO_MAXIRADIO is not set
+# CONFIG_RADIO_MAESTRO is not set
+# 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 is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+CONFIG_VGASTATE=y
+CONFIG_VIDEO_OUTPUT_CONTROL=m
+CONFIG_FB=y
+CONFIG_FIRMWARE_EDID=y
+# CONFIG_FB_DDC is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_SYS_FOPS is not set
+CONFIG_FB_DEFERRED_IO=y
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_CIRRUS is not set
+# 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 is not set
+CONFIG_FB_UVESA=m
+# CONFIG_FB_VESA is not set
+# CONFIG_FB_HECUBA is not set
+# CONFIG_FB_HGA is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_I810 is not set
+# CONFIG_FB_LE80578 is not set
+# CONFIG_FB_INTEL is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_S3 is not set
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_VT8623 is not set
+# CONFIG_FB_CYBLA is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_ARK is not set
+# CONFIG_FB_PM3 is not set
+# CONFIG_FB_GEODE 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_VIDEO_SELECT=y
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+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
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+CONFIG_LOGO_OHAND_CLUT224=y
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+CONFIG_SND_SEQUENCER=y
+# CONFIG_SND_SEQ_DUMMY is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_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_AC97_CODEC=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
+
+#
+# ISA devices
+#
+# CONFIG_SND_ADLIB is not set
+# 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 is not set
+# 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 is not set
+# CONFIG_SND_OPTI92X_AD1848 is not set
+# CONFIG_SND_OPTI92X_CS4231 is not set
+# CONFIG_SND_OPTI93X is not set
+# CONFIG_SND_MIRO is not set
+# CONFIG_SND_SB8 is not set
+# CONFIG_SND_SB16 is not set
+# CONFIG_SND_SBAWE 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 is not set
+# CONFIG_SND_ALS300 is not set
+# CONFIG_SND_ALS4000 is not set
+# CONFIG_SND_ALI5451 is not set
+# CONFIG_SND_ATIIXP is not set
+# CONFIG_SND_ATIIXP_MODEM is not set
+# CONFIG_SND_AU8810 is not set
+# CONFIG_SND_AU8820 is not set
+# CONFIG_SND_AU8830 is not set
+# CONFIG_SND_AZT3328 is not set
+# CONFIG_SND_BT87X is not set
+# CONFIG_SND_CA0106 is not set
+# CONFIG_SND_CMIPCI is not set
+# CONFIG_SND_CS4281 is not set
+# CONFIG_SND_CS46XX is not set
+# CONFIG_SND_CS5530 is not set
+# CONFIG_SND_CS5535AUDIO is not set
+# CONFIG_SND_DARLA20 is not set
+# CONFIG_SND_GINA20 is not set
+# CONFIG_SND_LAYLA20 is not set
+# CONFIG_SND_DARLA24 is not set
+# CONFIG_SND_GINA24 is not set
+# CONFIG_SND_LAYLA24 is not set
+# CONFIG_SND_MONA is not set
+# CONFIG_SND_MIA is not set
+# CONFIG_SND_ECHO3G is not set
+# CONFIG_SND_INDIGO is not set
+# CONFIG_SND_INDIGOIO is not set
+# CONFIG_SND_INDIGODJ is not set
+# CONFIG_SND_EMU10K1 is not set
+# CONFIG_SND_EMU10K1X is not set
+# CONFIG_SND_ENS1370 is not set
+# CONFIG_SND_ENS1371 is not set
+# CONFIG_SND_ES1938 is not set
+# CONFIG_SND_ES1968 is not set
+# CONFIG_SND_FM801 is not set
+# CONFIG_SND_HDA_INTEL is not set
+# CONFIG_SND_HDSP is not set
+# CONFIG_SND_HDSPM is not set
+# CONFIG_SND_ICE1712 is not set
+# CONFIG_SND_ICE1724 is not set
+CONFIG_SND_INTEL8X0=y
+# CONFIG_SND_INTEL8X0M is not set
+# CONFIG_SND_KORG1212 is not set
+# CONFIG_SND_MAESTRO3 is not set
+# CONFIG_SND_MIXART is not set
+# CONFIG_SND_NM256 is not set
+# CONFIG_SND_PCXHR is not set
+# CONFIG_SND_RIPTIDE is not set
+# CONFIG_SND_RME32 is not set
+# CONFIG_SND_RME96 is not set
+# CONFIG_SND_RME9652 is not set
+# CONFIG_SND_SONICVIBES is not set
+# CONFIG_SND_TRIDENT is not set
+# CONFIG_SND_VIA82XX is not set
+# CONFIG_SND_VIA82XX_MODEM is not set
+# CONFIG_SND_VX222 is not set
+# CONFIG_SND_YMFPCI is not set
+CONFIG_SND_AC97_POWER_SAVE=y
+
+#
+# USB devices
+#
+# CONFIG_SND_USB_AUDIO is not set
+# CONFIG_SND_USB_USX2Y is not set
+# CONFIG_SND_USB_CAIAQ is not set
+
+#
+# System on Chip audio support
+#
+# CONFIG_SND_SOC is not set
+
+#
+# SoC Audio support for SuperH
+#
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+CONFIG_AC97_BUS=y
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+CONFIG_USB_SUSPEND=y
+# CONFIG_USB_PERSIST is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_SPLIT_ISO=y
+# 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_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=y
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+# CONFIG_USB_STORAGE is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+# 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_ADUTUX is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+# CONFIG_MMC is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_INFINIBAND is not set
+# CONFIG_EDAC is not set
+# CONFIG_RTC_CLASS is not set
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+CONFIG_VIRTUALIZATION=y
+# CONFIG_KVM is not set
+
+#
+# Userspace I/O
+#
+# CONFIG_UIO is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_JBD=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 is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+# CONFIG_ZISOFS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS 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 is not set
+CONFIG_LOCKD=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="utf-8"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=y
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+CONFIG_INSTRUMENTATION=y
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=y
+# CONFIG_KPROBES is not set
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_EARLY_PRINTK=y
+CONFIG_X86_FIND_SMP_CONFIG=y
+CONFIG_X86_MPPARSE=y
+CONFIG_DOUBLEFAULT=y
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=m
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_MANAGER=m
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC 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=m
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_TWOFISH_586 is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_AES_586 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_LZO is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_TEST is not set
+CONFIG_CRYPTO_HW=y
+CONFIG_CRYPTO_DEV_PADLOCK=m
+CONFIG_CRYPTO_DEV_PADLOCK_AES=m
+CONFIG_CRYPTO_DEV_PADLOCK_SHA=m
+CONFIG_CRYPTO_DEV_GEODE=m
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+CONFIG_LIBCRC32C=m
+CONFIG_AUDIT_GENERIC=y
+CONFIG_ZLIB_INFLATE=m
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=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/packages/kexecboot/linux-kexecboot-2.6.23/c7x0/defconfig b/packages/kexecboot/linux-kexecboot-2.6.23/c7x0/defconfig
new file mode 100644 (file)
index 0000000..a541a10
--- /dev/null
@@ -0,0 +1,1039 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.23
+# Sat Dec 13 19:36:13 2008
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_MMU=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ZONE_DMA=y
+CONFIG_ARCH_MTD_XIP=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+# CONFIG_USER_NS is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE="initramfs.cpio.gz"
+CONFIG_INITRAMFS_ROOT_UID=0
+CONFIG_INITRAMFS_ROOT_GID=0
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+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_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# 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_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_MXC 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_DAVINCI is not set
+# CONFIG_ARCH_OMAP 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=y
+# CONFIG_MACH_TRIZEPS4 is not set
+# CONFIG_MACH_EM_X270 is not set
+# CONFIG_MACH_HX2750 is not set
+# CONFIG_MACH_HTCUNIVERSAL is not set
+CONFIG_PXA_SHARPSL_25x=y
+# CONFIG_PXA_SHARPSL_27x is not set
+# CONFIG_MACH_POODLE is not set
+CONFIG_MACH_CORGI=y
+CONFIG_MACH_SHEPHERD=y
+CONFIG_MACH_HUSKY=y
+# CONFIG_MACH_TOSA is not set
+CONFIG_PXA25x=y
+CONFIG_PXA_SHARP_C7xx=y
+CONFIG_PXA_SSP=y
+# CONFIG_PXA_KEYS is not set
+
+#
+# Boot options
+#
+
+#
+# Power management
+#
+
+#
+# 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
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_OUTER_CACHE is not set
+# CONFIG_IWMMXT is not set
+CONFIG_XSCALE_PMU=y
+CONFIG_SHARP_PARAM=y
+CONFIG_SHARPSL_PM=y
+CONFIG_SHARP_SCOOP=y
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_PREEMPT=y
+CONFIG_HZ=100
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT 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_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=tty0"
+# CONFIG_XIP_KERNEL is not set
+CONFIG_KEXEC=y
+CONFIG_ATAGS_PROC=y
+CONFIG_CPU_FREQ_PXA25x=y
+
+#
+# CPU Frequency scaling
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+CONFIG_CPU_FREQ_DEBUG=y
+CONFIG_CPU_FREQ_STAT=y
+# CONFIG_CPU_FREQ_STAT_DETAILS is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND_UP_POSSIBLE=y
+CONFIG_SUSPEND=y
+CONFIG_APM_EMULATION=y
+
+#
+# Networking
+#
+# CONFIG_NET 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_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI 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=y
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_SHARP_SL=y
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_VERIFY_WRITE=y
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_H1900 is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+CONFIG_MTD_NAND_SHARPSL=y
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_CDROM_PKTCDVD is not set
+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 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
+CONFIG_IDE_PROC_FS=y
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_IDEPCI_PCIBUS_ORDER is not set
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+CONFIG_MD=y
+# CONFIG_BLK_DEV_MD is not set
+# CONFIG_BLK_DEV_DM is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=640
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=480
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+CONFIG_INPUT_POWER=y
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+CONFIG_KEYBOARD_CORGI=y
+# CONFIG_KEYBOARD_SPITZ is not set
+# CONFIG_KEYBOARD_GPIO is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_CORGI=y
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_UCB1400 is not set
+# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_ATI_REMOTE is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
+# CONFIG_INPUT_UINPUT is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_PXA=y
+CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_HW_RANDOM=m
+# CONFIG_NVRAM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+# CONFIG_I2C_CHARDEV 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_GPIO is not set
+CONFIG_I2C_PXA=y
+# CONFIG_I2C_PXA_SLAVE is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_DS1682 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_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_EEPROM_93CX6 is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_ASIC3 is not set
+# CONFIG_HTC_ASIC3_DS1WM is not set
+
+#
+# Multi-Function Devices
+#
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+CONFIG_LEDS_CORGI=y
+# CONFIG_LEDS_TOSA is not set
+# CONFIG_LEDS_GPIO is not set
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_IDE_DISK=y
+# CONFIG_LEDS_TRIGGER_HEARTBEAT is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+CONFIG_DAB=y
+
+#
+# Graphics support
+#
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+# CONFIG_LCD_CLASS_DEVICE is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_CORGI=y
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=m
+CONFIG_FB=y
+CONFIG_FIRMWARE_EDID=y
+# CONFIG_FB_DDC is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_SYS_FOPS is not set
+CONFIG_FB_DEFERRED_IO=y
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_PXA is not set
+# CONFIG_FB_MBX is not set
+CONFIG_FB_W100=y
+# 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_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+CONFIG_FONTS=y
+# CONFIG_FONT_8x8 is not set
+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
+# CONFIG_LOGO is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+# CONFIG_USB is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG is not set
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+CONFIG_USB_GADGET_PXA2XX=y
+CONFIG_USB_PXA2XX=y
+# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_PXA27X is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+# CONFIG_USB_GADGET_DUALSPEED 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
+# CONFIG_USB_MIDI_GADGET is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_UNSAFE_RESUME=y
+
+#
+# MMC/SD Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+
+#
+# MMC/SD Host Controller Drivers
+#
+CONFIG_MMC_PXA=y
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_SA1100=y
+
+#
+# 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_EXT4DEV_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+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 is not set
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+CONFIG_JFFS2_SUMMARY=y
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_SYSFS is not set
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_LZO=y
+CONFIG_JFFS2_RTIME=y
+CONFIG_JFFS2_RUBIN=y
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="cp437"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=y
+
+#
+# Profiling support
+#
+CONFIG_PROFILING=y
+# CONFIG_OPROFILE is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+CONFIG_TIMER_STATS=y
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_PREEMPT is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_FORCED_INLINING is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_DEBUG_USER is not set
+CONFIG_DEBUG_ERRORS=y
+# CONFIG_DEBUG_LL is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 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_GF128MUL is not set
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_TEST is not set
+CONFIG_CRYPTO_HW=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/packages/kexecboot/linux-kexecboot-2.6.23/collie/defconfig b/packages/kexecboot/linux-kexecboot-2.6.23/collie/defconfig
new file mode 100644 (file)
index 0000000..64e5090
--- /dev/null
@@ -0,0 +1,1790 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.20.4
+# Fri Apr  6 23:20:59 2007
+#
+CONFIG_ARM=y
+# CONFIG_GENERIC_TIME is not set
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_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_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_IPC_NS is not set
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+# CONFIG_ELF_CORE is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=m
+CONFIG_IOSCHED_CFQ=m
+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_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+CONFIG_ARCH_SA1100=y
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+
+#
+# SA11x0 Implementations
+#
+# CONFIG_SA1100_ASSABET is not set
+# CONFIG_SA1100_CERF is not set
+CONFIG_SA1100_COLLIE=y
+# CONFIG_SA1100_H3100 is not set
+# CONFIG_SA1100_H3600 is not set
+# CONFIG_SA1100_H3800 is not set
+# CONFIG_SA1100_BADGE4 is not set
+# CONFIG_SA1100_JORNADA720 is not set
+# CONFIG_SA1100_HACKKIT is not set
+# CONFIG_SA1100_LART is not set
+# CONFIG_SA1100_PLEB is not set
+# CONFIG_SA1100_SHANNON is not set
+# CONFIG_SA1100_SIMPAD is not set
+# CONFIG_SA1100_SSP is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_SA1100=y
+CONFIG_CPU_32v4=y
+CONFIG_CPU_ABRT_EV4=y
+CONFIG_CPU_CACHE_V4WB=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_TLB_V4WB=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+CONFIG_SHARP_LOCOMO=y
+CONFIG_SHARP_PARAM=y
+CONFIG_SHARP_SCOOP=y
+
+#
+# Bus support
+#
+CONFIG_ISA=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
+
+#
+# PC-card bridges
+#
+# CONFIG_I82365 is not set
+# CONFIG_TCIC is not set
+CONFIG_PCMCIA_SA1100=y
+
+#
+# Kernel Features
+#
+CONFIG_PREEMPT=y
+CONFIG_NO_IDLE_HZ=y
+CONFIG_HZ=100
+# CONFIG_AEABI is not set
+CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
+CONFIG_NODES_SHIFT=2
+CONFIG_SELECT_MEMORY_MODEL=y
+# CONFIG_FLATMEM_MANUAL is not set
+CONFIG_DISCONTIGMEM_MANUAL=y
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_DISCONTIGMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_NEED_MULTIPLE_NODES=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_RESOURCES_64BIT 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_XIP_KERNEL is not set
+CONFIG_KEXEC=y
+CONFIG_ATAGS_PROC=y
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# 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 is not set
+# CONFIG_PM_DEBUG is not set
+# CONFIG_PM_SYSFS_DEPRECATED is not set
+CONFIG_APM=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=m
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_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=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+
+#
+# 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_IPV6_MIP6 is not set
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=m
+CONFIG_IPV6_TUNNEL=m
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK is not set
+# CONFIG_NF_CONNTRACK_ENABLED is not set
+# CONFIG_NF_CONNTRACK is not set
+CONFIG_NETFILTER_XTABLES=m
+# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
+# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
+# CONFIG_NETFILTER_XT_TARGET_MARK is not set
+# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
+# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
+# CONFIG_NETFILTER_XT_TARGET_TRACE is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
+# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
+# CONFIG_NETFILTER_XT_MATCH_ESP is not set
+# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
+# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_MAC is not set
+# CONFIG_NETFILTER_XT_MATCH_MARK is not set
+# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
+# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
+# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
+# CONFIG_NETFILTER_XT_MATCH_REALM is not set
+# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
+# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
+# CONFIG_NETFILTER_XT_MATCH_STRING is not set
+# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_U32 is not set
+# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=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_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=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 is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+# CONFIG_IRDA_ULTRA is not set
+
+#
+# IrDA options
+#
+# CONFIG_IRDA_CACHE_LAST_LSAP is not set
+# CONFIG_IRDA_FAST_RR is not set
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+
+#
+# Dongle support
+#
+# CONFIG_DONGLE is not set
+
+#
+# Old SIR device drivers
+#
+# CONFIG_IRPORT_SIR is not set
+
+#
+# Old Serial dongle support
+#
+
+#
+# FIR device drivers
+#
+CONFIG_USB_IRDA=m
+# CONFIG_SIGMATEL_FIR is not set
+CONFIG_SA1100_FIR=m
+# CONFIG_MCS_FIR 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=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+# CONFIG_BT_HCIBCM203X is not set
+# CONFIG_BT_HCIBPA10X is not set
+# CONFIG_BT_HCIBFUSB is not set
+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 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 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=m
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE 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=y
+# CONFIG_MTD_ABSENT is not set
+CONFIG_MTD_OBSOLETE_CHIPS=y
+CONFIG_MTD_SHARP=y
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_SA1100=y
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_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=m
+CONFIG_IDE_MAX_HWIFS=4
+CONFIG_BLK_DEV_IDE=m
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=m
+# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_BLK_DEV_IDECS=m
+# CONFIG_BLK_DEV_IDECD 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 is not set
+# CONFIG_IDE_ARM is not set
+# CONFIG_IDE_CHIPSETS 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=m
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+CONFIG_CHR_DEV_ST=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 is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_AHA152X is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_IN2000 is not set
+# CONFIG_SCSI_DTC3280 is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
+# CONFIG_SCSI_NCR53C406A is not set
+# CONFIG_SCSI_PAS16 is not set
+# CONFIG_SCSI_PSI240I is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_SYM53C416 is not set
+# CONFIG_SCSI_T128 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
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+# CONFIG_BLK_DEV_MD is not set
+CONFIG_BLK_DEV_DM=m
+# CONFIG_DM_DEBUG is not set
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_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_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=m
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_ISA is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+# CONFIG_NET_WIRELESS_RTNETLINK is not set
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+# CONFIG_ARLAN is not set
+# CONFIG_WAVELAN 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=m
+# CONFIG_AIRO_CS is not set
+# CONFIG_PCMCIA_WL3501 is not set
+# CONFIG_USB_ZD1201 is not set
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+# CONFIG_HOSTAP_FIRMWARE_NVRAM is not set
+CONFIG_HOSTAP_CS=m
+CONFIG_NET_WIRELESS=y
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+# CONFIG_PCMCIA_3C589 is not set
+# CONFIG_PCMCIA_3C574 is not set
+# CONFIG_PCMCIA_FMVJ18X is not set
+CONFIG_PCMCIA_PCNET=m
+# CONFIG_PCMCIA_NMCLAN is not set
+# CONFIG_PCMCIA_SMC91C92 is not set
+# CONFIG_PCMCIA_XIRC2PS is not set
+# CONFIG_PCMCIA_AXNET is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+# CONFIG_PPP_MPPE is not set
+# CONFIG_PPPOE is not set
+# CONFIG_SLIP is not set
+CONFIG_SLHC=m
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=480
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=640
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+CONFIG_INPUT_POWER=y
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+CONFIG_KEYBOARD_LOCOMO=y
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO 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=m
+CONFIG_SERIAL_8250_CS=m
+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_SA1100=y
+CONFIG_SERIAL_SA1100_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+CONFIG_HW_RANDOM=m
+# CONFIG_NVRAM is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_CARDMAN_4000 is not set
+# CONFIG_CARDMAN_4040 is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=m
+# 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_ELEKTOR is not set
+# 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=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_BITBANG is not set
+CONFIG_SPI_LOCOMO=m
+
+#
+# SPI Protocol Masters
+#
+
+#
+# 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
+#
+# CONFIG_TIFM_CORE is not set
+
+#
+# Multimedia Capabilities Port drivers
+#
+CONFIG_MCP=y
+CONFIG_MCP_SA11X0=y
+CONFIG_MCP_UCB1200=y
+CONFIG_MCP_UCB1200_TS=m
+
+#
+# Multi-Function Devices
+#
+
+#
+# LED devices
+#
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=m
+
+#
+# LED drivers
+#
+CONFIG_LEDS_LOCOMO=m
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=m
+# CONFIG_LEDS_TRIGGER_IDE_DISK is not set
+CONFIG_LEDS_TRIGGER_HEARTBEAT=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_HELPER_CHIPS_AUTO=y
+# CONFIG_VIDEO_VIVI is not set
+# CONFIG_VIDEO_PMS is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_TUNER_3036 is not set
+
+#
+# V4L USB devices
+#
+# CONFIG_VIDEO_PVRUSB2 is not set
+# CONFIG_VIDEO_EM28XX is not set
+# CONFIG_VIDEO_USBVISION is not set
+# CONFIG_USB_VICAM is not set
+# CONFIG_USB_IBMCAM is not set
+# CONFIG_USB_KONICAWC is not set
+# CONFIG_USB_QUICKCAM_MESSENGER is not set
+# CONFIG_USB_ET61X251 is not set
+# CONFIG_VIDEO_OVCAMCHIP is not set
+# CONFIG_USB_W9968CF is not set
+# CONFIG_USB_OV511 is not set
+# CONFIG_USB_SE401 is not set
+# CONFIG_USB_SN9C102 is not set
+# CONFIG_USB_STV680 is not set
+# CONFIG_USB_ZC0301 is not set
+# CONFIG_USB_PWC 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_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 is not set
+
+#
+# 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 is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+CONFIG_FB_SA1100=y
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+# CONFIG_FONT_8x16 is not set
+# 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 is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=m
+CONFIG_LCD_DEVICE=y
+CONFIG_BACKLIGHT_LOCOMO=y
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+# CONFIG_SND_SEQUENCER is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+CONFIG_SND_DUMMY=m
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# ALSA ARM devices
+#
+
+#
+# USB devices
+#
+# CONFIG_SND_USB_AUDIO is not set
+
+#
+# PCMCIA devices
+#
+# CONFIG_SND_VXPOCKET is not set
+# CONFIG_SND_PDAUDIOCF is not set
+
+#
+# SoC audio support
+#
+# CONFIG_SND_SOC is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# HID Devices
+#
+CONFIG_HID=m
+
+#
+# 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=m
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_SL811_HCD=m
+CONFIG_USB_SL811_CS=m
+
+#
+# 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_KARMA is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=m
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_TOUCHSCREEN is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_ATI_REMOTE2 is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# 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_MII=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_MCS7830 is not set
+# CONFIG_USB_NET_RNDIS_HOST is not set
+CONFIG_USB_NET_CDC_SUBSET=m
+# CONFIG_USB_ALI_M5632 is not set
+# CONFIG_USB_AN2720 is not set
+CONFIG_USB_BELKIN=y
+CONFIG_USB_ARMLINUX=y
+# CONFIG_USB_EPSON2888 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_AIRCABLE is not set
+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 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_MOS7720 is not set
+# CONFIG_USB_SERIAL_MOS7840 is not set
+# CONFIG_USB_SERIAL_NAVMAN is not set
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_HP4X=m
+CONFIG_USB_SERIAL_SAFE=m
+# CONFIG_USB_SERIAL_SAFE_PADDED is not set
+# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+# CONFIG_USB_SERIAL_OPTION is not set
+# CONFIG_USB_SERIAL_OMNINET is not set
+# CONFIG_USB_SERIAL_DEBUG is not set
+CONFIG_USB_EZUSB=y
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_PXA2XX is not set
+# CONFIG_USB_GADGET_PXA27X is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+# CONFIG_USB_GADGET_DUALSPEED is not set
+
+#
+# MMC/SD Card support
+#
+CONFIG_MMC=m
+CONFIG_MMC_DEBUG=y
+CONFIG_MMC_BLOCK=m
+# CONFIG_MMC_TIFM_SD is not set
+CONFIG_MMC_SPI=m
+CONFIG_MMC_UNSAFE_RESUME=y
+
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+
+#
+# RTC drivers
+#
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+CONFIG_RTC_DRV_SA1100=y
+# CONFIG_RTC_DRV_TEST is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=m
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=m
+# CONFIG_EXT4DEV_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_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=m
+
+#
+# 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_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_LZO=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 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=y
+# 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_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+CONFIG_SMB_NLS_DEFAULT=y
+CONFIG_SMB_NLS_REMOTE="cp437"
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_WEAK_PW_HASH is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION 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="cp437"
+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=m
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=m
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK 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_PREEMPT 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 is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_FORCED_INLINING is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_DEBUG_USER 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_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_HASH=m
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_HMAC=m
+# CONFIG_CRYPTO_XCBC is not set
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=m
+# CONFIG_CRYPTO_LRW is not set
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+# CONFIG_CRYPTO_LZO is not set
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_TEST=m
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_LZO=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
+# CONFIG_SHARPSL_RC is not set
diff --git a/packages/kexecboot/linux-kexecboot-2.6.23/connectplus-prevent-oops-HACK.patch b/packages/kexecboot/linux-kexecboot-2.6.23/connectplus-prevent-oops-HACK.patch
new file mode 100644 (file)
index 0000000..b5439c6
--- /dev/null
@@ -0,0 +1,17 @@
+Index: linux-2.6.21/drivers/net/wireless/hostap/hostap_hw.c
+===================================================================
+--- linux-2.6.21.orig/drivers/net/wireless/hostap/hostap_hw.c  2007-07-07 12:45:39.000000000 +0100
++++ linux-2.6.21/drivers/net/wireless/hostap/hostap_hw.c       2007-07-07 12:47:30.000000000 +0100
+@@ -2666,6 +2666,12 @@
+       iface = netdev_priv(dev);
+       local = iface->local;
++      if(dev->base_addr == 0)
++      {
++              printk(KERN_DEBUG "%s: IRQ before base_addr set\n", dev->name);
++              return IRQ_HANDLED;
++      }
++
+       prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INTERRUPT, 0, 0);
+       if (local->func->card_present && !local->func->card_present(local)) {
diff --git a/packages/kexecboot/linux-kexecboot-2.6.23/connectplus-remove-ide-HACK.patch b/packages/kexecboot/linux-kexecboot-2.6.23/connectplus-remove-ide-HACK.patch
new file mode 100644 (file)
index 0000000..4414b21
--- /dev/null
@@ -0,0 +1,12 @@
+Index: linux-2.6.13/drivers/ide/legacy/ide-cs.c
+===================================================================
+--- linux-2.6.13.orig/drivers/ide/legacy/ide-cs.c      2005-09-01 22:43:46.000000000 +0100
++++ linux-2.6.13/drivers/ide/legacy/ide-cs.c   2005-09-01 22:45:46.000000000 +0100
+@@ -488,7 +488,6 @@
+       PCMCIA_DEVICE_PROD_ID123("KODAK Picture Card       ", "KODAK  ", "V100K", 0x94a0d8f3, 0xe4fc3ea0, 0xe5e7eed4),
+       PCMCIA_DEVICE_PROD_ID1("STI Flash", 0xe4a13209),
+       PCMCIA_DEVICE_PROD_ID12("STI", "Flash 5.0", 0xbf2df18d, 0x8cb57a0e),
+-      PCMCIA_MFC_DEVICE_PROD_ID12(1, "SanDisk", "ConnectPlus", 0x7a954bd9, 0x74be00c6),
+       PCMCIA_DEVICE_NULL,
+ };
+ MODULE_DEVICE_TABLE(pcmcia, ide_ids);
diff --git a/packages/kexecboot/linux-kexecboot-2.6.23/hostap-monitor-mode.patch b/packages/kexecboot/linux-kexecboot-2.6.23/hostap-monitor-mode.patch
new file mode 100644 (file)
index 0000000..641fd19
--- /dev/null
@@ -0,0 +1,209 @@
+This is a patch that I've been maintaining for a few years, and I'd 
+really like to see it added to the mainstream zaurus kernel so I can 
+finally stop distributing my own.
+
+This patch only effects the card while in monitor mode, and does not 
+cause any known stability issues.
+
+http://patches.aircrack-ng.org/hostap-kernel-2.6.18.patch
+
+Rick Farina (Zero_Chaos)
+
+diff -ur linux-2.6.18-gentoo/drivers/net/wireless/hostap/hostap_80211_tx.c linux-2.6.18-gentoo-rawtx/drivers/net/wireless/hostap/hostap_80211_tx.c
+--- linux-2.6.18-gentoo/drivers/net/wireless/hostap/hostap_80211_tx.c  2006-09-21 01:26:27.000000000 -0400
++++ linux-2.6.18-gentoo-rawtx/drivers/net/wireless/hostap/hostap_80211_tx.c    2006-09-21 01:30:18.000000000 -0400
+@@ -69,6 +69,9 @@
+       iface = netdev_priv(dev);
+       local = iface->local;
++      if (local->iw_mode == IW_MODE_MONITOR)
++              goto xmit;
++
+       if (skb->len < ETH_HLEN) {
+               printk(KERN_DEBUG "%s: hostap_data_start_xmit: short skb "
+                      "(len=%d)\n", dev->name, skb->len);
+@@ -234,6 +237,7 @@
+               memcpy(skb_put(skb, ETH_ALEN), &hdr.addr4, ETH_ALEN);
+       }
++xmit:
+       iface->stats.tx_packets++;
+       iface->stats.tx_bytes += skb->len;
+@@ -404,8 +408,6 @@
+       }
+       if (skb->len < 24) {
+-              printk(KERN_DEBUG "%s: hostap_master_start_xmit: short skb "
+-                     "(len=%d)\n", dev->name, skb->len);
+               ret = 0;
+               iface->stats.tx_dropped++;
+               goto fail;
+Only in linux-2.6.18-gentoo-rawtx/drivers/net/wireless/hostap: hostap_cs.c.orig
+Only in linux-2.6.18-gentoo-rawtx/drivers/net/wireless/hostap: hostap_cs.c.rej
+diff -ur linux-2.6.18-gentoo/drivers/net/wireless/hostap/hostap_hw.c linux-2.6.18-gentoo-rawtx/drivers/net/wireless/hostap/hostap_hw.c
+--- linux-2.6.18-gentoo/drivers/net/wireless/hostap/hostap_hw.c        2006-09-21 01:26:27.000000000 -0400
++++ linux-2.6.18-gentoo-rawtx/drivers/net/wireless/hostap/hostap_hw.c  2006-09-21 01:30:18.000000000 -0400
+@@ -1005,6 +1005,35 @@
+       return fid;
+ }
++static int prism2_monitor_enable(struct net_device *dev)
++{
++      if (hostap_set_word(dev, HFA384X_RID_CNFPORTTYPE, 5)) {
++              printk(KERN_DEBUG "Port type setting for monitor mode "
++                      "failed\n");
++              return -EOPNOTSUPP;
++      }
++
++      if (hfa384x_cmd(dev, HFA384X_CMDCODE_TEST | (0x0a << 8),
++                           0, NULL, NULL)) {
++              printk(KERN_DEBUG "Could not enter testmode 0x0a\n");
++              return -EOPNOTSUPP;
++      }
++
++      if (hostap_set_word(dev, HFA384X_RID_CNFWEPFLAGS,
++                          HFA384X_WEPFLAGS_PRIVACYINVOKED |
++                          HFA384X_WEPFLAGS_HOSTENCRYPT |
++                          HFA384X_WEPFLAGS_HOSTDECRYPT)) {
++              printk(KERN_DEBUG "WEP flags setting failed\n");
++              return -EOPNOTSUPP;
++      }
++
++      if (hostap_set_word(dev, HFA384X_RID_PROMISCUOUSMODE, 1)) {
++              printk(KERN_DEBUG "Could not set promiscuous mode\n");
++              return -EOPNOTSUPP;
++      }
++
++      return 0;
++}
+ static int prism2_reset_port(struct net_device *dev)
+ {
+@@ -1031,6 +1060,10 @@
+                              "port\n", dev->name);
+       }
++      if (local->iw_mode == IW_MODE_MONITOR)
++              /* force mode 0x0a after port 0 reset */
++              return prism2_monitor_enable(dev);
++
+       /* It looks like at least some STA firmware versions reset
+        * fragmentation threshold back to 2346 after enable command. Restore
+        * the configured value, if it differs from this default. */
+@@ -1466,6 +1499,10 @@
+               return 1;
+       }
++      if (local->iw_mode == IW_MODE_MONITOR)
++              /* force mode 0x0a after port 0 reset */
++              prism2_monitor_enable(dev);
++
+       local->hw_ready = 1;
+       local->hw_reset_tries = 0;
+       local->hw_resetting = 0;
+@@ -3156,6 +3193,7 @@
+       local->func->hw_config = prism2_hw_config;
+       local->func->hw_reset = prism2_hw_reset;
+       local->func->hw_shutdown = prism2_hw_shutdown;
++      local->func->monitor_enable = prism2_monitor_enable;
+       local->func->reset_port = prism2_reset_port;
+       local->func->schedule_reset = prism2_schedule_reset;
+ #ifdef PRISM2_DOWNLOAD_SUPPORT
+Only in linux-2.6.18-gentoo-rawtx/drivers/net/wireless/hostap: hostap_hw.c.orig
+diff -ur linux-2.6.18-gentoo/drivers/net/wireless/hostap/hostap_ioctl.c linux-2.6.18-gentoo-rawtx/drivers/net/wireless/hostap/hostap_ioctl.c
+--- linux-2.6.18-gentoo/drivers/net/wireless/hostap/hostap_ioctl.c     2006-09-21 01:26:27.000000000 -0400
++++ linux-2.6.18-gentoo-rawtx/drivers/net/wireless/hostap/hostap_ioctl.c       2006-09-21 01:30:18.000000000 -0400
+@@ -1104,33 +1104,7 @@
+       printk(KERN_DEBUG "Enabling monitor mode\n");
+       hostap_monitor_set_type(local);
+-
+-      if (hostap_set_word(dev, HFA384X_RID_CNFPORTTYPE,
+-                          HFA384X_PORTTYPE_PSEUDO_IBSS)) {
+-              printk(KERN_DEBUG "Port type setting for monitor mode "
+-                     "failed\n");
+-              return -EOPNOTSUPP;
+-      }
+-
+-      /* Host decrypt is needed to get the IV and ICV fields;
+-       * however, monitor mode seems to remove WEP flag from frame
+-       * control field */
+-      if (hostap_set_word(dev, HFA384X_RID_CNFWEPFLAGS,
+-                          HFA384X_WEPFLAGS_HOSTENCRYPT |
+-                          HFA384X_WEPFLAGS_HOSTDECRYPT)) {
+-              printk(KERN_DEBUG "WEP flags setting failed\n");
+-              return -EOPNOTSUPP;
+-      }
+-
+-      if (local->func->reset_port(dev) ||
+-          local->func->cmd(dev, HFA384X_CMDCODE_TEST |
+-                           (HFA384X_TEST_MONITOR << 8),
+-                           0, NULL, NULL)) {
+-              printk(KERN_DEBUG "Setting monitor mode failed\n");
+-              return -EOPNOTSUPP;
+-      }
+-
+-      return 0;
++      return local->func->reset_port(dev);
+ }
+@@ -1199,7 +1173,7 @@
+       local->iw_mode = *mode;
+       if (local->iw_mode == IW_MODE_MONITOR)
+-              hostap_monitor_mode_enable(local);
++              return hostap_monitor_mode_enable(local);
+       else if (local->iw_mode == IW_MODE_MASTER && !local->host_encrypt &&
+                !local->fw_encrypt_ok) {
+               printk(KERN_DEBUG "%s: defaulting to host-based encryption as "
+diff -ur linux-2.6.18-gentoo/drivers/net/wireless/hostap/hostap_main.c linux-2.6.18-gentoo-rawtx/drivers/net/wireless/hostap/hostap_main.c
+--- linux-2.6.18-gentoo/drivers/net/wireless/hostap/hostap_main.c      2006-09-21 01:26:27.000000000 -0400
++++ linux-2.6.18-gentoo-rawtx/drivers/net/wireless/hostap/hostap_main.c        2006-09-21 01:30:18.000000000 -0400
+@@ -331,7 +331,7 @@
+       if (local->iw_mode == IW_MODE_REPEAT)
+               return HFA384X_PORTTYPE_WDS;
+       if (local->iw_mode == IW_MODE_MONITOR)
+-              return HFA384X_PORTTYPE_PSEUDO_IBSS;
++              return 5; /*HFA384X_PORTTYPE_PSEUDO_IBSS;*/
+       return HFA384X_PORTTYPE_HOSTAP;
+ }
+Only in linux-2.6.18-gentoo-rawtx/drivers/net/wireless/hostap: hostap_main.c.orig
+diff -ur linux-2.6.18-gentoo/drivers/net/wireless/hostap/hostap_pci.c linux-2.6.18-gentoo-rawtx/drivers/net/wireless/hostap/hostap_pci.c
+--- linux-2.6.18-gentoo/drivers/net/wireless/hostap/hostap_pci.c       2006-09-21 01:26:27.000000000 -0400
++++ linux-2.6.18-gentoo-rawtx/drivers/net/wireless/hostap/hostap_pci.c 2006-09-21 01:30:18.000000000 -0400
+@@ -48,6 +48,8 @@
+       { 0x1260, 0x3873, PCI_ANY_ID, PCI_ANY_ID },
+       /* Samsung MagicLAN SWL-2210P */
+       { 0x167d, 0xa000, PCI_ANY_ID, PCI_ANY_ID },
++      /* NETGEAR MA311 */
++      { 0x1385, 0x3872, PCI_ANY_ID, PCI_ANY_ID },
+       { 0 }
+ };
+Only in linux-2.6.18-gentoo-rawtx/drivers/net/wireless/hostap: hostap_pci.c.orig
+diff -ur linux-2.6.18-gentoo/drivers/net/wireless/hostap/hostap_plx.c linux-2.6.18-gentoo-rawtx/drivers/net/wireless/hostap/hostap_plx.c
+--- linux-2.6.18-gentoo/drivers/net/wireless/hostap/hostap_plx.c       2006-09-21 01:26:27.000000000 -0400
++++ linux-2.6.18-gentoo-rawtx/drivers/net/wireless/hostap/hostap_plx.c 2006-09-21 01:30:18.000000000 -0400
+@@ -101,6 +101,7 @@
+       { 0xc250, 0x0002 } /* EMTAC A2424i */,
+       { 0xd601, 0x0002 } /* Z-Com XI300 */,
+       { 0xd601, 0x0005 } /* Zcomax XI-325H 200mW */,
++      { 0xd601, 0x0010 } /* Zcomax XI-325H 100mW */,
+       { 0, 0}
+ };
+Only in linux-2.6.18-gentoo-rawtx/drivers/net/wireless/hostap: hostap_plx.c.orig
+diff -ur linux-2.6.18-gentoo/drivers/net/wireless/hostap/hostap_wlan.h linux-2.6.18-gentoo-rawtx/drivers/net/wireless/hostap/hostap_wlan.h
+--- linux-2.6.18-gentoo/drivers/net/wireless/hostap/hostap_wlan.h      2006-09-21 01:26:27.000000000 -0400
++++ linux-2.6.18-gentoo-rawtx/drivers/net/wireless/hostap/hostap_wlan.h        2006-09-21 01:30:18.000000000 -0400
+@@ -575,6 +575,7 @@
+       int (*hw_config)(struct net_device *dev, int initial);
+       void (*hw_reset)(struct net_device *dev);
+       void (*hw_shutdown)(struct net_device *dev, int no_disable);
++      int (*monitor_enable)(struct net_device *dev);
+       int (*reset_port)(struct net_device *dev);
+       void (*schedule_reset)(local_info_t *local);
+       int (*download)(local_info_t *local,
diff --git a/packages/kexecboot/linux-kexecboot-2.6.23/hrw-add-wcf11-to-hostap.patch b/packages/kexecboot/linux-kexecboot-2.6.23/hrw-add-wcf11-to-hostap.patch
new file mode 100644 (file)
index 0000000..5ee8b20
--- /dev/null
@@ -0,0 +1,31 @@
+From: Marcin Juszkiewicz <openembedded@haerwu.biz>
+
+Linksys WCF11 submitted by Ã…ngström user.
+
+"The Linksys Group, Inc.", "Wireless Network CF Card", "ISL37300P", "RevA",
+0xa5f472c2, 0x9c05598d, 0xc9049a39, 0x57a66194 
+manfid: 0x0274, 0x3301
+
+Signed-off-by: Marcin Juszkiewicz <openembedded@haerwu.biz>
+Acked-by: Pavel Roskin <proski@gnu.org>
+
+---
+ drivers/net/wireless/hostap/hostap_cs.c |    3 +++
+ 1 file changed, 3 insertions(+)
+
+--- linux-2.6.23.orig/drivers/net/wireless/hostap/hostap_cs.c
++++ linux-2.6.23/drivers/net/wireless/hostap/hostap_cs.c
+@@ -887,10 +887,13 @@ static struct pcmcia_device_id hostap_cs
+               "Ver. 1.00",
+               0x5cd01705, 0x4271660f, 0x9d08ee12),
+       PCMCIA_DEVICE_PROD_ID123(
+               "corega", "WL PCCL-11", "ISL37300P",
+               0xa21501a, 0x59868926, 0xc9049a39),
++      PCMCIA_DEVICE_PROD_ID123(
++              "The Linksys Group, Inc.", "Wireless Network CF Card", "ISL37300P",
++              0xa5f472c2, 0x9c05598d, 0xc9049a39),
+       PCMCIA_DEVICE_NULL
+ };
+ MODULE_DEVICE_TABLE(pcmcia, hostap_cs_ids);
diff --git a/packages/kexecboot/linux-kexecboot-2.6.23/htcuni-acx.patch b/packages/kexecboot/linux-kexecboot-2.6.23/htcuni-acx.patch
new file mode 100644 (file)
index 0000000..769674c
--- /dev/null
@@ -0,0 +1,33526 @@
+---
+ drivers/net/wireless/Kconfig                |   31 
+ drivers/net/wireless/Makefile               |    2 
+ drivers/net/wireless/acx/Kconfig            |  113 
+ drivers/net/wireless/acx/Makefile           |   21 
+ drivers/net/wireless/acx/acx.h              |   14 
+ drivers/net/wireless/acx/acx_config.h       |   50 
+ drivers/net/wireless/acx/acx_func.h         |  710 ++
+ drivers/net/wireless/acx/acx_hw.h           |   18 
+ drivers/net/wireless/acx/acx_struct.h       | 2114 ++++++++
+ drivers/net/wireless/acx/common.c           | 7388 ++++++++++++++++++++++++++++
+ drivers/net/wireless/acx/conv.c             |  504 +
+ drivers/net/wireless/acx/cs.c               | 5703 +++++++++++++++++++++
+ drivers/net/wireless/acx/htcsable_acx.c     |  118 
+ drivers/net/wireless/acx/htcuniversal_acx.c |  108 
+ drivers/net/wireless/acx/hx4700_acx.c       |  108 
+ drivers/net/wireless/acx/ioctl.c            | 2748 ++++++++++
+ drivers/net/wireless/acx/mem.c              | 5363 ++++++++++++++++++++
+ drivers/net/wireless/acx/pci.c              | 4234 ++++++++++++++++
+ drivers/net/wireless/acx/rx3000_acx.c       |  110 
+ drivers/net/wireless/acx/setrate.c          |  213 
+ drivers/net/wireless/acx/usb.c              | 1922 +++++++
+ drivers/net/wireless/acx/wlan.c             |  424 +
+ drivers/net/wireless/acx/wlan_compat.h      |  260 
+ drivers/net/wireless/acx/wlan_hdr.h         |  497 +
+ drivers/net/wireless/acx/wlan_mgmt.h        |  582 ++
+ 25 files changed, 33355 insertions(+)
+
+Index: linux-2.6.22/drivers/net/wireless/acx/acx_config.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/drivers/net/wireless/acx/acx_config.h 2007-08-23 18:46:40.000000000 +0200
+@@ -0,0 +1,50 @@
++#define ACX_RELEASE "v0.3.36"
++
++/*
++ * Test out all the channels in reg domain 0x10
++ */
++#define ACX_ALLOW_ALLCHANNELS
++
++/* set to 0 if you don't want any debugging code to be compiled in */
++/* set to 1 if you want some debugging */
++/* set to 2 if you want extensive debug log */
++#define ACX_DEBUG 0
++
++/*
++ * Since we'll be changing channels a lot
++#define ACX_DEFAULT_MSG (L_ASSOC|L_INIT)
++*/
++#define ACX_DEFAULT_MSG (L_ASSOC|L_INIT)
++
++/* assume 32bit I/O width
++ * (16bit is also compatible with Compact Flash) */
++#define ACX_IO_WIDTH 32
++
++/* Set this to 1 if you want monitor mode to use
++ * phy header. Currently it is not useful anyway since we
++ * don't know what useful info (if any) is in phy header.
++ * If you want faster/smaller code, say 0 here */
++#define WANT_PHY_HDR 0
++
++/* whether to do Tx descriptor cleanup in softirq (i.e. not in IRQ
++ * handler) or not. Note that doing it later does slightly increase
++ * system load, so still do that stuff in the IRQ handler for now,
++ * even if that probably means worse latency */
++#define TX_CLEANUP_IN_SOFTIRQ 0
++
++/* if you want very experimental 802.11 power save mode features */
++#define POWER_SAVE_80211 0
++
++/* if you want very early packet fragmentation bits and pieces */
++#define ACX_FRAGMENTATION 0
++
++/* Locking: */
++/* very talkative */
++/* #define PARANOID_LOCKING 1 */
++/* normal (use when bug-free) */
++#define DO_LOCKING 1
++/* else locking is disabled! */
++
++/* 0 - normal mode */
++/* 1 - development/debug: probe for IEs on modprobe */
++#define CMD_DISCOVERY 0
+Index: linux-2.6.22/drivers/net/wireless/acx/acx_func.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/drivers/net/wireless/acx/acx_func.h   2007-08-23 18:34:19.000000000 +0200
+@@ -0,0 +1,710 @@
++/***********************************************************************
++** Copyright (C) 2003  ACX100 Open Source Project
++**
++** The contents of this file are subject to the Mozilla Public
++** License Version 1.1 (the "License"); you may not use this file
++** except in compliance with the License. You may obtain a copy of
++** the License at http://www.mozilla.org/MPL/
++**
++** Software distributed under the License is distributed on an "AS
++** IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
++** implied. See the License for the specific language governing
++** rights and limitations under the License.
++**
++** Alternatively, the contents of this file may be used under the
++** terms of the GNU Public License version 2 (the "GPL"), in which
++** case the provisions of the GPL are applicable instead of the
++** above.  If you wish to allow the use of your version of this file
++** only under the terms of the GPL and not to allow others to use
++** your version of this file under the MPL, indicate your decision
++** by deleting the provisions above and replace them with the notice
++** and other provisions required by the GPL.  If you do not delete
++** the provisions above, a recipient may use your version of this
++** file under either the MPL or the GPL.
++** ---------------------------------------------------------------------
++** Inquiries regarding the ACX100 Open Source Project can be
++** made directly to:
++**
++** acx100-users@lists.sf.net
++** http://acx100.sf.net
++** ---------------------------------------------------------------------
++*/
++
++
++/***********************************************************************
++** LOGGING
++**
++** - Avoid SHOUTING needlessly. Avoid excessive verbosity.
++**   Gradually remove messages which are old debugging aids.
++**
++** - Use printk() for messages which are to be always logged.
++**   Supply either 'acx:' or '<devname>:' prefix so that user
++**   can figure out who's speaking among other kernel chatter.
++**   acx: is for general issues (e.g. "acx: no firmware image!")
++**   while <devname>: is related to a particular device
++**   (think about multi-card setup). Double check that message
++**   is not confusing to the average user.
++**
++** - use printk KERN_xxx level only if message is not a WARNING
++**   but is INFO, ERR etc.
++**
++** - Use printk_ratelimited() for messages which may flood
++**   (e.g. "rx DUP pkt!").
++**
++** - Use log() for messages which may be omitted (and they
++**   _will_ be omitted in non-debug builds). Note that
++**   message levels may be disabled at compile-time selectively,
++**   thus select them wisely. Example: L_DEBUG is the lowest
++**   (most likely to be compiled out) -> use for less important stuff.
++**
++** - Do not print important stuff with log(), or else people
++**   will never build non-debug driver.
++**
++** Style:
++** hex: capital letters, zero filled (e.g. 0x02AC)
++** str: dont start from capitals, no trailing periods ("tx: queue is stopped")
++*/
++#if ACX_DEBUG > 1
++
++void log_fn_enter(const char *funcname);
++void log_fn_exit(const char *funcname);
++void log_fn_exit_v(const char *funcname, int v);
++
++#define FN_ENTER \
++      do { \
++              if (unlikely(acx_debug & L_FUNC)) { \
++                      log_fn_enter(__func__); \
++              } \
++      } while (0)
++
++#define FN_EXIT1(v) \
++      do { \
++              if (unlikely(acx_debug & L_FUNC)) { \
++                      log_fn_exit_v(__func__, v); \
++              } \
++      } while (0)
++#define FN_EXIT0 \
++      do { \
++              if (unlikely(acx_debug & L_FUNC)) { \
++                      log_fn_exit(__func__); \
++              } \
++      } while (0)
++
++#else
++
++#define FN_ENTER
++#define FN_EXIT1(v)
++#define FN_EXIT0
++
++#endif /* ACX_DEBUG > 1 */
++
++
++#if ACX_DEBUG
++
++#define log(chan, args...) \
++      do { \
++              if (acx_debug & (chan)) \
++                      printk(KERN_DEBUG args); \
++      } while (0)
++#define printk_ratelimited(args...) printk(args)
++
++#else /* Non-debug build: */
++
++#define log(chan, args...)
++/* Standard way of log flood prevention */
++#define printk_ratelimited(args...) \
++do { \
++      if (printk_ratelimit()) \
++              printk(args); \
++} while (0)
++
++#endif /* ACX_DEBUG */
++
++void acx_print_mac(const char *head, const u8 *mac, const char *tail);
++
++/* Optimized out to nothing in non-debug build */
++static inline void
++acxlog_mac(int level, const char *head, const u8 *mac, const char *tail)
++{
++      if (acx_debug & level) {
++              acx_print_mac(head, mac, tail);
++      }
++}
++
++
++/***********************************************************************
++** MAC address helpers
++*/
++static inline void
++MAC_COPY(u8 *mac, const u8 *src)
++{
++      *(u32*)mac = *(u32*)src;
++      ((u16*)mac)[2] = ((u16*)src)[2];
++      /* kernel's memcpy will do the same: memcpy(dst, src, ETH_ALEN); */
++}
++
++static inline void
++MAC_FILL(u8 *mac, u8 val)
++{
++      memset(mac, val, ETH_ALEN);
++}
++
++static inline void
++MAC_BCAST(u8 *mac)
++{
++      ((u16*)mac)[2] = *(u32*)mac = -1;
++}
++
++static inline void
++MAC_ZERO(u8 *mac)
++{
++      ((u16*)mac)[2] = *(u32*)mac = 0;
++}
++
++static inline int
++mac_is_equal(const u8 *a, const u8 *b)
++{
++      /* can't beat this */
++      return memcmp(a, b, ETH_ALEN) == 0;
++}
++
++static inline int
++mac_is_bcast(const u8 *mac)
++{
++      /* AND together 4 first bytes with sign-extended 2 last bytes
++      ** Only bcast address gives 0xffffffff. +1 gives 0 */
++      return ( *(s32*)mac & ((s16*)mac)[2] ) + 1 == 0;
++}
++
++static inline int
++mac_is_zero(const u8 *mac)
++{
++      return ( *(u32*)mac | ((u16*)mac)[2] ) == 0;
++}
++
++static inline int
++mac_is_directed(const u8 *mac)
++{
++      return (mac[0] & 1)==0;
++}
++
++static inline int
++mac_is_mcast(const u8 *mac)
++{
++      return (mac[0] & 1) && !mac_is_bcast(mac);
++}
++
++#define MACSTR "%02X:%02X:%02X:%02X:%02X:%02X"
++#define MAC(bytevector) \
++      ((unsigned char *)bytevector)[0], \
++      ((unsigned char *)bytevector)[1], \
++      ((unsigned char *)bytevector)[2], \
++      ((unsigned char *)bytevector)[3], \
++      ((unsigned char *)bytevector)[4], \
++      ((unsigned char *)bytevector)[5]
++
++
++/***********************************************************************
++** Random helpers
++*/
++#define TO_STRING(x)  #x
++#define STRING(x)     TO_STRING(x)
++
++#define CLEAR_BIT(val, mask) ((val) &= ~(mask))
++#define SET_BIT(val, mask) ((val) |= (mask))
++
++/* undefined if v==0 */
++static inline unsigned int
++lowest_bit(u16 v)
++{
++      unsigned int n = 0;
++      while (!(v & 0xf)) { v>>=4; n+=4; }
++      while (!(v & 1)) { v>>=1; n++; }
++      return n;
++}
++
++/* undefined if v==0 */
++static inline unsigned int
++highest_bit(u16 v)
++{
++      unsigned int n = 0;
++      while (v>0xf) { v>>=4; n+=4; }
++      while (v>1) { v>>=1; n++; }
++      return n;
++}
++
++/* undefined if v==0 */
++static inline int
++has_only_one_bit(u16 v)
++{
++      return ((v-1) ^ v) >= v;
++}
++
++
++static inline int
++is_hidden_essid(char *essid)
++{
++      return (('\0' == essid[0]) ||
++              ((' ' == essid[0]) && ('\0' == essid[1])));
++}
++
++/***********************************************************************
++** LOCKING
++** We have adev->sem and adev->lock.
++**
++** We employ following naming convention in order to get locking right:
++**
++** acx_e_xxxx - external entry points called from process context.
++**    It is okay to sleep. adev->sem is to be taken on entry.
++** acx_i_xxxx - external entry points possibly called from atomic context.
++**    Sleeping is not allowed (and thus down(sem) is not legal!)
++** acx_s_xxxx - potentially sleeping functions. Do not ever call under lock!
++** acx_l_xxxx - functions which expect lock to be already taken.
++** rest       - non-sleeping functions which do not require locking
++**            but may be run under lock
++**
++** A small number of local helpers do not have acx_[eisl]_ prefix.
++** They are always close to caller and are to be reviewed locally.
++**
++** Theory of operation:
++**
++** All process-context entry points (_e_ functions) take sem
++** immediately. IRQ handler and other 'atomic-context' entry points
++** (_i_ functions) take lock immediately on entry, but dont take sem
++** because that might sleep.
++**
++** Thus *all* code is either protected by sem or lock, or both.
++**
++** Code which must not run concurrently with IRQ takes lock.
++** Such code is marked with _l_.
++**
++** This results in the following rules of thumb useful in code review:
++**
++** + If a function calls _s_ fn, it must be an _s_ itself.
++** + You can call _l_ fn only (a) from another _l_ fn
++**   or (b) from _s_, _e_ or _i_ fn by taking lock, calling _l_,
++**   and dropping lock.
++** + All IRQ code runs under lock.
++** + Any _s_ fn is running under sem.
++** + Code under sem can race only with IRQ code.
++** + Code under sem+lock cannot race with anything.
++*/
++
++/* These functions *must* be inline or they will break horribly on SPARC, due
++ * to its weird semantics for save/restore flags */
++
++#if defined(PARANOID_LOCKING) /* Lock debugging */
++
++void acx_lock_debug(acx_device_t *adev, const char* where);
++void acx_unlock_debug(acx_device_t *adev, const char* where);
++void acx_down_debug(acx_device_t *adev, const char* where);
++void acx_up_debug(acx_device_t *adev, const char* where);
++void acx_lock_unhold(void);
++void acx_sem_unhold(void);
++
++static inline void
++acx_lock_helper(acx_device_t *adev, unsigned long *fp, const char* where)
++{
++      acx_lock_debug(adev, where);
++      spin_lock_irqsave(&adev->lock, *fp);
++}
++static inline void
++acx_unlock_helper(acx_device_t *adev, unsigned long *fp, const char* where)
++{
++      acx_unlock_debug(adev, where);
++      spin_unlock_irqrestore(&adev->lock, *fp);
++}
++static inline void
++acx_down_helper(acx_device_t *adev, const char* where)
++{
++      acx_down_debug(adev, where);
++}
++static inline void
++acx_up_helper(acx_device_t *adev, const char* where)
++{
++      acx_up_debug(adev, where);
++}
++#define acx_lock(adev, flags) acx_lock_helper(adev, &(flags), __FILE__ ":" STRING(__LINE__))
++#define acx_unlock(adev, flags)       acx_unlock_helper(adev, &(flags), __FILE__ ":" STRING(__LINE__))
++#define acx_sem_lock(adev)    acx_down_helper(adev, __FILE__ ":" STRING(__LINE__))
++#define acx_sem_unlock(adev)  acx_up_helper(adev, __FILE__ ":" STRING(__LINE__))
++
++#elif defined(DO_LOCKING)
++
++#define acx_lock(adev, flags) spin_lock_irqsave(&adev->lock, flags)
++#define acx_unlock(adev, flags)       spin_unlock_irqrestore(&adev->lock, flags)
++#define acx_sem_lock(adev)    down(&adev->sem)
++#define acx_sem_unlock(adev)  up(&adev->sem)
++#define acx_lock_unhold()     ((void)0)
++#define acx_sem_unhold()      ((void)0)
++
++#else /* no locking! :( */
++
++#define acx_lock(adev, flags) ((void)0)
++#define acx_unlock(adev, flags)       ((void)0)
++#define acx_sem_lock(adev)    ((void)0)
++#define acx_sem_unlock(adev)  ((void)0)
++#define acx_lock_unhold()     ((void)0)
++#define acx_sem_unhold()      ((void)0)
++
++#endif
++
++
++/***********************************************************************
++*/
++
++/* Can race with rx path (which is not protected by sem):
++** rx -> process_[re]assocresp() -> set_status(ASSOCIATED) -> wake_queue()
++** Can race with tx_complete IRQ:
++** IRQ -> acxpci_l_clean_txdesc -> acx_wake_queue
++** Review carefully all callsites */
++static inline void
++acx_stop_queue(struct net_device *ndev, const char *msg)
++{
++      if (netif_queue_stopped(ndev))
++              return;
++
++      netif_stop_queue(ndev);
++      if (msg)
++              log(L_BUFT, "tx: stop queue %s\n", msg);
++}
++
++static inline int
++acx_queue_stopped(struct net_device *ndev)
++{
++      return netif_queue_stopped(ndev);
++}
++
++/*
++static inline void
++acx_start_queue(struct net_device *ndev, const char *msg)
++{
++      netif_start_queue(ndev);
++      if (msg)
++              log(L_BUFT, "tx: start queue %s\n", msg);
++}
++*/
++
++static inline void
++acx_wake_queue(struct net_device *ndev, const char *msg)
++{
++      netif_wake_queue(ndev);
++      if (msg)
++              log(L_BUFT, "tx: wake queue %s\n", msg);
++}
++
++static inline void
++acx_carrier_off(struct net_device *ndev, const char *msg)
++{
++      netif_carrier_off(ndev);
++      if (msg)
++              log(L_BUFT, "tx: carrier off %s\n", msg);
++}
++
++static inline void
++acx_carrier_on(struct net_device *ndev, const char *msg)
++{
++      netif_carrier_on(ndev);
++      if (msg)
++              log(L_BUFT, "tx: carrier on %s\n", msg);
++}
++
++/* This function does not need locking UNLESS you call it
++** as acx_set_status(ACX_STATUS_4_ASSOCIATED), bacause this can
++** wake queue. This can race with stop_queue elsewhere. */
++void acx_set_status(acx_device_t *adev, u16 status);
++
++
++/***********************************************************************
++** Communication with firmware
++*/
++#define CMD_TIMEOUT_MS(n)     (n)
++#define ACX_CMD_TIMEOUT_DEFAULT       CMD_TIMEOUT_MS(50)
++
++#if ACX_DEBUG
++
++/* We want to log cmd names */
++int acxpci_s_issue_cmd_timeo_debug(acx_device_t *adev, unsigned cmd, void *param, unsigned len, unsigned timeout, const char* cmdstr);
++int acxmem_s_issue_cmd_timeo_debug(acx_device_t *adev, unsigned cmd, void *param, unsigned len, unsigned timeout, const char* cmdstr);
++int acxusb_s_issue_cmd_timeo_debug(acx_device_t *adev, unsigned cmd, void *param, unsigned len, unsigned timeout, const char* cmdstr);
++static inline int
++acx_s_issue_cmd_timeo_debug(acx_device_t *adev, unsigned cmd, void *param, unsigned len, unsigned timeout, const char* cmdstr)
++{
++        if (IS_MEM(adev))
++                return acxmem_s_issue_cmd_timeo_debug(adev, cmd, param, len, timeout, cmdstr);
++      if (IS_PCI(adev))
++              return acxpci_s_issue_cmd_timeo_debug(adev, cmd, param, len, timeout, cmdstr);
++      return acxusb_s_issue_cmd_timeo_debug(adev, cmd, param, len, timeout, cmdstr);
++}
++#define acx_s_issue_cmd(adev,cmd,param,len) \
++      acx_s_issue_cmd_timeo_debug(adev,cmd,param,len,ACX_CMD_TIMEOUT_DEFAULT,#cmd)
++#define acx_s_issue_cmd_timeo(adev,cmd,param,len,timeo) \
++      acx_s_issue_cmd_timeo_debug(adev,cmd,param,len,timeo,#cmd)
++int acx_s_configure_debug(acx_device_t *adev, void *pdr, int type, const char* str);
++#define acx_s_configure(adev,pdr,type) \
++      acx_s_configure_debug(adev,pdr,type,#type)
++int acx_s_interrogate_debug(acx_device_t *adev, void *pdr, int type, const char* str);
++#define acx_s_interrogate(adev,pdr,type) \
++      acx_s_interrogate_debug(adev,pdr,type,#type)
++
++#else
++
++int acxpci_s_issue_cmd_timeo(acx_device_t *adev, unsigned cmd, void *param, unsigned len, unsigned timeout);
++int acxmem_s_issue_cmd_timeo(acx_device_t *adev, unsigned cmd, void *param, unsigned len, unsigned timeout);
++int acxusb_s_issue_cmd_timeo(acx_device_t *adev, unsigned cmd, void *param, unsigned len, unsigned timeout);
++static inline int
++acx_s_issue_cmd_timeo(acx_device_t *adev, unsigned cmd,       void *param, unsigned len, unsigned timeout)
++{
++      if (IS_MEM(adev))
++              return acxmem_s_issue_cmd_timeo(adev, cmd, param, len, timeout);
++      if (IS_PCI(adev))
++              return acxpci_s_issue_cmd_timeo(adev, cmd, param, len, timeout);
++      return acxusb_s_issue_cmd_timeo(adev, cmd, param, len, timeout);
++}
++static inline int
++acx_s_issue_cmd(acx_device_t *adev, unsigned cmd, void *param, unsigned len)
++{
++      if (IS_MEM(adev))
++              return acxmem_s_issue_cmd_timeo(adev, cmd, param, len, ACX_CMD_TIMEOUT_DEFAULT);
++      if (IS_PCI(adev))
++              return acxpci_s_issue_cmd_timeo(adev, cmd, param, len, ACX_CMD_TIMEOUT_DEFAULT);
++      return acxusb_s_issue_cmd_timeo(adev, cmd, param, len, ACX_CMD_TIMEOUT_DEFAULT);
++}
++int acx_s_configure(acx_device_t *adev, void *pdr, int type);
++int acx_s_interrogate(acx_device_t *adev, void *pdr, int type);
++
++#endif
++
++void acx_s_cmd_start_scan(acx_device_t *adev);
++
++
++/***********************************************************************
++** Ioctls
++*/
++int
++acx111pci_ioctl_info(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      struct iw_param *vwrq,
++      char *extra);
++int
++acx100pci_ioctl_set_phy_amp_bias(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      struct iw_param *vwrq,
++      char *extra);
++int
++acx100mem_ioctl_set_phy_amp_bias(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      struct iw_param *vwrq,
++      char *extra);
++
++
++/***********************************************************************
++** /proc
++*/
++#ifdef CONFIG_PROC_FS
++int acx_proc_register_entries(const struct net_device *ndev);
++int acx_proc_unregister_entries(const struct net_device *ndev);
++#else
++static inline int
++acx_proc_register_entries(const struct net_device *ndev) { return OK; }
++static inline int
++acx_proc_unregister_entries(const struct net_device *ndev) { return OK; }
++#endif
++
++
++/***********************************************************************
++*/
++firmware_image_t *acx_s_read_fw(struct device *dev, const char *file, u32 *size);
++int acxpci_s_upload_radio(acx_device_t *adev);
++int acxmem_s_upload_radio(acx_device_t *adev);
++
++
++/***********************************************************************
++** Unsorted yet :)
++*/
++int acxpci_s_read_phy_reg(acx_device_t *adev, u32 reg, u8 *charbuf);
++int acxmem_s_read_phy_reg(acx_device_t *adev, u32 reg, u8 *charbuf);
++int acxusb_s_read_phy_reg(acx_device_t *adev, u32 reg, u8 *charbuf);
++static inline int
++acx_s_read_phy_reg(acx_device_t *adev, u32 reg, u8 *charbuf)
++{
++      if (IS_MEM(adev))
++              return acxmem_s_read_phy_reg(adev, reg, charbuf);
++      if (IS_PCI(adev))
++              return acxpci_s_read_phy_reg(adev, reg, charbuf);
++      return acxusb_s_read_phy_reg(adev, reg, charbuf);
++}
++
++int acxpci_s_write_phy_reg(acx_device_t *adev, u32 reg, u8 value);
++int acxmem_s_write_phy_reg(acx_device_t *adev, u32 reg, u8 value);
++int acxusb_s_write_phy_reg(acx_device_t *adev, u32 reg, u8 value);
++static inline int
++acx_s_write_phy_reg(acx_device_t *adev, u32 reg, u8 value)
++{
++      if (IS_MEM(adev))
++              return acxmem_s_write_phy_reg(adev, reg, value);
++      if (IS_PCI(adev))
++              return acxpci_s_write_phy_reg(adev, reg, value);
++      return acxusb_s_write_phy_reg(adev, reg, value);
++}
++
++tx_t* acxpci_l_alloc_tx(acx_device_t *adev);
++tx_t* acxmem_l_alloc_tx(acx_device_t *adev);
++tx_t* acxusb_l_alloc_tx(acx_device_t *adev);
++static inline tx_t*
++acx_l_alloc_tx(acx_device_t *adev)
++{
++      if (IS_MEM(adev))
++              return acxmem_l_alloc_tx(adev);
++      if (IS_PCI(adev))
++              return acxpci_l_alloc_tx(adev);
++      return acxusb_l_alloc_tx(adev);
++}
++
++void acxusb_l_dealloc_tx(tx_t *tx_opaque);
++void acxmem_l_dealloc_tx(acx_device_t *adev, tx_t *tx_opaque);
++static inline void
++acx_l_dealloc_tx(acx_device_t *adev, tx_t *tx_opaque)
++{
++#ifdef ACX_MEM
++  acxmem_l_dealloc_tx (adev, tx_opaque);
++#else
++      if (IS_USB(adev))
++              acxusb_l_dealloc_tx(tx_opaque);
++#endif
++}
++
++void* acxpci_l_get_txbuf(acx_device_t *adev, tx_t *tx_opaque);
++void* acxmem_l_get_txbuf(acx_device_t *adev, tx_t *tx_opaque);
++void* acxusb_l_get_txbuf(acx_device_t *adev, tx_t *tx_opaque);
++static inline void*
++acx_l_get_txbuf(acx_device_t *adev, tx_t *tx_opaque)
++{
++#if defined (ACX_MEM)
++              return acxmem_l_get_txbuf(adev, tx_opaque);
++#else
++      if (IS_PCI(adev))
++              return acxpci_l_get_txbuf(adev, tx_opaque);
++      return acxusb_l_get_txbuf(adev, tx_opaque);
++#endif
++}
++
++void acxpci_l_tx_data(acx_device_t *adev, tx_t *tx_opaque, int len);
++void acxmem_l_tx_data(acx_device_t *adev, tx_t *tx_opaque, int len);
++void acxusb_l_tx_data(acx_device_t *adev, tx_t *tx_opaque, int len);
++static inline void
++acx_l_tx_data(acx_device_t *adev, tx_t *tx_opaque, int len)
++{
++#if defined (ACX_MEM)
++              acxmem_l_tx_data(adev, tx_opaque, len);
++#else
++      if (IS_PCI(adev))
++              acxpci_l_tx_data(adev, tx_opaque, len);
++      else
++              acxusb_l_tx_data(adev, tx_opaque, len);
++#endif
++}
++
++static inline wlan_hdr_t*
++acx_get_wlan_hdr(acx_device_t *adev, const rxbuffer_t *rxbuf)
++{
++      return (wlan_hdr_t*)((u8*)&rxbuf->hdr_a3 + adev->phy_header_len);
++}
++
++void acxpci_l_power_led(acx_device_t *adev, int enable);
++int acxpci_read_eeprom_byte(acx_device_t *adev, u32 addr, u8 *charbuf);
++unsigned int acxpci_l_clean_txdesc(acx_device_t *adev);
++void acxpci_l_clean_txdesc_emergency(acx_device_t *adev);
++int acxpci_s_create_hostdesc_queues(acx_device_t *adev);
++void acxpci_create_desc_queues(acx_device_t *adev, u32 tx_queue_start, u32 rx_queue_start);
++void acxpci_free_desc_queues(acx_device_t *adev);
++char* acxpci_s_proc_diag_output(char *p, acx_device_t *adev);
++int acxpci_proc_eeprom_output(char *p, acx_device_t *adev);
++void acxpci_set_interrupt_mask(acx_device_t *adev);
++int acx100pci_s_set_tx_level(acx_device_t *adev, u8 level_dbm);
++
++void acxmem_l_power_led(acx_device_t *adev, int enable);
++int acxmem_read_eeprom_byte(acx_device_t *adev, u32 addr, u8 *charbuf);
++unsigned int acxmem_l_clean_txdesc(acx_device_t *adev);
++void acxmem_l_clean_txdesc_emergency(acx_device_t *adev);
++int acxmem_s_create_hostdesc_queues(acx_device_t *adev);
++void acxmem_create_desc_queues(acx_device_t *adev, u32 tx_queue_start, u32 rx_queue_start);
++void acxmem_free_desc_queues(acx_device_t *adev);
++char* acxmem_s_proc_diag_output(char *p, acx_device_t *adev);
++int acxmem_proc_eeprom_output(char *p, acx_device_t *adev);
++void acxmem_set_interrupt_mask(acx_device_t *adev);
++int acx100mem_s_set_tx_level(acx_device_t *adev, u8 level_dbm);
++
++void acx_s_msleep(int ms);
++int acx_s_init_mac(acx_device_t *adev);
++void acx_set_reg_domain(acx_device_t *adev, unsigned char reg_dom_id);
++void acx_set_timer(acx_device_t *adev, int timeout_us);
++void acx_update_capabilities(acx_device_t *adev);
++void acx_s_start(acx_device_t *adev);
++
++void acx_s_update_card_settings(acx_device_t *adev);
++void acx_s_parse_configoption(acx_device_t *adev, const acx111_ie_configoption_t *pcfg);
++void acx_l_update_ratevector(acx_device_t *adev);
++
++void acx_init_task_scheduler(acx_device_t *adev);
++void acx_schedule_task(acx_device_t *adev, unsigned int set_flag);
++
++int acx_e_ioctl_old(struct net_device *ndev, struct ifreq *ifr, int cmd);
++
++client_t *acx_l_sta_list_get(acx_device_t *adev, const u8 *address);
++void acx_l_sta_list_del(acx_device_t *adev, client_t *clt);
++
++int acx_l_transmit_disassoc(acx_device_t *adev, client_t *clt);
++void acx_i_timer(unsigned long a);
++int acx_s_complete_scan(acx_device_t *adev);
++
++struct sk_buff *acx_rxbuf_to_ether(acx_device_t *adev, rxbuffer_t *rxbuf);
++int acx_ether_to_txbuf(acx_device_t *adev, void *txbuf, const struct sk_buff *skb);
++
++u8 acx_signal_determine_quality(u8 signal, u8 noise);
++
++void acx_l_process_rxbuf(acx_device_t *adev, rxbuffer_t *rxbuf);
++void acx_l_handle_txrate_auto(acx_device_t *adev, struct client *txc,
++                      u16 intended_rate, u8 rate100, u16 rate111, u8 error,
++                      int pkts_to_ignore);
++
++void acx_dump_bytes(const void *, int);
++void acx_log_bad_eid(wlan_hdr_t* hdr, int len, wlan_ie_t* ie_ptr);
++
++u8 acx_rate111to100(u16);
++
++void acx_s_set_defaults(acx_device_t *adev);
++
++#if !ACX_DEBUG
++static inline const char* acx_get_packet_type_string(u16 fc) { return ""; }
++#else
++const char* acx_get_packet_type_string(u16 fc);
++#endif
++const char* acx_cmd_status_str(unsigned int state);
++
++int acx_i_start_xmit(struct sk_buff *skb, struct net_device *ndev);
++
++void great_inquisitor(acx_device_t *adev);
++
++void acx_s_get_firmware_version(acx_device_t *adev);
++void acx_display_hardware_details(acx_device_t *adev);
++
++int acx_e_change_mtu(struct net_device *ndev, int mtu);
++struct net_device_stats* acx_e_get_stats(struct net_device *ndev);
++struct iw_statistics* acx_e_get_wireless_stats(struct net_device *ndev);
++
++#ifdef ACX_MEM
++int __init acxmem_e_init_module(void);
++void __exit acxmem_e_cleanup_module(void);
++void acxmem_e_release(struct device *dev);
++#else
++int __init acxpci_e_init_module(void);
++int __init acxusb_e_init_module(void);
++void __exit acxpci_e_cleanup_module(void);
++void __exit acxusb_e_cleanup_module(void);
++#endif
++int __init acx_cs_init(void);
++void __exit acx_cs_cleanup(void);
+Index: linux-2.6.22/drivers/net/wireless/acx/acx.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/drivers/net/wireless/acx/acx.h        2007-08-23 18:34:19.000000000 +0200
+@@ -0,0 +1,14 @@
++#if defined(CONFIG_ACX_MEM) && !defined(ACX_MEM)
++#define ACX_MEM
++#endif
++
++#if defined(CONFIG_ACX_CS) && !defined(ACX_MEM)
++#define ACX_MEM
++#endif
++
++#include "acx_config.h"
++#include "wlan_compat.h"
++#include "wlan_hdr.h"
++#include "wlan_mgmt.h"
++#include "acx_struct.h"
++#include "acx_func.h"
+Index: linux-2.6.22/drivers/net/wireless/acx/acx_hw.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/drivers/net/wireless/acx/acx_hw.h     2007-08-23 18:34:19.000000000 +0200
+@@ -0,0 +1,18 @@
++/*
++ * Interface for ACX slave memory driver
++ *
++ * Copyright (c) 2006 SDG Systems, LLC
++ *
++ * GPL
++ *
++ */
++
++#ifndef _ACX_HW_H
++#define _ACX_HW_H
++
++struct acx_hardware_data {
++      int (*start_hw)( void );
++      int (*stop_hw)( void );
++};
++
++#endif /* _ACX_HW_H */
+Index: linux-2.6.22/drivers/net/wireless/acx/acx_struct.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/drivers/net/wireless/acx/acx_struct.h 2007-08-23 18:34:19.000000000 +0200
+@@ -0,0 +1,2114 @@
++/***********************************************************************
++** Copyright (C) 2003  ACX100 Open Source Project
++**
++** The contents of this file are subject to the Mozilla Public
++** License Version 1.1 (the "License"); you may not use this file
++** except in compliance with the License. You may obtain a copy of
++** the License at http://www.mozilla.org/MPL/
++**
++** Software distributed under the License is distributed on an "AS
++** IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
++** implied. See the License for the specific language governing
++** rights and limitations under the License.
++**
++** Alternatively, the contents of this file may be used under the
++** terms of the GNU Public License version 2 (the "GPL"), in which
++** case the provisions of the GPL are applicable instead of the
++** above.  If you wish to allow the use of your version of this file
++** only under the terms of the GPL and not to allow others to use
++** your version of this file under the MPL, indicate your decision
++** by deleting the provisions above and replace them with the notice
++** and other provisions required by the GPL.  If you do not delete
++** the provisions above, a recipient may use your version of this
++** file under either the MPL or the GPL.
++** ---------------------------------------------------------------------
++** Inquiries regarding the ACX100 Open Source Project can be
++** made directly to:
++**
++** acx100-users@lists.sf.net
++** http://acx100.sf.net
++** ---------------------------------------------------------------------
++*/
++
++/***********************************************************************
++** Forward declarations of types
++*/
++typedef struct tx tx_t;
++typedef struct acx_device acx_device_t;
++typedef struct client client_t;
++typedef struct rxdesc rxdesc_t;
++typedef struct txdesc txdesc_t;
++typedef struct rxhostdesc rxhostdesc_t;
++typedef struct txhostdesc txhostdesc_t;
++
++
++/***********************************************************************
++** Debug / log functionality
++*/
++enum {
++      L_LOCK          = (ACX_DEBUG>1)*0x0001, /* locking debug log */
++      L_INIT          = (ACX_DEBUG>0)*0x0002, /* special card initialization logging */
++      L_IRQ           = (ACX_DEBUG>0)*0x0004, /* interrupt stuff */
++      L_ASSOC         = (ACX_DEBUG>0)*0x0008, /* assocation (network join) and station log */
++      L_FUNC          = (ACX_DEBUG>1)*0x0020, /* logging of function enter / leave */
++      L_XFER          = (ACX_DEBUG>1)*0x0080, /* logging of transfers and mgmt */
++      L_DATA          = (ACX_DEBUG>1)*0x0100, /* logging of transfer data */
++      L_DEBUG         = (ACX_DEBUG>1)*0x0200, /* log of debug info */
++      L_IOCTL         = (ACX_DEBUG>0)*0x0400, /* log ioctl calls */
++      L_CTL           = (ACX_DEBUG>1)*0x0800, /* log of low-level ctl commands */
++      L_BUFR          = (ACX_DEBUG>1)*0x1000, /* debug rx buffer mgmt (ring buffer etc.) */
++      L_XFER_BEACON   = (ACX_DEBUG>1)*0x2000, /* also log beacon packets */
++      L_BUFT          = (ACX_DEBUG>1)*0x4000, /* debug tx buffer mgmt (ring buffer etc.) */
++      L_USBRXTX       = (ACX_DEBUG>0)*0x8000, /* debug USB rx/tx operations */
++      L_BUF           = L_BUFR + L_BUFT,
++      L_ANY           = 0xffff
++};
++
++#if ACX_DEBUG
++extern unsigned int acx_debug;
++#else
++enum { acx_debug = 0 };
++#endif
++
++
++/***********************************************************************
++** Random helpers
++*/
++#define ACX_PACKED __attribute__ ((packed))
++
++#define VEC_SIZE(a) (sizeof(a)/sizeof(a[0]))
++
++/* Use worker_queues for 2.5/2.6 kernels and queue tasks for 2.4 kernels
++   (used for the 'bottom half' of the interrupt routine) */
++
++#include <linux/workqueue.h>
++#define USE_WORKER_TASKS
++#define WORK_STRUCT struct work_struct
++#define SCHEDULE_WORK schedule_work
++#define FLUSH_SCHEDULED_WORK flush_scheduled_work
++
++
++/***********************************************************************
++** Constants
++*/
++#define OK    0
++#define NOT_OK        1
++
++/* The supported chip models */
++#define CHIPTYPE_ACX100               1
++#define CHIPTYPE_ACX111               2
++
++#define IS_ACX100(adev)       ((adev)->chip_type == CHIPTYPE_ACX100)
++#define IS_ACX111(adev)       ((adev)->chip_type == CHIPTYPE_ACX111)
++
++/* Supported interfaces */
++#define DEVTYPE_PCI           0
++#define DEVTYPE_USB           1
++#define DEVTYPE_MEM             2
++
++#if !defined(CONFIG_ACX_PCI) && !defined(CONFIG_ACX_USB) && !defined(CONFIG_ACX_MEM) && !defined(CONFIG_ACX_CS)
++#error Driver must include PCI, USB, PCMCIA or memory mapped interface support. You selected none of them.
++#endif
++
++#if defined(CONFIG_ACX_PCI)
++ #if !defined(CONFIG_ACX_USB)
++  #define IS_PCI(adev)        1
++ #else
++  #define IS_PCI(adev)        ((adev)->dev_type == DEVTYPE_PCI)
++ #endif
++#else
++ #define IS_PCI(adev) 0
++#endif
++
++#if defined(CONFIG_ACX_USB)
++ #if !defined(CONFIG_ACX_PCI)
++  #define IS_USB(adev)        1
++ #else
++  #define IS_USB(adev)        ((adev)->dev_type == DEVTYPE_USB)
++ #endif
++#else
++ #define IS_USB(adev) 0
++#endif
++
++#if defined(CONFIG_ACX_MEM) || defined(CONFIG_ACX_CS)
++ #define IS_MEM(adev)  1
++#else
++ #define IS_MEM(adev)   0
++#endif
++
++/* Driver defaults */
++#define DEFAULT_DTIM_INTERVAL 10
++/* used to be 2048, but FreeBSD driver changed it to 4096 to work properly
++** in noisy wlans */
++#define DEFAULT_MSDU_LIFETIME 4096
++#define DEFAULT_RTS_THRESHOLD 2312    /* max. size: disable RTS mechanism */
++#define DEFAULT_BEACON_INTERVAL       100
++
++#define ACX100_BAP_DATALEN_MAX                4096
++#define ACX100_RID_GUESSING_MAXLEN    2048    /* I'm not really sure */
++#define ACX100_RIDDATA_MAXLEN         ACX100_RID_GUESSING_MAXLEN
++
++/* Support Constants */
++/* Radio type names, found in Win98 driver's TIACXLN.INF */
++#define RADIO_MAXIM_0D                0x0d
++#define RADIO_RFMD_11         0x11
++#define RADIO_RALINK_15               0x15
++/* used in ACX111 cards (WG311v2, WL-121, ...): */
++#define RADIO_RADIA_16                0x16
++/* most likely *sometimes* used in ACX111 cards: */
++#define RADIO_UNKNOWN_17      0x17
++/* FwRad19.bin was found in a Safecom driver; must be an ACX111 radio: */
++#define RADIO_UNKNOWN_19      0x19
++#define RADIO_UNKNOWN_1B      0x1b    /* radio in SafeCom SWLUT-54125 USB adapter; entirely unknown!! */
++
++/* Controller Commands */
++/* can be found in table cmdTable in firmware "Rev. 1.5.0" (FW150) */
++#define ACX1xx_CMD_RESET              0x00
++#define ACX1xx_CMD_INTERROGATE                0x01
++#define ACX1xx_CMD_CONFIGURE          0x02
++#define ACX1xx_CMD_ENABLE_RX          0x03
++#define ACX1xx_CMD_ENABLE_TX          0x04
++#define ACX1xx_CMD_DISABLE_RX         0x05
++#define ACX1xx_CMD_DISABLE_TX         0x06
++#define ACX1xx_CMD_FLUSH_QUEUE                0x07
++#define ACX1xx_CMD_SCAN                       0x08
++#define ACX1xx_CMD_STOP_SCAN          0x09
++#define ACX1xx_CMD_CONFIG_TIM         0x0a
++#define ACX1xx_CMD_JOIN                       0x0b
++#define ACX1xx_CMD_WEP_MGMT           0x0c
++#ifdef OLD_FIRMWARE_VERSIONS
++#define ACX100_CMD_HALT                       0x0e    /* mapped to unknownCMD in FW150 */
++#else
++#define ACX1xx_CMD_MEM_READ           0x0d
++#define ACX1xx_CMD_MEM_WRITE          0x0e
++#endif
++#define ACX1xx_CMD_SLEEP              0x0f
++#define ACX1xx_CMD_WAKE                       0x10
++#define ACX1xx_CMD_UNKNOWN_11         0x11    /* mapped to unknownCMD in FW150 */
++#define ACX100_CMD_INIT_MEMORY                0x12
++#define ACX1FF_CMD_DISABLE_RADIO      0x12    /* new firmware? TNETW1450? */
++#define ACX1xx_CMD_CONFIG_BEACON      0x13
++#define ACX1xx_CMD_CONFIG_PROBE_RESPONSE      0x14
++#define ACX1xx_CMD_CONFIG_NULL_DATA   0x15
++#define ACX1xx_CMD_CONFIG_PROBE_REQUEST       0x16
++#define ACX1xx_CMD_FCC_TEST           0x17
++#define ACX1xx_CMD_RADIOINIT          0x18
++#define ACX111_CMD_RADIOCALIB         0x19
++#define ACX1FF_CMD_NOISE_HISTOGRAM    0x1c /* new firmware? TNETW1450? */
++#define ACX1FF_CMD_RX_RESET           0x1d /* new firmware? TNETW1450? */
++#define ACX1FF_CMD_LNA_CONTROL                0x20 /* new firmware? TNETW1450? */
++#define ACX1FF_CMD_CONTROL_DBG_TRACE  0x21 /* new firmware? TNETW1450? */
++
++/* 'After Interrupt' Commands */
++#define ACX_AFTER_IRQ_CMD_STOP_SCAN   0x01
++#define ACX_AFTER_IRQ_CMD_ASSOCIATE   0x02
++#define ACX_AFTER_IRQ_CMD_RADIO_RECALIB       0x04
++#define ACX_AFTER_IRQ_UPDATE_CARD_CFG 0x08
++#define ACX_AFTER_IRQ_TX_CLEANUP      0x10
++#define ACX_AFTER_IRQ_COMPLETE_SCAN   0x20
++#define ACX_AFTER_IRQ_RESTART_SCAN    0x40
++
++/***********************************************************************
++** Tx/Rx buffer sizes and watermarks
++**
++** This will alloc and use DMAable buffers of
++** WLAN_A4FR_MAXLEN_WEP_FCS * (RX_CNT + TX_CNT) bytes
++** RX/TX_CNT=32 -> ~150k DMA buffers
++** RX/TX_CNT=16 -> ~75k DMA buffers
++**
++** 2005-10-10: reduced memory usage by lowering both to 16
++*/
++#define RX_CNT 16
++#define TX_CNT 16
++
++/* we clean up txdescs when we have N free txdesc: */
++#define TX_CLEAN_BACKLOG (TX_CNT/4)
++#define TX_START_CLEAN (TX_CNT - TX_CLEAN_BACKLOG)
++#define TX_EMERG_CLEAN 2
++/* we stop queue if we have < N free txbufs: */
++#define TX_STOP_QUEUE 3
++/* we start queue if we have >= N free txbufs: */
++#define TX_START_QUEUE 5
++
++/***********************************************************************
++** Interrogate/Configure cmd constants
++**
++** NB: length includes JUST the data part of the IE
++** (does not include size of the (type,len) pair)
++**
++** TODO: seems that acx100, acx100usb, acx111 have some differences,
++** fix code with regard to this!
++*/
++
++#define DEF_IE(name, val, len) enum { ACX##name=val, ACX##name##_LEN=len }
++
++/* Information Elements: Network Parameters, Static Configuration Entities */
++/* these are handled by real_cfgtable in firmware "Rev 1.5.0" (FW150) */
++DEF_IE(1xx_IE_UNKNOWN_00              ,0x0000, -1);   /* mapped to cfgInvalid in FW150 */
++DEF_IE(100_IE_ACX_TIMER                       ,0x0001, 0x10);
++DEF_IE(1xx_IE_POWER_MGMT              ,0x0002, 0x06); /* TNETW1450: length 0x18!! */
++DEF_IE(1xx_IE_QUEUE_CONFIG            ,0x0003, 0x1c);
++DEF_IE(100_IE_BLOCK_SIZE              ,0x0004, 0x02);
++DEF_IE(1FF_IE_SLOT_TIME                       ,0x0004, 0x08); /* later firmware versions only? */
++DEF_IE(1xx_IE_MEMORY_CONFIG_OPTIONS   ,0x0005, 0x14);
++DEF_IE(1FF_IE_QUEUE_HEAD              ,0x0005, 0x14 /* FIXME: length? */);
++DEF_IE(1xx_IE_RATE_FALLBACK           ,0x0006, 0x01); /* TNETW1450: length 2 */
++DEF_IE(100_IE_WEP_OPTIONS             ,0x0007, 0x03);
++DEF_IE(111_IE_RADIO_BAND              ,0x0007, -1);
++DEF_IE(1FF_IE_TIMING_CFG              ,0x0007, -1);   /* later firmware versions; TNETW1450 only? */
++DEF_IE(100_IE_SSID                    ,0x0008, 0x20); /* huh? */
++DEF_IE(1xx_IE_MEMORY_MAP              ,0x0008, 0x28); /* huh? TNETW1450 has length 0x40!! */
++DEF_IE(1xx_IE_SCAN_STATUS             ,0x0009, 0x04); /* mapped to cfgInvalid in FW150 */
++DEF_IE(1xx_IE_ASSOC_ID                        ,0x000a, 0x02);
++DEF_IE(1xx_IE_UNKNOWN_0B              ,0x000b, -1);   /* mapped to cfgInvalid in FW150 */
++DEF_IE(1FF_IE_TX_POWER_LEVEL_TABLE    ,0x000b, 0x18); /* later firmware versions; TNETW1450 only? */
++DEF_IE(100_IE_UNKNOWN_0C              ,0x000c, -1);   /* very small implementation in FW150! */
++/* ACX100 has an equivalent struct in the cmd mailbox directly after reset.
++ * 0x14c seems extremely large, will trash stack on failure (memset!)
++ * in case of small input struct --> OOPS! */
++DEF_IE(111_IE_CONFIG_OPTIONS          ,0x000c, 0x14c);
++DEF_IE(1xx_IE_FWREV                   ,0x000d, 0x18);
++DEF_IE(1xx_IE_FCS_ERROR_COUNT         ,0x000e, 0x04);
++DEF_IE(1xx_IE_MEDIUM_USAGE            ,0x000f, 0x08);
++DEF_IE(1xx_IE_RXCONFIG                        ,0x0010, 0x04);
++DEF_IE(100_IE_UNKNOWN_11              ,0x0011, -1);   /* NONBINARY: large implementation in FW150! link quality readings or so? */
++DEF_IE(111_IE_QUEUE_THRESH            ,0x0011, -1);
++DEF_IE(100_IE_UNKNOWN_12              ,0x0012, -1);   /* NONBINARY: VERY large implementation in FW150!! */
++DEF_IE(111_IE_BSS_POWER_SAVE          ,0x0012, /* -1 */ 2);
++DEF_IE(1xx_IE_FIRMWARE_STATISTICS     ,0x0013, 0x9c); /* TNETW1450: length 0x134!! */
++DEF_IE(1FF_IE_RX_INTR_CONFIG          ,0x0014, 0x14); /* later firmware versions, TNETW1450 only? */
++DEF_IE(1xx_IE_FEATURE_CONFIG          ,0x0015, 0x08);
++DEF_IE(111_IE_KEY_CHOOSE              ,0x0016, 0x04); /* for rekeying. really len=4?? */
++DEF_IE(1FF_IE_MISC_CONFIG_TABLE               ,0x0017, 0x04); /* later firmware versions, TNETW1450 only? */
++DEF_IE(1FF_IE_WONE_CONFIG             ,0x0018, -1);   /* later firmware versions, TNETW1450 only? */
++DEF_IE(1FF_IE_TID_CONFIG              ,0x001a, 0x2c); /* later firmware versions, TNETW1450 only? */
++DEF_IE(1FF_IE_CALIB_ASSESSMENT                ,0x001e, 0x04); /* later firmware versions, TNETW1450 only? */
++DEF_IE(1FF_IE_BEACON_FILTER_OPTIONS   ,0x001f, 0x02); /* later firmware versions, TNETW1450 only? */
++DEF_IE(1FF_IE_LOW_RSSI_THRESH_OPT     ,0x0020, 0x04); /* later firmware versions, TNETW1450 only? */
++DEF_IE(1FF_IE_NOISE_HISTOGRAM_RESULTS ,0x0021, 0x30); /* later firmware versions, TNETW1450 only? */
++DEF_IE(1FF_IE_PACKET_DETECT_THRESH    ,0x0023, 0x04); /* later firmware versions, TNETW1450 only? */
++DEF_IE(1FF_IE_TX_CONFIG_OPTIONS               ,0x0024, 0x04); /* later firmware versions, TNETW1450 only? */
++DEF_IE(1FF_IE_CCA_THRESHOLD           ,0x0025, 0x02); /* later firmware versions, TNETW1450 only? */
++DEF_IE(1FF_IE_EVENT_MASK              ,0x0026, 0x08); /* later firmware versions, TNETW1450 only? */
++DEF_IE(1FF_IE_DTIM_PERIOD             ,0x0027, 0x02); /* later firmware versions, TNETW1450 only? */
++DEF_IE(1FF_IE_ACI_CONFIG_SET          ,0x0029, 0x06); /* later firmware versions; maybe TNETW1450 only? */
++DEF_IE(1FF_IE_EEPROM_VER              ,0x0030, 0x04); /* later firmware versions; maybe TNETW1450 only? */
++DEF_IE(1xx_IE_DOT11_STATION_ID                ,0x1001, 0x06);
++DEF_IE(100_IE_DOT11_UNKNOWN_1002      ,0x1002, -1);   /* mapped to cfgInvalid in FW150 */
++DEF_IE(111_IE_DOT11_FRAG_THRESH               ,0x1002, -1);   /* mapped to cfgInvalid in FW150; TNETW1450 has length 2!! */
++DEF_IE(100_IE_DOT11_BEACON_PERIOD     ,0x1003, 0x02); /* mapped to cfgInvalid in FW150 */
++DEF_IE(1xx_IE_DOT11_DTIM_PERIOD               ,0x1004, -1);   /* mapped to cfgInvalid in FW150 */
++DEF_IE(1FF_IE_DOT11_MAX_RX_LIFETIME   ,0x1004, -1);   /* later firmware versions; maybe TNETW1450 only? */
++DEF_IE(1xx_IE_DOT11_SHORT_RETRY_LIMIT ,0x1005, 0x01); /* TNETW1450: length 2 */
++DEF_IE(1xx_IE_DOT11_LONG_RETRY_LIMIT  ,0x1006, 0x01); /* TNETW1450: length 2 */
++DEF_IE(100_IE_DOT11_WEP_DEFAULT_KEY_WRITE     ,0x1007, 0x20); /* configure default keys; TNETW1450 has length 0x24!! */
++DEF_IE(1xx_IE_DOT11_MAX_XMIT_MSDU_LIFETIME    ,0x1008, 0x04);
++DEF_IE(1xx_IE_DOT11_GROUP_ADDR                ,0x1009, -1);
++DEF_IE(1xx_IE_DOT11_CURRENT_REG_DOMAIN        ,0x100a, 0x02);
++/* It's harmless to have larger struct. Use USB case always. */
++DEF_IE(1xx_IE_DOT11_CURRENT_ANTENNA   ,0x100b, 0x02); /* in fact len=1 for PCI */
++DEF_IE(1xx_IE_DOT11_UNKNOWN_100C      ,0x100c, -1);   /* mapped to cfgInvalid in FW150 */
++DEF_IE(1xx_IE_DOT11_TX_POWER_LEVEL    ,0x100d, 0x01); /* TNETW1450 has length 2!! */
++DEF_IE(1xx_IE_DOT11_CURRENT_CCA_MODE  ,0x100e, 0x02); /* in fact len=1 for PCI */
++/* USB doesn't return anything - len==0?! */
++DEF_IE(100_IE_DOT11_ED_THRESHOLD      ,0x100f, 0x04);
++DEF_IE(1xx_IE_DOT11_WEP_DEFAULT_KEY_SET       ,0x1010, 0x01); /* set default key ID; TNETW1450: length 2 */
++DEF_IE(100_IE_DOT11_UNKNOWN_1011      ,0x1011, -1);   /* mapped to cfgInvalid in FW150 */
++DEF_IE(1FF_IE_DOT11_CURR_5GHZ_REGDOM  ,0x1011, -1);   /* later firmware versions; maybe TNETW1450 only? */
++DEF_IE(100_IE_DOT11_UNKNOWN_1012      ,0x1012, -1);   /* mapped to cfgInvalid in FW150 */
++DEF_IE(100_IE_DOT11_UNKNOWN_1013      ,0x1013, -1);   /* mapped to cfgInvalid in FW150 */
++
++#if 0
++/* Experimentally obtained on acx100, fw 1.9.8.b
++** -1 means that fw returned 'invalid IE'
++** 0200 FC00 nnnn... are test read contents: u16 type, u16 len, data
++** (AA are poison bytes marking bytes not written by fw)
++**
++** Looks like acx100 fw does not update len field (thus len=256-4=FC here)
++** A number of IEs seem to trash type,len fields
++** IEs marked 'huge' return gobs of data (no poison bytes remain)
++*/
++DEF_IE(100_IE_INVAL_00,                       0x0000, -1);
++DEF_IE(100_IE_INVAL_01,                       0x0001, -1);    /* IE_ACX_TIMER, len=16 on older fw */
++DEF_IE(100_IE_POWER_MGMT,             0x0002, 4);     /* 0200FC00 00040000 AAAAAAAA */
++DEF_IE(100_IE_QUEUE_CONFIG,           0x0003, 28);    /* 0300FC00 48060000 9CAD0000 0101AAAA DCB00000 E4B00000 9CAA0000 00AAAAAA */
++DEF_IE(100_IE_BLOCK_SIZE,             0x0004, 2);     /* 0400FC00 0001AAAA AAAAAAAA AAAAAAAA */
++/* write only: */
++DEF_IE(100_IE_MEMORY_CONFIG_OPTIONS,  0x0005, 20);
++DEF_IE(100_IE_RATE_FALLBACK,          0x0006, 1);     /* 0600FC00 00AAAAAA AAAAAAAA AAAAAAAA */
++/* write only: */
++DEF_IE(100_IE_WEP_OPTIONS,            0x0007, 3);
++DEF_IE(100_IE_MEMORY_MAP,             0x0008, 40);    /* huge: 0800FC00 30000000 6CA20000 70A20000... */
++/* gives INVAL on read: */
++DEF_IE(100_IE_SCAN_STATUS,            0x0009, -1);
++DEF_IE(100_IE_ASSOC_ID,                       0x000a, 2);     /* huge: 0A00FC00 00000000 01040800 00000000... */
++DEF_IE(100_IE_INVAL_0B,                       0x000b, -1);
++/* 'command rejected': */
++DEF_IE(100_IE_CONFIG_OPTIONS,         0x000c, -3);
++DEF_IE(100_IE_FWREV,                  0x000d, 24);    /* 0D00FC00 52657620 312E392E 382E6200 AAAAAAAA AAAAAAAA 05050201 AAAAAAAA */
++DEF_IE(100_IE_FCS_ERROR_COUNT,                0x000e, 4);
++DEF_IE(100_IE_MEDIUM_USAGE,           0x000f, 8);     /* E41F0000 2D780300 FCC91300 AAAAAAAA */
++DEF_IE(100_IE_RXCONFIG,                       0x0010, 4);     /* 1000FC00 00280000 AAAAAAAA AAAAAAAA */
++DEF_IE(100_IE_QUEUE_THRESH,           0x0011, 12);    /* 1100FC00 AAAAAAAA 00000000 00000000 */
++DEF_IE(100_IE_BSS_POWER_SAVE,         0x0012, 1);     /* 1200FC00 00AAAAAA AAAAAAAA AAAAAAAA */
++/* read only, variable len */
++DEF_IE(100_IE_FIRMWARE_STATISTICS,    0x0013, 256); /* 0000AC00 00000000 ... */
++DEF_IE(100_IE_INT_CONFIG,             0x0014, 20);    /* 00000000 00000000 00000000 00000000 5D74D105 00000000 AAAAAAAA AAAAAAAA */
++DEF_IE(100_IE_FEATURE_CONFIG,         0x0015, 8);     /* 1500FC00 16000000 AAAAAAAA AAAAAAAA */
++/* returns 'invalid MAC': */
++DEF_IE(100_IE_KEY_CHOOSE,             0x0016, -4);
++DEF_IE(100_IE_INVAL_17,                       0x0017, -1);
++DEF_IE(100_IE_UNKNOWN_18,             0x0018, 0);     /* null len?! 1800FC00 AAAAAAAA AAAAAAAA AAAAAAAA */
++DEF_IE(100_IE_UNKNOWN_19,             0x0019, 256);   /* huge: 1900FC00 9C1F00EA FEFFFFEA FEFFFFEA... */
++DEF_IE(100_IE_INVAL_1A,                       0x001A, -1);
++
++DEF_IE(100_IE_DOT11_INVAL_1000,                       0x1000, -1);
++DEF_IE(100_IE_DOT11_STATION_ID,                       0x1001, 6);     /* huge: 0110FC00 58B10E2F 03000000 00000000... */
++DEF_IE(100_IE_DOT11_INVAL_1002,                       0x1002, -1);
++DEF_IE(100_IE_DOT11_INVAL_1003,                       0x1003, -1);
++DEF_IE(100_IE_DOT11_INVAL_1004,                       0x1004, -1);
++DEF_IE(100_IE_DOT11_SHORT_RETRY_LIMIT,                0x1005, 1);
++DEF_IE(100_IE_DOT11_LONG_RETRY_LIMIT,         0x1006, 1);
++/* write only: */
++DEF_IE(100_IE_DOT11_WEP_DEFAULT_KEY_WRITE,    0x1007, 32);
++DEF_IE(100_IE_DOT11_MAX_XMIT_MSDU_LIFETIME,   0x1008, 4);     /* huge: 0810FC00 00020000 F4010000 00000000... */
++/* undoc but returns something */
++DEF_IE(100_IE_DOT11_GROUP_ADDR,                       0x1009, 12);    /* huge: 0910FC00 00000000 00000000 00000000... */
++DEF_IE(100_IE_DOT11_CURRENT_REG_DOMAIN,               0x100a, 1);     /* 0A10FC00 30AAAAAA AAAAAAAA AAAAAAAA */
++DEF_IE(100_IE_DOT11_CURRENT_ANTENNA,          0x100b, 1);     /* 0B10FC00 8FAAAAAA AAAAAAAA AAAAAAAA */
++DEF_IE(100_IE_DOT11_INVAL_100C,                       0x100c, -1);
++DEF_IE(100_IE_DOT11_TX_POWER_LEVEL,           0x100d, 2);     /* 00000000 0100AAAA AAAAAAAA AAAAAAAA */
++DEF_IE(100_IE_DOT11_CURRENT_CCA_MODE,         0x100e, 1);     /* 0E10FC00 0DAAAAAA AAAAAAAA AAAAAAAA */
++DEF_IE(100_IE_DOT11_ED_THRESHOLD,             0x100f, 4);     /* 0F10FC00 70000000 AAAAAAAA AAAAAAAA */
++/* set default key ID  */
++DEF_IE(100_IE_DOT11_WEP_DEFAULT_KEY_SET,      0x1010, 1);     /* 1010FC00 00AAAAAA AAAAAAAA AAAAAAAA */
++DEF_IE(100_IE_DOT11_INVAL_1011,                       0x1011, -1);
++DEF_IE(100_IE_DOT11_INVAL_1012,                       0x1012, -1);
++DEF_IE(100_IE_DOT11_INVAL_1013,                       0x1013, -1);
++DEF_IE(100_IE_DOT11_UNKNOWN_1014,             0x1014, 256);   /* huge */
++DEF_IE(100_IE_DOT11_UNKNOWN_1015,             0x1015, 256);   /* huge */
++DEF_IE(100_IE_DOT11_UNKNOWN_1016,             0x1016, 256);   /* huge */
++DEF_IE(100_IE_DOT11_UNKNOWN_1017,             0x1017, 256);   /* huge */
++DEF_IE(100_IE_DOT11_UNKNOWN_1018,             0x1018, 256);   /* huge */
++DEF_IE(100_IE_DOT11_UNKNOWN_1019,             0x1019, 256);   /* huge */
++#endif
++
++#if 0
++/* Experimentally obtained on PCI acx111 Xterasys XN-2522g, fw 1.2.1.34
++** -1 means that fw returned 'invalid IE'
++** 0400 0800 nnnn... are test read contents: u16 type, u16 len, data
++** (AA are poison bytes marking bytes not written by fw)
++**
++** Looks like acx111 fw reports real len!
++*/
++DEF_IE(111_IE_INVAL_00,                       0x0000, -1);
++DEF_IE(111_IE_INVAL_01,                       0x0001, -1);
++DEF_IE(111_IE_POWER_MGMT,             0x0002, 12);
++/* write only, variable len: 12 + rxqueue_cnt*8 + txqueue_cnt*4: */
++DEF_IE(111_IE_MEMORY_CONFIG,          0x0003, 24);
++DEF_IE(111_IE_BLOCK_SIZE,             0x0004, 8); /* 04000800 AA00AAAA AAAAAAAA */
++/* variable len: 8 + rxqueue_cnt*8 + txqueue_cnt*8: */
++DEF_IE(111_IE_QUEUE_HEAD,             0x0005, 24);
++DEF_IE(111_IE_RATE_FALLBACK,          0x0006, 1);
++/* acx100 name:WEP_OPTIONS */
++/* said to have len:1 (not true, actually returns 12 bytes): */
++DEF_IE(111_IE_RADIO_BAND,             0x0007, 12); /* 07000C00 AAAA1F00 FF03AAAA AAAAAAAA */
++DEF_IE(111_IE_MEMORY_MAP,             0x0008, 48);
++/* said to have len:4, but gives INVAL on read: */
++DEF_IE(111_IE_SCAN_STATUS,            0x0009, -1);
++DEF_IE(111_IE_ASSOC_ID,                       0x000a, 2);
++/* write only, len is not known: */
++DEF_IE(111_IE_UNKNOWN_0B,             0x000b, 0);
++/* read only, variable len. I see 67 byte reads: */
++DEF_IE(111_IE_CONFIG_OPTIONS,         0x000c, 67); /* 0C004300 01160500 ... */
++DEF_IE(111_IE_FWREV,                  0x000d, 24);
++DEF_IE(111_IE_FCS_ERROR_COUNT,                0x000e, 4);
++DEF_IE(111_IE_MEDIUM_USAGE,           0x000f, 8);
++DEF_IE(111_IE_RXCONFIG,                       0x0010, 4);
++DEF_IE(111_IE_QUEUE_THRESH,           0x0011, 12);
++DEF_IE(111_IE_BSS_POWER_SAVE,         0x0012, 1);
++/* read only, variable len. I see 240 byte reads: */
++DEF_IE(111_IE_FIRMWARE_STATISTICS,    0x0013, 240); /* 1300F000 00000000 ... */
++/* said to have len=17. looks like fw pads it to 20: */
++DEF_IE(111_IE_INT_CONFIG,             0x0014, 20); /* 14001400 00000000 00000000 00000000 00000000 00000000 */
++DEF_IE(111_IE_FEATURE_CONFIG,         0x0015, 8);
++/* said to be name:KEY_INDICATOR, len:4, but gives INVAL on read: */
++DEF_IE(111_IE_KEY_CHOOSE,             0x0016, -1);
++/* said to have len:4, but in fact returns 8: */
++DEF_IE(111_IE_MAX_USB_XFR,            0x0017, 8); /* 17000800 00014000 00000000 */
++DEF_IE(111_IE_INVAL_18,                       0x0018, -1);
++DEF_IE(111_IE_INVAL_19,                       0x0019, -1);
++/* undoc but returns something: */
++/* huh, fw indicates len=20 but uses 4 more bytes in buffer??? */
++DEF_IE(111_IE_UNKNOWN_1A,             0x001A, 20); /* 1A001400 AA00AAAA 0000020F FF030000 00020000 00000007 04000000 */
++
++DEF_IE(111_IE_DOT11_INVAL_1000,                       0x1000, -1);
++DEF_IE(111_IE_DOT11_STATION_ID,                       0x1001, 6);
++DEF_IE(111_IE_DOT11_FRAG_THRESH,              0x1002, 2);
++/* acx100 only? gives INVAL on read: */
++DEF_IE(111_IE_DOT11_BEACON_PERIOD,            0x1003, -1);
++/* said to be MAX_RECV_MSDU_LIFETIME: */
++DEF_IE(111_IE_DOT11_DTIM_PERIOD,              0x1004, 4);
++DEF_IE(111_IE_DOT11_SHORT_RETRY_LIMIT,                0x1005, 1);
++DEF_IE(111_IE_DOT11_LONG_RETRY_LIMIT,         0x1006, 1);
++/* acx100 only? gives INVAL on read: */
++DEF_IE(111_IE_DOT11_WEP_DEFAULT_KEY_WRITE,    0x1007, -1);
++DEF_IE(111_IE_DOT11_MAX_XMIT_MSDU_LIFETIME,   0x1008, 4);
++/* undoc but returns something. maybe it's 2 multicast MACs to listen to? */
++DEF_IE(111_IE_DOT11_GROUP_ADDR,                       0x1009, 12); /* 09100C00 00000000 00000000 00000000 */
++DEF_IE(111_IE_DOT11_CURRENT_REG_DOMAIN,               0x100a, 1);
++DEF_IE(111_IE_DOT11_CURRENT_ANTENNA,          0x100b, 2);
++DEF_IE(111_IE_DOT11_INVAL_100C,                       0x100c, -1);
++DEF_IE(111_IE_DOT11_TX_POWER_LEVEL,           0x100d, 1);
++/* said to have len=1 but gives INVAL on read: */
++DEF_IE(111_IE_DOT11_CURRENT_CCA_MODE,         0x100e, -1);
++/* said to have len=4 but gives INVAL on read: */
++DEF_IE(111_IE_DOT11_ED_THRESHOLD,             0x100f, -1);
++/* set default key ID. write only: */
++DEF_IE(111_IE_DOT11_WEP_DEFAULT_KEY_SET,      0x1010, 1);
++/* undoc but returns something: */
++DEF_IE(111_IE_DOT11_UNKNOWN_1011,             0x1011, 1); /* 11100100 20 */
++DEF_IE(111_IE_DOT11_INVAL_1012,                       0x1012, -1);
++DEF_IE(111_IE_DOT11_INVAL_1013,                       0x1013, -1);
++#endif
++
++
++/***********************************************************************
++**Information Frames Structures
++*/
++
++/* Used in beacon frames and the like */
++#define DOT11RATEBYTE_1               (1*2)
++#define DOT11RATEBYTE_2               (2*2)
++#define DOT11RATEBYTE_5_5     (5*2+1)
++#define DOT11RATEBYTE_11      (11*2)
++#define DOT11RATEBYTE_22      (22*2)
++#define DOT11RATEBYTE_6_G     (6*2)
++#define DOT11RATEBYTE_9_G     (9*2)
++#define DOT11RATEBYTE_12_G    (12*2)
++#define DOT11RATEBYTE_18_G    (18*2)
++#define DOT11RATEBYTE_24_G    (24*2)
++#define DOT11RATEBYTE_36_G    (36*2)
++#define DOT11RATEBYTE_48_G    (48*2)
++#define DOT11RATEBYTE_54_G    (54*2)
++#define DOT11RATEBYTE_BASIC   0x80    /* flags rates included in basic rate set */
++
++
++/***********************************************************************
++** rxbuffer_t
++**
++** This is the format of rx data returned by acx
++*/
++
++/* I've hoped it's a 802.11 PHY header, but no...
++ * so far, I've seen on acx111:
++ * 0000 3a00 0000 0000 IBSS Beacons
++ * 0000 3c00 0000 0000 ESS Beacons
++ * 0000 2700 0000 0000 Probe requests
++ * --vda
++ */
++typedef struct phy_hdr {
++      u8      unknown[4];
++      u8      acx111_unknown[4];
++} ACX_PACKED phy_hdr_t;
++
++/* seems to be a bit similar to hfa384x_rx_frame.
++ * These fields are still not quite obvious, though.
++ * Some seem to have different meanings... */
++
++#define RXBUF_HDRSIZE 12
++#define RXBUF_BYTES_RCVD(adev, rxbuf) \
++              ((le16_to_cpu((rxbuf)->mac_cnt_rcvd) & 0xfff) - (adev)->phy_header_len)
++#define RXBUF_BYTES_USED(rxbuf) \
++              ((le16_to_cpu((rxbuf)->mac_cnt_rcvd) & 0xfff) + RXBUF_HDRSIZE)
++/* USBism */
++#define RXBUF_IS_TXSTAT(rxbuf) (le16_to_cpu((rxbuf)->mac_cnt_rcvd) & 0x8000)
++/*
++mac_cnt_rcvd:
++    12 bits: length of frame from control field to first byte of FCS
++    3 bits: reserved
++    1 bit: 1 = it's a tx status info, not a rx packet (USB only)
++
++mac_cnt_mblks:
++    6 bits: number of memory block used to store frame in adapter memory
++    1 bit: Traffic Indicator bit in TIM of received Beacon was set
++
++mac_status: 1 byte (bitmap):
++    7 Matching BSSID
++    6 Matching SSID
++    5 BDCST   Address 1 field is a broadcast
++    4 VBM     received beacon frame has more than one set bit (?!)
++    3 TIM Set bit representing this station is set in TIM of received beacon
++    2 GROUP   Address 1 is a multicast
++    1 ADDR1   Address 1 matches our MAC
++    0 FCSGD   FSC is good
++
++phy_stat_baseband: 1 byte (bitmap):
++    7 Preamble                frame had a long preamble
++    6 PLCP Error      CRC16 error in PLCP header
++    5 Unsup_Mod               unsupported modulation
++    4 Selected Antenna        antenna 1 was used to receive this frame
++    3 PBCC/CCK                frame used: 1=PBCC, 0=CCK modulation
++    2 OFDM            frame used OFDM modulation
++    1 TI Protection   protection frame was detected
++    0 Reserved
++
++phy_plcp_signal: 1 byte:
++    Receive PLCP Signal field from the Baseband Processor
++
++phy_level: 1 byte:
++    receive AGC gain level (can be used to measure receive signal strength)
++
++phy_snr: 1 byte:
++    estimated noise power of equalized receive signal
++    at input of FEC decoder (can be used to measure receive signal quality)
++
++time: 4 bytes:
++    timestamp sampled from either the Access Manager TSF counter
++    or free-running microsecond counter when the MAC receives
++    first byte of PLCP header.
++*/
++
++typedef struct rxbuffer {
++      u16     mac_cnt_rcvd;           /* only 12 bits are len! (0xfff) */
++      u8      mac_cnt_mblks;
++      u8      mac_status;
++      u8      phy_stat_baseband;      /* bit 0x80: used LNA (Low-Noise Amplifier) */
++      u8      phy_plcp_signal;
++      u8      phy_level;              /* PHY stat */
++      u8      phy_snr;                /* PHY stat */
++      u32     time;                   /* timestamp upon MAC rcv first byte */
++/* 4-byte (acx100) or 8-byte (acx111) phy header will be here
++** if RX_CFG1_INCLUDE_PHY_HDR is in effect:
++**    phy_hdr_t phy                   */
++      wlan_hdr_a3_t hdr_a3;
++      /* maximally sized data part of wlan packet */
++      u8      data_a3[WLAN_A4FR_MAXLEN_WEP_FCS - WLAN_HDR_A3_LEN];
++      /* can add hdr/data_a4 if needed */
++} ACX_PACKED rxbuffer_t;
++
++
++/*--- Firmware statistics ----------------------------------------------------*/
++
++/* define a random 100 bytes more to catch firmware versions which
++ * provide a bigger struct */
++#define FW_STATS_FUTURE_EXTENSION     100
++
++typedef struct fw_stats_tx {
++      u32     tx_desc_of;
++} ACX_PACKED fw_stats_tx_t;
++
++typedef struct fw_stats_rx {
++      u32     rx_oom;
++      u32     rx_hdr_of;
++      u32     rx_hw_stuck; /* old: u32        rx_hdr_use_next */
++      u32     rx_dropped_frame;
++      u32     rx_frame_ptr_err;
++      u32     rx_xfr_hint_trig;
++      u32     rx_aci_events; /* later versions only */
++      u32     rx_aci_resets; /* later versions only */
++} ACX_PACKED fw_stats_rx_t;
++
++typedef struct fw_stats_dma {
++      u32     rx_dma_req;
++      u32     rx_dma_err;
++      u32     tx_dma_req;
++      u32     tx_dma_err;
++} ACX_PACKED fw_stats_dma_t;
++
++typedef struct fw_stats_irq {
++      u32     cmd_cplt;
++      u32     fiq;
++      u32     rx_hdrs;
++      u32     rx_cmplt;
++      u32     rx_mem_of;
++      u32     rx_rdys;
++      u32     irqs;
++      u32     tx_procs;
++      u32     decrypt_done;
++      u32     dma_0_done;
++      u32     dma_1_done;
++      u32     tx_exch_complet;
++      u32     commands;
++      u32     rx_procs;
++      u32     hw_pm_mode_changes;
++      u32     host_acks;
++      u32     pci_pm;
++      u32     acm_wakeups;
++} ACX_PACKED fw_stats_irq_t;
++
++typedef struct fw_stats_wep {
++      u32     wep_key_count;
++      u32     wep_default_key_count;
++      u32     dot11_def_key_mib;
++      u32     wep_key_not_found;
++      u32     wep_decrypt_fail;
++      u32     wep_pkt_decrypt;
++      u32     wep_decrypt_irqs;
++} ACX_PACKED fw_stats_wep_t;
++
++typedef struct fw_stats_pwr {
++      u32     tx_start_ctr;
++      u32     no_ps_tx_too_short;
++      u32     rx_start_ctr;
++      u32     no_ps_rx_too_short;
++      u32     lppd_started;
++      u32     no_lppd_too_noisy;
++      u32     no_lppd_too_short;
++      u32     no_lppd_matching_frame;
++} ACX_PACKED fw_stats_pwr_t;
++
++typedef struct fw_stats_mic {
++      u32 mic_rx_pkts;
++      u32 mic_calc_fail;
++} ACX_PACKED fw_stats_mic_t;
++
++typedef struct fw_stats_aes {
++      u32 aes_enc_fail;
++      u32 aes_dec_fail;
++      u32 aes_enc_pkts;
++      u32 aes_dec_pkts;
++      u32 aes_enc_irq;
++      u32 aes_dec_irq;
++} ACX_PACKED fw_stats_aes_t;
++
++typedef struct fw_stats_event {
++      u32 heartbeat;
++      u32 calibration;
++      u32 rx_mismatch;
++      u32 rx_mem_empty;
++      u32 rx_pool;
++      u32 oom_late;
++      u32 phy_tx_err;
++      u32 tx_stuck;
++} ACX_PACKED fw_stats_event_t;
++
++/* mainly for size calculation only */
++typedef struct fw_stats {
++      u16                     type;
++      u16                     len;
++      fw_stats_tx_t           tx;
++      fw_stats_rx_t           rx;
++      fw_stats_dma_t          dma;
++      fw_stats_irq_t          irq;
++      fw_stats_wep_t          wep;
++      fw_stats_pwr_t          pwr;
++      fw_stats_mic_t          mic;
++      fw_stats_aes_t          aes;
++      fw_stats_event_t        evt;
++      u8                      _padding[FW_STATS_FUTURE_EXTENSION];
++} fw_stats_t;
++
++/* Firmware version struct */
++
++typedef struct fw_ver {
++      u16     cmd;
++      u16     size;
++      char    fw_id[20];
++      u32     hw_id;
++} ACX_PACKED fw_ver_t;
++
++#define FW_ID_SIZE 20
++
++typedef struct shared_queueindicator {
++        u32     indicator;
++        u16     host_lock;
++        u16     fw_lock;
++} ACX_PACKED queueindicator_t;
++
++/*--- WEP stuff --------------------------------------------------------------*/
++#define DOT11_MAX_DEFAULT_WEP_KEYS    4
++
++/* non-firmware struct, no packing necessary */
++typedef struct wep_key {
++      size_t  size; /* most often used member first */
++      u8      index;
++      u8      key[29];
++      u16     strange_filler;
++} wep_key_t;                  /* size = 264 bytes (33*8) */
++/* FIXME: We don't have size 264! Or is there 2 bytes beyond the key
++ * (strange_filler)? */
++
++/* non-firmware struct, no packing necessary */
++typedef struct key_struct {
++      u8      addr[ETH_ALEN]; /* 0x00 */
++      u16     filler1;        /* 0x06 */
++      u32     filler2;        /* 0x08 */
++      u32     index;          /* 0x0c */
++      u16     len;            /* 0x10 */
++      u8      key[29];        /* 0x12; is this long enough??? */
++} key_struct_t;                       /* size = 276. FIXME: where is the remaining space?? */
++
++
++/*--- Client (peer) info -----------------------------------------------------*/
++/* adev->sta_list[] is used for:
++** accumulating and processing of scan results
++** keeping client info in AP mode
++** keeping AP info in STA mode (AP is the only one 'client')
++** keeping peer info in ad-hoc mode
++** non-firmware struct --> no packing necessary */
++enum {
++      CLIENT_EMPTY_SLOT_0 = 0,
++      CLIENT_EXIST_1 = 1,
++      CLIENT_AUTHENTICATED_2 = 2,
++      CLIENT_ASSOCIATED_3 = 3,
++      CLIENT_JOIN_CANDIDATE = 4
++};
++struct client {
++      /* most frequent access first */
++      u8      used;                   /* misnamed, more like 'status' */
++      struct client*  next;
++      unsigned long   mtime;          /* last time we heard it, in jiffies */
++      size_t  essid_len;              /* length of ESSID (without '\0') */
++      u32     sir;                    /* Standard IR */
++      u32     snr;                    /* Signal to Noise Ratio */
++      u16     aid;                    /* association ID */
++      u16     seq;                    /* from client's auth req */
++      u16     auth_alg;               /* from client's auth req */
++      u16     cap_info;               /* from client's assoc req */
++      u16     rate_cap;               /* what client supports (all rates) */
++      u16     rate_bas;               /* what client supports (basic rates) */
++      u16     rate_cfg;               /* what is allowed (by iwconfig etc) */
++      u16     rate_cur;               /* currently used rate mask */
++      u8      rate_100;               /* currently used rate byte (acx100 only) */
++      u8      address[ETH_ALEN];
++      u8      bssid[ETH_ALEN];        /* ad-hoc hosts can have bssid != mac */
++      u8      channel;
++      u8      auth_step;
++      u8      ignore_count;
++      u8      fallback_count;
++      u8      stepup_count;
++      char    essid[IW_ESSID_MAX_SIZE + 1];   /* ESSID and trailing '\0'  */
++/* FIXME: this one is too damn big */
++      char    challenge_text[WLAN_CHALLENGE_LEN];
++};
++
++
++/***********************************************************************
++** Hardware structures
++*/
++
++/* An opaque typesafe helper type
++ *
++ * Some hardware fields are actually pointers,
++ * but they have to remain u32, since using ptr instead
++ * (8 bytes on 64bit systems!) would disrupt the fixed descriptor
++ * format the acx firmware expects in the non-user area.
++ * Since we cannot cram an 8 byte ptr into 4 bytes, we need to
++ * enforce that pointed to data remains in low memory
++ * (address value needs to fit in 4 bytes) on 64bit systems.
++ *
++ * This is easy to get wrong, thus we are using a small struct
++ * and special macros to access it. Macros will check for
++ * attempts to overflow an acx_ptr with value > 0xffffffff.
++ *
++ * Attempts to use acx_ptr without macros result in compile-time errors */
++
++typedef struct {
++      u32     v;
++} ACX_PACKED acx_ptr;
++
++#if ACX_DEBUG
++#define CHECK32(n) BUG_ON(sizeof(n)>4 && (long)(n)>0xffffff00)
++#else
++#define CHECK32(n) ((void)0)
++#endif
++
++/* acx_ptr <-> integer conversion */
++#define cpu2acx(n) ({ CHECK32(n); ((acx_ptr){ .v = cpu_to_le32(n) }); })
++#define acx2cpu(a) (le32_to_cpu(a.v))
++
++/* acx_ptr <-> pointer conversion */
++#define ptr2acx(p) ({ CHECK32(p); ((acx_ptr){ .v = cpu_to_le32((u32)(long)(p)) }); })
++#define acx2ptr(a) ((void*)le32_to_cpu(a.v))
++
++/* Values for rate field (acx100 only) */
++#define RATE100_1             10
++#define RATE100_2             20
++#define RATE100_5             55
++#define RATE100_11            110
++#define RATE100_22            220
++/* This bit denotes use of PBCC:
++** (PBCC encoding is usable with 11 and 22 Mbps speeds only) */
++#define RATE100_PBCC511               0x80
++
++/* Bit values for rate111 field */
++#define RATE111_1             0x0001  /* DBPSK */
++#define RATE111_2             0x0002  /* DQPSK */
++#define RATE111_5             0x0004  /* CCK or PBCC */
++#define RATE111_6             0x0008  /* CCK-OFDM or OFDM */
++#define RATE111_9             0x0010  /* CCK-OFDM or OFDM */
++#define RATE111_11            0x0020  /* CCK or PBCC */
++#define RATE111_12            0x0040  /* CCK-OFDM or OFDM */
++#define RATE111_18            0x0080  /* CCK-OFDM or OFDM */
++#define RATE111_22            0x0100  /* PBCC */
++#define RATE111_24            0x0200  /* CCK-OFDM or OFDM */
++#define RATE111_36            0x0400  /* CCK-OFDM or OFDM */
++#define RATE111_48            0x0800  /* CCK-OFDM or OFDM */
++#define RATE111_54            0x1000  /* CCK-OFDM or OFDM */
++#define RATE111_RESERVED      0x2000
++#define RATE111_PBCC511               0x4000  /* PBCC mod at 5.5 or 11Mbit (else CCK) */
++#define RATE111_SHORTPRE      0x8000  /* short preamble */
++/* Special 'try everything' value */
++#define RATE111_ALL           0x1fff
++/* These bits denote acx100 compatible settings */
++#define RATE111_ACX100_COMPAT 0x0127
++/* These bits denote 802.11b compatible settings */
++#define RATE111_80211B_COMPAT 0x0027
++
++/* Descriptor Ctl field bits
++ * init value is 0x8e, "idle" value is 0x82 (in idle tx descs)
++ */
++#define DESC_CTL_SHORT_PREAMBLE       0x01    /* preamble type: 0 = long; 1 = short */
++#define DESC_CTL_FIRSTFRAG    0x02    /* this is the 1st frag of the frame */
++#define DESC_CTL_AUTODMA      0x04
++#define DESC_CTL_RECLAIM      0x08    /* ready to reuse */
++#define DESC_CTL_HOSTDONE     0x20    /* host has finished processing */
++#define DESC_CTL_ACXDONE      0x40    /* acx has finished processing */
++/* host owns the desc [has to be released last, AFTER modifying all other desc fields!] */
++#define DESC_CTL_HOSTOWN      0x80
++#define       DESC_CTL_ACXDONE_HOSTOWN (DESC_CTL_ACXDONE | DESC_CTL_HOSTOWN)
++
++/* Descriptor Status field
++ */
++#define       DESC_STATUS_FULL        (1 << 31)
++
++/* NB: some bits may be interesting for Monitor mode tx (aka Raw tx): */
++#define DESC_CTL2_SEQ         0x01    /* don't increase sequence field */
++#define DESC_CTL2_FCS         0x02    /* don't add the FCS */
++#define DESC_CTL2_MORE_FRAG   0x04
++#define DESC_CTL2_RETRY               0x08    /* don't increase retry field */
++#define DESC_CTL2_POWER               0x10    /* don't increase power mgmt. field */
++#define DESC_CTL2_RTS         0x20    /* do RTS/CTS magic before sending */
++#define DESC_CTL2_WEP         0x40    /* encrypt this frame */
++#define DESC_CTL2_DUR         0x80    /* don't increase duration field */
++
++/***********************************************************************
++** PCI structures
++*/
++/* IRQ Constants
++** (outside of "#ifdef PCI" because USB (mis)uses HOST_INT_SCAN_COMPLETE) */
++#define HOST_INT_RX_DATA      0x0001
++#define HOST_INT_TX_COMPLETE  0x0002
++#define HOST_INT_TX_XFER      0x0004
++#define HOST_INT_RX_COMPLETE  0x0008
++#define HOST_INT_DTIM         0x0010
++#define HOST_INT_BEACON               0x0020
++#define HOST_INT_TIMER                0x0040
++#define HOST_INT_KEY_NOT_FOUND        0x0080
++#define HOST_INT_IV_ICV_FAILURE       0x0100
++#define HOST_INT_CMD_COMPLETE 0x0200
++#define HOST_INT_INFO         0x0400
++#define HOST_INT_OVERFLOW     0x0800
++#define HOST_INT_PROCESS_ERROR        0x1000
++#define HOST_INT_SCAN_COMPLETE        0x2000
++#define HOST_INT_FCS_THRESHOLD        0x4000
++#define HOST_INT_UNKNOWN      0x8000
++
++/* Outside of "#ifdef PCI" because USB needs to know sizeof()
++** of txdesc and rxdesc: */
++struct txdesc {
++      acx_ptr pNextDesc;      /* pointer to next txdesc */
++      acx_ptr HostMemPtr;                     /* 0x04 */
++      acx_ptr AcxMemPtr;                      /* 0x08 */
++      u32     tx_time;                        /* 0x0c */
++      u16     total_length;           /* 0x10 */
++      u16     Reserved;                       /* 0x12 */
++
++/* The following 16 bytes do not change when acx100 owns the descriptor */
++/* BUG: fw clears last byte of this area which is supposedly reserved
++** for driver use. amd64 blew up. We dare not use it now */
++      u32     dummy[4];
++
++      u8      Ctl_8;                  /* 0x24, 8bit value */
++      u8      Ctl2_8;                 /* 0x25, 8bit value */
++      u8      error;                  /* 0x26 */
++      u8      ack_failures;           /* 0x27 */
++
++      union {
++        /*
++         * Packing doesn't work correctly on ARM unless unions are on
++         * 4 byte boundaries.
++         */
++              struct {
++                      u8      rts_failures;           /* 0x28 */
++                      u8      rts_ok;                 /* 0x29 */
++                      u16     d1;
++              } ACX_PACKED rts;
++              struct {
++                      u16     d1;
++                      u8      rate;   /* 0x2a */
++                      u8      queue_ctrl;     /* 0x2b */
++              } ACX_PACKED r1;
++              struct {
++                      u16     d1;
++                      u16     rate111;        /* 0x2a */
++              } ACX_PACKED r2;
++      } ACX_PACKED u;
++      u32     queue_info;                     /* 0x2c (acx100, reserved on acx111) */
++} ACX_PACKED;         /* size : 48 = 0x30 */
++/* NB: acx111 txdesc structure is 4 byte larger */
++/* All these 4 extra bytes are reserved. tx alloc code takes them into account */
++
++struct rxdesc {
++      acx_ptr pNextDesc;                      /* 0x00 */
++      acx_ptr HostMemPtr;                     /* 0x04 */
++      acx_ptr ACXMemPtr;                      /* 0x08 */
++      u32     rx_time;                        /* 0x0c */
++      u16     total_length;           /* 0x10 */
++      u16     WEP_length;                     /* 0x12 */
++      u32     WEP_ofs;                        /* 0x14 */
++
++/* the following 16 bytes do not change when acx100 owns the descriptor */
++      u8      driverWorkspace[16];            /* 0x18 */
++
++      u8      Ctl_8;
++      u8      rate;
++      u8      error;
++      u8      SNR;                            /* Signal-to-Noise Ratio */
++      u8      RxLevel;
++      u8      queue_ctrl;
++      u16     unknown;
++      u32     unknown2;
++} ACX_PACKED;         /* size 52 = 0x34 */
++
++#if defined(ACX_PCI) || defined(ACX_MEM)
++
++/* Register I/O offsets */
++#define ACX100_EEPROM_ID_OFFSET       0x380
++
++/* please add further ACX hardware register definitions only when
++   it turns out you need them in the driver, and please try to use
++   firmware functionality instead, since using direct I/O access instead
++   of letting the firmware do it might confuse the firmware's state
++   machine */
++
++/* ***** ABSOLUTELY ALWAYS KEEP OFFSETS IN SYNC WITH THE INITIALIZATION
++** OF THE I/O ARRAYS!!!! (grep for '^IO_ACX') ***** */
++enum {
++      IO_ACX_SOFT_RESET = 0,
++
++      IO_ACX_SLV_MEM_ADDR,
++      IO_ACX_SLV_MEM_DATA,
++      IO_ACX_SLV_MEM_CTL,
++      IO_ACX_SLV_END_CTL,
++
++      IO_ACX_FEMR,            /* Function Event Mask */
++
++      IO_ACX_INT_TRIG,
++      IO_ACX_IRQ_MASK,
++      IO_ACX_IRQ_STATUS_NON_DES,
++      IO_ACX_IRQ_STATUS_CLEAR, /* CLEAR = clear on read */
++      IO_ACX_IRQ_ACK,
++      IO_ACX_HINT_TRIG,
++
++      IO_ACX_ENABLE,
++
++      IO_ACX_EEPROM_CTL,
++      IO_ACX_EEPROM_ADDR,
++      IO_ACX_EEPROM_DATA,
++      IO_ACX_EEPROM_CFG,
++
++      IO_ACX_PHY_ADDR,
++      IO_ACX_PHY_DATA,
++      IO_ACX_PHY_CTL,
++
++      IO_ACX_GPIO_OE,
++
++      IO_ACX_GPIO_OUT,
++
++      IO_ACX_CMD_MAILBOX_OFFS,
++      IO_ACX_INFO_MAILBOX_OFFS,
++      IO_ACX_EEPROM_INFORMATION,
++
++      IO_ACX_EE_START,
++      IO_ACX_SOR_CFG,
++      IO_ACX_ECPU_CTRL
++};
++/* ***** ABSOLUTELY ALWAYS KEEP OFFSETS IN SYNC WITH THE INITIALIZATION
++** OF THE I/O ARRAYS!!!! (grep for '^IO_ACX') ***** */
++
++/* Values for IO_ACX_INT_TRIG register: */
++/* inform hw that rxdesc in queue needs processing */
++#define INT_TRIG_RXPRC                0x08
++/* inform hw that txdesc in queue needs processing */
++#define INT_TRIG_TXPRC                0x04
++/* ack that we received info from info mailbox */
++#define INT_TRIG_INFOACK      0x02
++/* inform hw that we have filled command mailbox */
++#define INT_TRIG_CMD          0x01
++
++struct txhostdesc {
++      acx_ptr data_phy;                       /* 0x00 [u8 *] */
++      u16     data_offset;                    /* 0x04 */
++      u16     reserved;                       /* 0x06 */
++      u16     Ctl_16; /* 16bit value, endianness!! */
++      u16     length;                 /* 0x0a */
++      acx_ptr desc_phy_next;          /* 0x0c [txhostdesc *] */
++      acx_ptr pNext;                  /* 0x10 [txhostdesc *] */
++      u32     Status;                 /* 0x14, unused on Tx */
++/* From here on you can use this area as you want (variable length, too!) */
++      u8      *data;
++} ACX_PACKED;
++
++struct rxhostdesc {
++      acx_ptr data_phy;                       /* 0x00 [rxbuffer_t *] */
++      u16     data_offset;                    /* 0x04 */
++      u16     reserved;                       /* 0x06 */
++      u16     Ctl_16;                 /* 0x08; 16bit value, endianness!! */
++      u16     length;                 /* 0x0a */
++      acx_ptr desc_phy_next;          /* 0x0c [rxhostdesc_t *] */
++      acx_ptr pNext;                  /* 0x10 [rxhostdesc_t *] */
++      u32     Status;                 /* 0x14 */
++/* From here on you can use this area as you want (variable length, too!) */
++      rxbuffer_t *data;
++} ACX_PACKED;
++
++#endif /* ACX_PCI */
++
++/***********************************************************************
++** USB structures and constants
++*/
++#ifdef ACX_USB
++
++/* Used for usb_txbuffer.desc field */
++#define USB_TXBUF_TXDESC      0xA
++/* Size of header (everything up to data[]) */
++#define USB_TXBUF_HDRSIZE     14
++typedef struct usb_txbuffer {
++      u16     desc;
++      u16     mpdu_len;
++      u8      queue_index;
++      u8      rate;
++      u32     hostdata;
++      u8      ctrl1;
++      u8      ctrl2;
++      u16     data_len;
++      /* wlan packet content is placed here: */
++      u8      data[WLAN_A4FR_MAXLEN_WEP_FCS];
++} ACX_PACKED usb_txbuffer_t;
++
++/* USB returns either rx packets (see rxbuffer) or
++** these "tx status" structs: */
++typedef struct usb_txstatus {
++      u16     mac_cnt_rcvd;           /* only 12 bits are len! (0xfff) */
++      u8      queue_index;
++      u8      mac_status;             /* seen 0x20 on tx failure */
++      u32     hostdata;
++      u8      rate;
++      u8      ack_failures;
++      u8      rts_failures;
++      u8      rts_ok;
++} ACX_PACKED usb_txstatus_t;
++
++typedef struct usb_tx {
++      unsigned        busy:1;
++      struct urb      *urb;
++      acx_device_t    *adev;
++      /* actual USB bulk output data block is here: */
++      usb_txbuffer_t  bulkout;
++} usb_tx_t;
++
++struct usb_rx_plain {
++      unsigned        busy:1;
++      struct urb      *urb;
++      acx_device_t    *adev;
++      rxbuffer_t      bulkin;
++};
++
++typedef struct usb_rx {
++      unsigned        busy:1;
++      struct urb      *urb;
++      acx_device_t    *adev;
++      rxbuffer_t      bulkin;
++ /* Make entire structure 4k. Report if it breaks something. */
++      u8 padding[4*1024 - sizeof(struct usb_rx_plain)];
++} usb_rx_t;
++#endif /* ACX_USB */
++
++
++/* Config Option structs */
++
++typedef struct co_antennas {
++      u8      type;
++      u8      len;
++      u8      list[2];
++} ACX_PACKED co_antennas_t;
++
++typedef struct co_powerlevels {
++      u8      type;
++      u8      len;
++      u16     list[8];
++} ACX_PACKED co_powerlevels_t;
++
++typedef struct co_datarates {
++      u8      type;
++      u8      len;
++      u8      list[8];
++} ACX_PACKED co_datarates_t;
++
++typedef struct co_domains {
++      u8      type;
++      u8      len;
++      u8      list[6];
++} ACX_PACKED co_domains_t;
++
++typedef struct co_product_id {
++      u8      type;
++      u8      len;
++      u8      list[128];
++} ACX_PACKED co_product_id_t;
++
++typedef struct co_manuf_id {
++      u8      type;
++      u8      len;
++      u8      list[128];
++} ACX_PACKED co_manuf_t;
++
++typedef struct co_fixed {
++      char    NVSv[8];
++/*    u16     NVS_vendor_offs;        ACX111-only */
++/*    u16     unknown;                ACX111-only */
++      u8      MAC[6]; /* ACX100-only */
++      u16     probe_delay;    /* ACX100-only */
++      u32     eof_memory;
++      u8      dot11CCAModes;
++      u8      dot11Diversity;
++      u8      dot11ShortPreambleOption;
++      u8      dot11PBCCOption;
++      u8      dot11ChannelAgility;
++      u8      dot11PhyType; /* FIXME: does 802.11 call it "dot11PHYType"? */
++      u8      dot11TempType;
++      u8      table_count;
++} ACX_PACKED co_fixed_t;
++
++typedef struct acx111_ie_configoption {
++      u16                     type;
++      u16                     len;
++/* Do not access below members directly, they are in fact variable length */
++      co_fixed_t              fixed;
++      co_antennas_t           antennas;
++      co_powerlevels_t        power_levels;
++      co_datarates_t          data_rates;
++      co_domains_t            domains;
++      co_product_id_t         product_id;
++      co_manuf_t              manufacturer;
++      u8                      _padding[4];
++} ACX_PACKED acx111_ie_configoption_t;
++
++
++/***********************************************************************
++** Main acx per-device data structure
++*/
++#define ACX_STATE_FW_LOADED   0x01
++#define ACX_STATE_IFACE_UP    0x02
++
++/* MAC mode (BSS type) defines
++ * Note that they shouldn't be redefined, since they are also used
++ * during communication with firmware */
++#define ACX_MODE_0_ADHOC      0
++#define ACX_MODE_1_UNUSED     1
++#define ACX_MODE_2_STA                2
++#define ACX_MODE_3_AP         3
++/* These are our own inventions. Sending these to firmware
++** makes it stop emitting beacons, which is exactly what we want
++** for these modes */
++#define ACX_MODE_MONITOR      0xfe
++#define ACX_MODE_OFF          0xff
++/* 'Submode': identifies exact status of ADHOC/STA host */
++#define ACX_STATUS_0_STOPPED          0
++#define ACX_STATUS_1_SCANNING         1
++#define ACX_STATUS_2_WAIT_AUTH                2
++#define ACX_STATUS_3_AUTHENTICATED    3
++#define ACX_STATUS_4_ASSOCIATED               4
++
++/* FIXME: this should be named something like struct acx_priv (typedef'd to
++ * acx_priv_t) */
++
++/* non-firmware struct, no packing necessary */
++struct acx_device {
++      /* most frequent accesses first (dereferencing and cache line!) */
++
++      /*** Locking ***/
++      /* FIXME: try to convert semaphore to more efficient mutex according
++         to Ingo Molnar's docs (but not before driver is in mainline or
++               pre-mutex Linux 2.6.10 is very outdated). */
++      struct semaphore        sem;
++      spinlock_t              lock;
++#if defined(PARANOID_LOCKING) /* Lock debugging */
++      const char              *last_sem;
++      const char              *last_lock;
++      unsigned long           sem_time;
++      unsigned long           lock_time;
++#endif
++#ifdef ACX_MEM
++        spinlock_t              txbuf_lock;
++#endif
++
++      /*** Linux network device ***/
++      struct net_device       *ndev;          /* pointer to linux netdevice */
++
++      /*** Device statistics ***/
++      struct net_device_stats stats;          /* net device statistics */
++#ifdef WIRELESS_EXT
++      struct iw_statistics    wstats;         /* wireless statistics */
++#endif
++      /*** Power managment ***/
++      struct pm_dev           *pm;            /* PM crap */
++
++      /*** Management timer ***/
++      struct timer_list       mgmt_timer;
++
++      /*** Hardware identification ***/
++      const char              *chip_name;
++      u8                      dev_type;
++      u8                      chip_type;
++      u8                      form_factor;
++      u8                      radio_type;
++      u8                      eeprom_version;
++
++      /*** Config retrieved from EEPROM ***/
++      char                    cfgopt_NVSv[8];
++      u16                     cfgopt_NVS_vendor_offs;
++      u8                      cfgopt_MAC[6];
++      u16                     cfgopt_probe_delay;
++      u32                     cfgopt_eof_memory;
++      u8                      cfgopt_dot11CCAModes;
++      u8                      cfgopt_dot11Diversity;
++      u8                      cfgopt_dot11ShortPreambleOption;
++      u8                      cfgopt_dot11PBCCOption;
++      u8                      cfgopt_dot11ChannelAgility;
++      u8                      cfgopt_dot11PhyType;
++      u8                      cfgopt_dot11TempType;
++      co_antennas_t           cfgopt_antennas;
++      co_powerlevels_t        cfgopt_power_levels;
++      co_datarates_t          cfgopt_data_rates;
++      co_domains_t            cfgopt_domains;
++      co_product_id_t         cfgopt_product_id;
++      co_manuf_t              cfgopt_manufacturer;
++
++      /*** Firmware identification ***/
++      char            firmware_version[FW_ID_SIZE+1];
++      u32             firmware_numver;
++      u32             firmware_id;
++      const u16       *ie_len;
++      const u16       *ie_len_dot11;
++
++      /*** Device state ***/
++      u16             dev_state_mask;
++      u8              led_power;              /* power LED status */
++      u32             get_mask;               /* mask of settings to fetch from the card */
++      u32             set_mask;               /* mask of settings to write to the card */
++
++      /* Barely used in USB case */
++      u16             irq_status;
++
++      u8              after_interrupt_jobs;   /* mini job list for doing actions after an interrupt occurred */
++      WORK_STRUCT     after_interrupt_task;   /* our task for after interrupt actions */
++
++      /*** scanning ***/
++      u16             scan_count;             /* number of times to do channel scan */
++      u8              scan_mode;              /* 0 == active, 1 == passive, 2 == background */
++      u8              scan_rate;
++      u16             scan_duration;
++      u16             scan_probe_delay;
++#if WIRELESS_EXT > 15
++      struct iw_spy_data      spy_data;       /* FIXME: needs to be implemented! */
++#endif
++
++      /*** Wireless network settings ***/
++      /* copy of the device address (ifconfig hw ether) that we actually use
++      ** for 802.11; copied over from the network device's MAC address
++      ** (ifconfig) when it makes sense only */
++      u8              dev_addr[MAX_ADDR_LEN];
++      u8              bssid[ETH_ALEN];        /* the BSSID after having joined */
++      u8              ap[ETH_ALEN];           /* The AP we want, FF:FF:FF:FF:FF:FF is any */
++      u16             aid;                    /* The Association ID sent from the AP / last used AID if we're an AP */
++      u16             mode;                   /* mode from iwconfig */
++      int             monitor_type;           /* ARPHRD_IEEE80211 or ARPHRD_IEEE80211_PRISM */
++      u16             status;                 /* 802.11 association status */
++      u8              essid_active;           /* specific ESSID active, or select any? */
++      u8              essid_len;              /* to avoid dozens of strlen() */
++      /* INCLUDES \0 termination for easy printf - but many places
++      ** simply want the string data memcpy'd plus a length indicator!
++      ** Keep that in mind... */
++      char            essid[IW_ESSID_MAX_SIZE+1];
++      /* essid we are going to use for association, in case of "essid 'any'"
++      ** and in case of hidden ESSID (use configured ESSID then) */
++      char            essid_for_assoc[IW_ESSID_MAX_SIZE+1];
++      char            nick[IW_ESSID_MAX_SIZE+1]; /* see essid! */
++      u8              channel;
++      u8              reg_dom_id;             /* reg domain setting */
++      u16             reg_dom_chanmask;
++      u16             auth_or_assoc_retries;
++      u16             scan_retries;
++      unsigned long   scan_start;             /* YES, jiffies is defined as "unsigned long" */
++
++      /* stations known to us (if we're an ap) */
++      client_t        sta_list[32];           /* tab is larger than list, so that */
++      client_t        *sta_hash_tab[64];      /* hash collisions are not likely */
++      client_t        *ap_client;             /* this one is our AP (STA mode only) */
++
++      int             dup_count;
++      int             nondup_count;
++      unsigned long   dup_msg_expiry;
++      u16             last_seq_ctrl;          /* duplicate packet detection */
++
++      /* 802.11 power save mode */
++      u8              ps_wakeup_cfg;
++      u8              ps_listen_interval;
++      u8              ps_options;
++      u8              ps_hangover_period;
++      u32             ps_enhanced_transition_time;
++      u32             ps_beacon_rx_time;
++
++      /*** PHY settings ***/
++      u8              fallback_threshold;
++      u8              stepup_threshold;
++      u16             rate_basic;
++      u16             rate_oper;
++      u16             rate_bcast;
++      u16             rate_bcast100;
++      u8              rate_auto;              /* false if "iwconfig rate N" (WITHOUT 'auto'!) */
++      u8              preamble_mode;          /* 0 == Long Preamble, 1 == Short, 2 == Auto */
++      u8              preamble_cur;
++
++      u8              tx_disabled;
++      u8              tx_level_dbm;
++      /* u8           tx_level_val; */
++      /* u8           tx_level_auto;          whether to do automatic power adjustment */
++
++      unsigned long   recalib_time_last_success;
++      unsigned long   recalib_time_last_attempt;
++      int             recalib_failure_count;
++      int             recalib_msg_ratelimit;
++      int             retry_errors_msg_ratelimit;
++
++      unsigned long   brange_time_last_state_change;  /* time the power LED was last changed */
++      u8              brange_last_state;      /* last state of the LED */
++      u8              brange_max_quality;     /* maximum quality that equates to full speed */
++
++      u8              sensitivity;
++      u8              antenna;                /* antenna settings */
++      u8              ed_threshold;           /* energy detect threshold */
++      u8              cca;                    /* clear channel assessment */
++
++      u16             rts_threshold;
++      u16             frag_threshold;
++      u32             short_retry;
++      u32             long_retry;
++      u16             msdu_lifetime;
++      u16             listen_interval;        /* given in units of beacon interval */
++      u32             beacon_interval;
++
++      u16             capabilities;
++      u8              rate_supported_len;
++      u8              rate_supported[13];
++
++      /*** Encryption settings (WEP) ***/
++      u32             auth_alg;               /* used in transmit_authen1 */
++      u8              wep_enabled;
++      u8              wep_restricted;
++      u8              wep_current_index;
++      wep_key_t       wep_keys[DOT11_MAX_DEFAULT_WEP_KEYS];   /* the default WEP keys */
++      key_struct_t    wep_key_struct[10];
++
++      /*** Unknown ***/
++      u8              dtim_interval;
++
++#ifdef ACX_MEM
++        u32 acx_txbuf_start;
++        int acx_txbuf_numblocks;
++        u32 acx_txbuf_free;                    /* addr of head of free list          */
++        int acx_txbuf_blocks_free;             /* how many are still open            */
++        queueindicator_t *acx_queue_indicator;
++#endif
++
++      /*** Card Rx/Tx management ***/
++      u16             rx_config_1;
++      u16             rx_config_2;
++      u16             memblocksize;
++      unsigned int    tx_free;
++      unsigned int    tx_head; /* keep as close as possible to Tx stuff below (cache line) */
++      u16             phy_header_len;
++
++/*************************************************************************
++ *** PCI/USB/... must be last or else hw agnostic code breaks horribly ***
++ *************************************************************************/
++
++      /* hack to let common code compile. FIXME */
++      dma_addr_t      rxhostdesc_startphy;
++
++      /*** PCI stuff ***/
++#if defined(ACX_PCI) || defined(ACX_MEM)
++      /* pointers to tx buffers, tx host descriptors (in host memory)
++      ** and tx descs in device memory */
++      unsigned int    tx_tail;
++      u8              *txbuf_start;
++      txhostdesc_t    *txhostdesc_start;
++      txdesc_t        *txdesc_start;  /* points to PCI-mapped memory */
++      dma_addr_t      txbuf_startphy;
++      dma_addr_t      txhostdesc_startphy;
++      /* sizes of above host memory areas */
++      unsigned int    txbuf_area_size;
++      unsigned int    txhostdesc_area_size;
++
++      unsigned int    txdesc_size;    /* size of txdesc; ACX111 = ACX100 + 4 */
++      client_t        *txc[TX_CNT];
++      u16             txr[TX_CNT];
++
++      /* same for rx */
++      unsigned int    rx_tail;
++      rxbuffer_t      *rxbuf_start;
++      rxhostdesc_t    *rxhostdesc_start;
++      rxdesc_t        *rxdesc_start;
++      /* physical addresses of above host memory areas */
++      dma_addr_t      rxbuf_startphy;
++      /* dma_addr_t   rxhostdesc_startphy; */
++      unsigned int    rxbuf_area_size;
++      unsigned int    rxhostdesc_area_size;
++
++      u8              need_radio_fw;
++      u8              irqs_active;    /* whether irq sending is activated */
++
++      const u16       *io;            /* points to ACX100 or ACX111 PCI I/O register address set */
++
++#ifdef ACX_PCI
++      struct pci_dev  *pdev;
++#endif
++#ifdef ACX_MEM
++      struct device   *dev;
++#endif
++
++#ifdef ACX_PCI
++      unsigned long   membase;
++#endif
++#ifdef ACX_MEM
++      volatile u32    *membase;
++#endif
++      unsigned long   membase2;
++#ifdef ACX_PCI
++      void __iomem    *iobase;
++#endif
++#ifdef ACX_MEM
++      volatile u32    *iobase;
++#endif
++      void __iomem    *iobase2;
++      /* command interface */
++      u8 __iomem      *cmd_area;
++      u8 __iomem      *info_area;
++
++      u16             irq_mask;               /* interrupt types to mask out (not wanted) with many IRQs activated */
++      u16             irq_mask_off;           /* interrupt types to mask out (not wanted) with IRQs off */
++      unsigned int    irq_loops_this_jiffy;
++      unsigned long   irq_last_jiffies;
++#endif
++
++      /*** USB stuff ***/
++#ifdef ACX_USB
++      struct usb_device       *usbdev;
++
++      rxbuffer_t      rxtruncbuf;
++
++      usb_tx_t        *usb_tx;
++      usb_rx_t        *usb_rx;
++
++      int             bulkinep;       /* bulk-in endpoint */
++      int             bulkoutep;      /* bulk-out endpoint */
++      int             rxtruncsize;
++#endif
++
++};
++
++static inline acx_device_t*
++ndev2adev(struct net_device *ndev)
++{
++      return netdev_priv(ndev);
++}
++
++
++/* For use with ACX1xx_IE_RXCONFIG */
++/*  bit     description
++ *    13   include additional header (length etc.) *required*
++ *            struct is defined in 'struct rxbuffer'
++ *            is this bit acx100 only? does acx111 always put the header,
++ *            and bit setting is irrelevant? --vda
++ *    10   receive frames only with SSID used in last join cmd
++ *     9   discard broadcast
++ *     8   receive packets for multicast address 1
++ *     7   receive packets for multicast address 0
++ *     6   discard all multicast packets
++ *     5   discard frames from foreign BSSID
++ *     4   discard frames with foreign destination MAC address
++ *     3   promiscuous mode (receive ALL frames, disable filter)
++ *     2   include FCS
++ *     1   include phy header
++ *     0   ???
++ */
++#define RX_CFG1_INCLUDE_RXBUF_HDR     0x2000 /* ACX100 only */
++#define RX_CFG1_FILTER_SSID           0x0400
++#define RX_CFG1_FILTER_BCAST          0x0200
++#define RX_CFG1_RCV_MC_ADDR1          0x0100
++#define RX_CFG1_RCV_MC_ADDR0          0x0080
++#define RX_CFG1_FILTER_ALL_MULTI      0x0040
++#define RX_CFG1_FILTER_BSSID          0x0020
++#define RX_CFG1_FILTER_MAC            0x0010
++#define RX_CFG1_RCV_PROMISCUOUS               0x0008
++#define RX_CFG1_INCLUDE_FCS           0x0004
++#define RX_CFG1_INCLUDE_PHY_HDR               (WANT_PHY_HDR ? 0x0002 : 0)
++/*  bit     description
++ *    11   receive association requests etc.
++ *    10   receive authentication frames
++ *     9   receive beacon frames
++ *     8   receive contention free packets
++ *     7   receive control frames
++ *     6   receive data frames
++ *     5   receive broken frames
++ *     4   receive management frames
++ *     3   receive probe requests
++ *     2   receive probe responses
++ *     1   receive RTS/CTS/ACK frames
++ *     0   receive other
++ */
++#define RX_CFG2_RCV_ASSOC_REQ         0x0800
++#define RX_CFG2_RCV_AUTH_FRAMES               0x0400
++#define RX_CFG2_RCV_BEACON_FRAMES     0x0200
++#define RX_CFG2_RCV_CONTENTION_FREE   0x0100
++#define RX_CFG2_RCV_CTRL_FRAMES               0x0080
++#define RX_CFG2_RCV_DATA_FRAMES               0x0040
++#define RX_CFG2_RCV_BROKEN_FRAMES     0x0020
++#define RX_CFG2_RCV_MGMT_FRAMES               0x0010
++#define RX_CFG2_RCV_PROBE_REQ         0x0008
++#define RX_CFG2_RCV_PROBE_RESP                0x0004
++#define RX_CFG2_RCV_ACK_FRAMES                0x0002
++#define RX_CFG2_RCV_OTHER             0x0001
++
++/* For use with ACX1xx_IE_FEATURE_CONFIG */
++#define FEATURE1_80MHZ_CLOCK  0x00000040L
++#define FEATURE1_4X           0x00000020L
++#define FEATURE1_LOW_RX               0x00000008L
++#define FEATURE1_EXTRA_LOW_RX 0x00000001L
++
++#define FEATURE2_SNIFFER      0x00000080L
++#define FEATURE2_NO_TXCRYPT   0x00000001L
++
++/*-- get and set mask values --*/
++#define GETSET_LED_POWER      0x00000001L
++#define GETSET_STATION_ID     0x00000002L
++#define SET_TEMPLATES         0x00000004L
++#define SET_STA_LIST          0x00000008L
++#define GETSET_TX             0x00000010L
++#define GETSET_RX             0x00000020L
++#define SET_RXCONFIG          0x00000040L
++#define GETSET_ANTENNA                0x00000080L
++#define GETSET_SENSITIVITY    0x00000100L
++#define GETSET_TXPOWER                0x00000200L
++#define GETSET_ED_THRESH      0x00000400L
++#define GETSET_CCA            0x00000800L
++#define GETSET_POWER_80211    0x00001000L
++#define GETSET_RETRY          0x00002000L
++#define GETSET_REG_DOMAIN     0x00004000L
++#define GETSET_CHANNEL                0x00008000L
++/* Used when ESSID changes etc and we need to scan for AP anew */
++#define GETSET_RESCAN         0x00010000L
++#define GETSET_MODE           0x00020000L
++#define GETSET_WEP            0x00040000L
++#define SET_WEP_OPTIONS               0x00080000L
++#define SET_MSDU_LIFETIME     0x00100000L
++#define SET_RATE_FALLBACK     0x00200000L
++
++/* keep in sync with the above */
++#define GETSET_ALL    (0 \
++/* GETSET_LED_POWER */        | 0x00000001L \
++/* GETSET_STATION_ID */       | 0x00000002L \
++/* SET_TEMPLATES */   | 0x00000004L \
++/* SET_STA_LIST */    | 0x00000008L \
++/* GETSET_TX */               | 0x00000010L \
++/* GETSET_RX */               | 0x00000020L \
++/* SET_RXCONFIG */    | 0x00000040L \
++/* GETSET_ANTENNA */  | 0x00000080L \
++/* GETSET_SENSITIVITY */| 0x00000100L \
++/* GETSET_TXPOWER */  | 0x00000200L \
++/* GETSET_ED_THRESH */        | 0x00000400L \
++/* GETSET_CCA */      | 0x00000800L \
++/* GETSET_POWER_80211 */| 0x00001000L \
++/* GETSET_RETRY */    | 0x00002000L \
++/* GETSET_REG_DOMAIN */       | 0x00004000L \
++/* GETSET_CHANNEL */  | 0x00008000L \
++/* GETSET_RESCAN */   | 0x00010000L \
++/* GETSET_MODE */     | 0x00020000L \
++/* GETSET_WEP */      | 0x00040000L \
++/* SET_WEP_OPTIONS */ | 0x00080000L \
++/* SET_MSDU_LIFETIME */       | 0x00100000L \
++/* SET_RATE_FALLBACK */       | 0x00200000L \
++                      )
++
++
++/***********************************************************************
++** Firmware loading
++*/
++#include <linux/firmware.h>   /* request_firmware() */
++#include <linux/pci.h>                /* struct pci_device */
++
++
++/***********************************************************************
++*/
++typedef struct acx100_ie_memblocksize {
++      u16     type;
++      u16     len;
++      u16     size;
++} ACX_PACKED acx100_ie_memblocksize_t;
++
++typedef struct acx100_ie_queueconfig {
++      u16     type;
++      u16     len;
++      u32     AreaSize;
++      u32     RxQueueStart;
++      u8      QueueOptions;
++      u8      NumTxQueues;
++      u8      NumRxDesc;       /* for USB only */
++      u8      pad1;
++      u32     QueueEnd;
++      u32     HostQueueEnd; /* QueueEnd2 */
++      u32     TxQueueStart;
++      u8      TxQueuePri;
++      u8      NumTxDesc;
++      u16     pad2;
++} ACX_PACKED acx100_ie_queueconfig_t;
++
++typedef struct acx111_ie_queueconfig {
++      u16     type;
++      u16     len;
++      u32     tx_memory_block_address;
++      u32     rx_memory_block_address;
++      u32     rx1_queue_address;
++      u32     reserved1;
++      u32     tx1_queue_address;
++      u8      tx1_attributes;
++      u16     reserved2;
++      u8      reserved3;
++} ACX_PACKED acx111_ie_queueconfig_t;
++
++typedef struct acx100_ie_memconfigoption {
++      u16     type;
++      u16     len;
++      u32     DMA_config;
++      acx_ptr pRxHostDesc;
++      u32     rx_mem;
++      u32     tx_mem;
++      u16     RxBlockNum;
++      u16     TxBlockNum;
++} ACX_PACKED acx100_ie_memconfigoption_t;
++
++typedef struct acx111_ie_memoryconfig {
++      u16     type;
++      u16     len;
++      u16     no_of_stations;
++      u16     memory_block_size;
++      u8      tx_rx_memory_block_allocation;
++      u8      count_rx_queues;
++      u8      count_tx_queues;
++      u8      options;
++      u8      fragmentation;
++      u16     reserved1;
++      u8      reserved2;
++
++      /* start of rx1 block */
++      u8      rx_queue1_count_descs;
++      u8      rx_queue1_reserved1;
++      u8      rx_queue1_type; /* must be set to 7 */
++      u8      rx_queue1_prio; /* must be set to 0 */
++      acx_ptr rx_queue1_host_rx_start;
++      /* end of rx1 block */
++
++      /* start of tx1 block */
++      u8      tx_queue1_count_descs;
++      u8      tx_queue1_reserved1;
++      u8      tx_queue1_reserved2;
++      u8      tx_queue1_attributes;
++      /* end of tx1 block */
++} ACX_PACKED acx111_ie_memoryconfig_t;
++
++typedef struct acx_ie_memmap {
++      u16     type;
++      u16     len;
++      u32     CodeStart;
++      u32     CodeEnd;
++      u32     WEPCacheStart;
++      u32     WEPCacheEnd;
++      u32     PacketTemplateStart;
++      u32     PacketTemplateEnd;
++      u32     QueueStart;
++      u32     QueueEnd;
++      u32     PoolStart;
++      u32     PoolEnd;
++} ACX_PACKED acx_ie_memmap_t;
++
++typedef struct acx111_ie_feature_config {
++      u16     type;
++      u16     len;
++      u32     feature_options;
++      u32     data_flow_options;
++} ACX_PACKED acx111_ie_feature_config_t;
++
++typedef struct acx111_ie_tx_level {
++      u16     type;
++      u16     len;
++      u8      level;
++} ACX_PACKED acx111_ie_tx_level_t;
++
++#define PS_CFG_ENABLE         0x80
++#define PS_CFG_PENDING                0x40 /* status flag when entering PS */
++#define PS_CFG_WAKEUP_MODE_MASK       0x07
++#define PS_CFG_WAKEUP_BY_HOST 0x03
++#define PS_CFG_WAKEUP_EACH_ITVL       0x02
++#define PS_CFG_WAKEUP_ON_DTIM 0x01
++#define PS_CFG_WAKEUP_ALL_BEAC        0x00
++
++/* Enhanced PS mode: sleep until Rx Beacon w/ the STA's AID bit set
++** in the TIM; newer firmwares only(?) */
++#define PS_OPT_ENA_ENHANCED_PS        0x04
++#define PS_OPT_TX_PSPOLL      0x02 /* send PSPoll frame to fetch waiting frames from AP (on frame with matching AID) */
++#define PS_OPT_STILL_RCV_BCASTS       0x01
++
++typedef struct acx100_ie_powersave {
++      u16     type;
++      u16     len;
++      u8      wakeup_cfg;
++      u8      listen_interval; /* for EACH_ITVL: wake up every "beacon units" interval */
++      u8      options;
++      u8      hangover_period; /* remaining wake time after Tx MPDU w/ PS bit, in values of 1/1024 seconds */
++      u16     enhanced_ps_transition_time; /* rem. wake time for Enh. PS */
++} ACX_PACKED acx100_ie_powersave_t;
++
++typedef struct acx111_ie_powersave {
++      u16     type;
++      u16     len;
++      u8      wakeup_cfg;
++      u8      listen_interval; /* for EACH_ITVL: wake up every "beacon units" interval */
++      u8      options;
++      u8      hangover_period; /* remaining wake time after Tx MPDU w/ PS bit, in values of 1/1024 seconds */
++      u32     beacon_rx_time;
++      u32     enhanced_ps_transition_time; /* rem. wake time for Enh. PS */
++} ACX_PACKED acx111_ie_powersave_t;
++
++
++/***********************************************************************
++** Commands and template structures
++*/
++
++/*
++** SCAN command structure
++**
++** even though acx100 scan rates match RATE100 constants,
++** acx111 ones do not match! Therefore we do not use RATE100 #defines */
++#define ACX_SCAN_RATE_1               10
++#define ACX_SCAN_RATE_2               20
++#define ACX_SCAN_RATE_5               55
++#define ACX_SCAN_RATE_11      110
++#define ACX_SCAN_RATE_22      220
++#define ACX_SCAN_RATE_PBCC    0x80    /* OR with this if needed */
++#define ACX_SCAN_OPT_ACTIVE   0x00    /* a bit mask */
++#define ACX_SCAN_OPT_PASSIVE  0x01
++/* Background scan: we go into Power Save mode (by transmitting
++** NULL data frame to AP with the power mgmt bit set), do the scan,
++** and then exit Power Save mode. A plus is that AP buffers frames
++** for us while we do background scan. Thus we avoid frame losses.
++** Background scan can be active or passive, just like normal one */
++#define ACX_SCAN_OPT_BACKGROUND       0x02
++typedef struct acx100_scan {
++      u16     count;  /* number of scans to do, 0xffff == continuous */
++      u16     start_chan;
++      u16     flags;  /* channel list mask; 0x8000 == all channels? */
++      u8      max_rate;       /* max. probe rate */
++      u8      options;        /* bit mask, see defines above */
++      u16     chan_duration;
++      u16     max_probe_delay;
++} ACX_PACKED acx100_scan_t;                   /* length 0xc */
++
++#define ACX111_SCAN_RATE_6    0x0B
++#define ACX111_SCAN_RATE_9    0x0F
++#define ACX111_SCAN_RATE_12   0x0A
++#define ACX111_SCAN_RATE_18   0x0E
++#define ACX111_SCAN_RATE_24   0x09
++#define ACX111_SCAN_RATE_36   0x0D
++#define ACX111_SCAN_RATE_48   0x08
++#define ACX111_SCAN_RATE_54   0x0C
++#define ACX111_SCAN_OPT_5GHZ    0x04  /* else 2.4GHZ */
++#define ACX111_SCAN_MOD_SHORTPRE 0x01 /* you can combine SHORTPRE and PBCC */
++#define ACX111_SCAN_MOD_PBCC  0x80
++#define ACX111_SCAN_MOD_OFDM  0x40
++typedef struct acx111_scan {
++      u16     count;          /* number of scans to do */
++      u8      channel_list_select; /* 0: scan all channels, 1: from chan_list only */
++      u16     reserved1;
++      u8      reserved2;
++      u8      rate;           /* rate for probe requests (if active scan) */
++      u8      options;                /* bit mask, see defines above */
++      u16     chan_duration;  /* min time to wait for reply on one channel (in TU) */
++                                              /* (active scan only) (802.11 section 11.1.3.2.2) */
++      u16     max_probe_delay;        /* max time to wait for reply on one channel (active scan) */
++                                              /* time to listen on a channel (passive scan) */
++      u8      modulation;
++      u8      channel_list[26];       /* bits 7:0 first byte: channels 8:1 */
++                                              /* bits 7:0 second byte: channels 16:9 */
++                                              /* 26 bytes is enough to cover 802.11a */
++} ACX_PACKED acx111_scan_t;
++
++
++/*
++** Radio calibration command structure
++*/
++typedef struct acx111_cmd_radiocalib {
++/* 0x80000000 == automatic calibration by firmware, according to interval;
++ * bits 0..3: select calibration methods to go through:
++ * calib based on DC, AfeDC, Tx mismatch, Tx equilization */
++      u32     methods;
++      u32     interval;
++} ACX_PACKED acx111_cmd_radiocalib_t;
++
++
++/*
++** Packet template structures
++**
++** Packet templates store contents of Beacon, Probe response, Probe request,
++** Null data frame, and TIM data frame. Firmware automatically transmits
++** contents of template at appropriate time:
++** - Beacon: when configured as AP or Ad-hoc
++** - Probe response: when configured as AP or Ad-hoc, whenever
++**   a Probe request frame is received
++** - Probe request: when host issues SCAN command (active)
++** - Null data frame: when entering 802.11 power save mode
++** - TIM data: at the end of Beacon frames (if no TIM template
++**   is configured, then transmits default TIM)
++** NB:
++** - size field must be set to size of actual template
++**   (NOT sizeof(struct) - templates are variable in length),
++**   size field is not itself counted.
++** - members flagged with an asterisk must be initialized with host,
++**   rest must be zero filled.
++** - variable length fields shown only in comments */
++typedef struct acx_template_tim {
++      u16     size;
++      u8      tim_eid;        /* 00 1 TIM IE ID * */
++      u8      len;            /* 01 1 Length * */
++      u8      dtim_cnt;       /* 02 1 DTIM Count */
++      u8      dtim_period;    /* 03 1 DTIM Period */
++      u8      bitmap_ctrl;    /* 04 1 Bitmap Control * (except bit0) */
++                                      /* 05 n Partial Virtual Bitmap * */
++      u8      variable[0x100 - 1-1-1-1-1];
++} ACX_PACKED acx_template_tim_t;
++
++typedef struct acx_template_probereq {
++      u16     size;
++      u16     fc;             /* 00 2 fc * */
++      u16     dur;            /* 02 2 Duration */
++      u8      da[6];  /* 04 6 Destination Address * */
++      u8      sa[6];  /* 0A 6 Source Address * */
++      u8      bssid[6];       /* 10 6 BSSID * */
++      u16     seq;            /* 16 2 Sequence Control */
++                                      /* 18 n SSID * */
++                                      /* nn n Supported Rates * */
++      u8      variable[0x44 - 2-2-6-6-6-2];
++} ACX_PACKED acx_template_probereq_t;
++
++typedef struct acx_template_proberesp {
++      u16     size;
++      u16     fc;             /* 00 2 fc * (bits [15:12] and [10:8] per 802.11 section 7.1.3.1) */
++      u16     dur;            /* 02 2 Duration */
++      u8      da[6];  /* 04 6 Destination Address */
++      u8      sa[6];  /* 0A 6 Source Address */
++      u8      bssid[6];       /* 10 6 BSSID */
++      u16     seq;            /* 16 2 Sequence Control */
++      u8      timestamp[8];/* 18 8 Timestamp */
++      u16     beacon_interval; /* 20 2 Beacon Interval * */
++      u16     cap;            /* 22 2 Capability Information * */
++                                      /* 24 n SSID * */
++                                      /* nn n Supported Rates * */
++                                      /* nn 1 DS Parameter Set * */
++      u8      variable[0x54 - 2-2-6-6-6-2-8-2-2];
++} ACX_PACKED acx_template_proberesp_t;
++#define acx_template_beacon_t acx_template_proberesp_t
++#define acx_template_beacon acx_template_proberesp
++
++typedef struct acx_template_nullframe {
++      u16     size;
++      struct wlan_hdr_a3 hdr;
++} ACX_PACKED acx_template_nullframe_t;
++
++
++/*
++** JOIN command structure
++**
++** as opposed to acx100, acx111 dtim interval is AFTER rates_basic111.
++** NOTE: took me about an hour to get !@#$%^& packing right --> struct packing is eeeeevil... */
++typedef struct acx_joinbss {
++      u8      bssid[ETH_ALEN];
++      u16     beacon_interval;
++      union {
++              struct {
++                      u8      dtim_interval;
++                      u8      rates_basic;
++                      u8      rates_supported;
++                /*
++                 * ARM compiler doesn't pack correctly unless unions
++                 * inside structures are multiples of 4 bytes.  Ugh.
++                 */
++                      u8      genfrm_txrate;  /* generated frame (bcn, proberesp, RTS, PSpoll) tx rate */
++              } ACX_PACKED acx100;
++              struct {
++                      u16     rates_basic;
++                      u8      dtim_interval;
++                      u8      genfrm_txrate;  /* generated frame (bcn, proberesp, RTS, PSpoll) tx rate */
++              } ACX_PACKED acx111;
++              /*
++               * ARM compiler doesn't pack correctly unles unions are aligned on
++               * 4 byte boundaries and are multiples of 4 bytes.
++               */
++              struct {
++                    u8 d1;
++                    u8 d2;
++                    u8 d3;
++                    u8 genfrm_txrate;
++              } ACX_PACKED txrate;
++      } ACX_PACKED u;
++      u8      genfrm_mod_pre; /* generated frame modulation/preamble:
++                                              ** bit7: PBCC, bit6: OFDM (else CCK/DQPSK/DBPSK)
++                                              ** bit5: short pre */
++      u8      macmode;        /* BSS Type, must be one of ACX_MODE_xxx */
++      u8      channel;
++      u8      essid_len;
++      char    essid[IW_ESSID_MAX_SIZE];
++} ACX_PACKED acx_joinbss_t;
++
++#define JOINBSS_RATES_1               0x01
++#define JOINBSS_RATES_2               0x02
++#define JOINBSS_RATES_5               0x04
++#define JOINBSS_RATES_11      0x08
++#define JOINBSS_RATES_22      0x10
++
++/* Looks like missing bits are used to indicate 11g rates!
++** (it follows from the fact that constants below match 1:1 to RATE111_nn)
++** This was actually seen! Look at that Assoc Request sent by acx111,
++** it _does_ contain 11g rates in basic set:
++01:30:20.070772 Beacon (xxx) [1.0* 2.0* 5.5* 11.0* 6.0* 9.0* 12.0* 18.0* 24.0* 36.0* 48.0* 54.0* Mbit] ESS CH: 1
++01:30:20.074425 Authentication (Open System)-1: Succesful
++01:30:20.076539 Authentication (Open System)-2:
++01:30:20.076620 Acknowledgment
++01:30:20.088546 Assoc Request (xxx) [1.0* 2.0* 5.5* 6.0* 9.0* 11.0* 12.0* 18.0* 24.0* 36.0* 48.0* 54.0* Mbit]
++01:30:20.122413 Assoc Response AID(1) :: Succesful
++01:30:20.122679 Acknowledgment
++01:30:20.173204 Beacon (xxx) [1.0* 2.0* 5.5* 11.0* 6.0* 9.0* 12.0* 18.0* 24.0* 36.0* 48.0* 54.0* Mbit] ESS CH: 1
++*/
++#define JOINBSS_RATES_BASIC111_1      0x0001
++#define JOINBSS_RATES_BASIC111_2      0x0002
++#define JOINBSS_RATES_BASIC111_5      0x0004
++#define JOINBSS_RATES_BASIC111_11     0x0020
++#define JOINBSS_RATES_BASIC111_22     0x0100
++
++
++/***********************************************************************
++*/
++typedef struct mem_read_write {
++      u16     addr;
++      u16     type; /* 0x0 int. RAM / 0xffff MAC reg. / 0x81 PHY RAM / 0x82 PHY reg.; or maybe it's actually 0x30 for MAC? Better verify it by writing and reading back and checking whether the value holds! */
++      u32     len;
++      u32     data;
++} ACX_PACKED mem_read_write_t;
++
++typedef struct firmware_image {
++      u32     chksum;
++      u32     size;
++      u8      data[1]; /* the byte array of the actual firmware... */
++} ACX_PACKED firmware_image_t;
++
++typedef struct acx_cmd_radioinit {
++      u32     offset;
++      u32     len;
++} ACX_PACKED acx_cmd_radioinit_t;
++
++typedef struct acx100_ie_wep_options {
++      u16     type;
++      u16     len;
++      u16     NumKeys;        /* max # of keys */
++      u8      WEPOption;      /* 0 == decrypt default key only, 1 == override decrypt */
++      u8      Pad;            /* used only for acx111 */
++} ACX_PACKED acx100_ie_wep_options_t;
++
++typedef struct ie_dot11WEPDefaultKey {
++      u16     type;
++      u16     len;
++      u8      action;
++      u8      keySize;
++      u8      defaultKeyNum;
++      u8      key[29];        /* check this! was Key[19] */
++} ACX_PACKED ie_dot11WEPDefaultKey_t;
++
++typedef struct acx111WEPDefaultKey {
++      u8      MacAddr[ETH_ALEN];
++      u16     action; /* NOTE: this is a u16, NOT a u8!! */
++      u16     reserved;
++      u8      keySize;
++      u8      type;
++      u8      index;
++      u8      defaultKeyNum;
++      u8      counter[6];
++      u8      key[32];        /* up to 32 bytes (for TKIP!) */
++} ACX_PACKED acx111WEPDefaultKey_t;
++
++typedef struct ie_dot11WEPDefaultKeyID {
++      u16     type;
++      u16     len;
++      u8      KeyID;
++} ACX_PACKED ie_dot11WEPDefaultKeyID_t;
++
++typedef struct acx100_cmd_wep_mgmt {
++      u8      MacAddr[ETH_ALEN];
++      u16     Action;
++      u16     KeySize;
++      u8      Key[29]; /* 29*8 == 232bits == WEP256 */
++} ACX_PACKED acx100_cmd_wep_mgmt_t;
++
++typedef struct acx_ie_generic {
++      u16     type;
++      u16     len;
++      union {
++              /* Association ID IE: just a 16bit value: */
++              u16     aid;
++              /* generic member for quick implementation of commands */
++              u8      bytes[32];
++      } ACX_PACKED m;
++} ACX_PACKED acx_ie_generic_t;
++
++/***********************************************************************
++*/
++#define CHECK_SIZEOF(type,size) { \
++      extern void BUG_bad_size_for_##type(void); \
++      if (sizeof(type)!=(size)) BUG_bad_size_for_##type(); \
++}
++
++static inline void
++acx_struct_size_check(void)
++{
++      CHECK_SIZEOF(txdesc_t, 0x30);
++      CHECK_SIZEOF(acx100_ie_memconfigoption_t, 24);
++      CHECK_SIZEOF(acx100_ie_queueconfig_t, 0x20);
++      CHECK_SIZEOF(acx_joinbss_t, 0x30);
++      /* IEs need 4 bytes for (type,len) tuple */
++      CHECK_SIZEOF(acx111_ie_configoption_t, ACX111_IE_CONFIG_OPTIONS_LEN + 4);
++}
++
++
++/***********************************************************************
++** Global data
++*/
++extern const u8 acx_bitpos2ratebyte[];
++extern const u8 acx_bitpos2rate100[];
++
++extern const u8 acx_reg_domain_ids[];
++extern const char * const acx_reg_domain_strings[];
++enum {
++      acx_reg_domain_ids_len = 8
++};
++
++extern const struct iw_handler_def acx_ioctl_handler_def;
+Index: linux-2.6.22/drivers/net/wireless/acx/common.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/drivers/net/wireless/acx/common.c     2007-08-23 18:34:19.000000000 +0200
+@@ -0,0 +1,7388 @@
++/***********************************************************************
++** Copyright (C) 2003  ACX100 Open Source Project
++**
++** The contents of this file are subject to the Mozilla Public
++** License Version 1.1 (the "License"); you may not use this file
++** except in compliance with the License. You may obtain a copy of
++** the License at http://www.mozilla.org/MPL/
++**
++** Software distributed under the License is distributed on an "AS
++** IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
++** implied. See the License for the specific language governing
++** rights and limitations under the License.
++**
++** Alternatively, the contents of this file may be used under the
++** terms of the GNU Public License version 2 (the "GPL"), in which
++** case the provisions of the GPL are applicable instead of the
++** above.  If you wish to allow the use of your version of this file
++** only under the terms of the GPL and not to allow others to use
++** your version of this file under the MPL, indicate your decision
++** by deleting the provisions above and replace them with the notice
++** and other provisions required by the GPL.  If you do not delete
++** the provisions above, a recipient may use your version of this
++** file under either the MPL or the GPL.
++** ---------------------------------------------------------------------
++** Inquiries regarding the ACX100 Open Source Project can be
++** made directly to:
++**
++** acx100-users@lists.sf.net
++** http://acx100.sf.net
++** ---------------------------------------------------------------------
++*/
++
++#include <linux/version.h>
++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18)
++#include <linux/config.h>
++#endif
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/types.h>
++#include <linux/slab.h>
++#include <linux/delay.h>
++#include <linux/proc_fs.h>
++#include <linux/if_arp.h>
++#include <linux/rtnetlink.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/wireless.h>
++#include <linux/pm.h>
++#include <linux/vmalloc.h>
++#include <net/iw_handler.h>
++
++#include "acx_hw.h"
++#include "acx.h"
++
++
++/***********************************************************************
++*/
++static client_t *acx_l_sta_list_alloc(acx_device_t *adev);
++static client_t *acx_l_sta_list_get_from_hash(acx_device_t *adev, const u8 *address);
++
++static int acx_l_process_data_frame_master(acx_device_t *adev, rxbuffer_t *rxbuf);
++static int acx_l_process_data_frame_client(acx_device_t *adev, rxbuffer_t *rxbuf);
++/* static int acx_l_process_NULL_frame(acx_device_t *adev, rxbuffer_t *rxbuf, int vala); */
++static int acx_l_process_mgmt_frame(acx_device_t *adev, rxbuffer_t *rxbuf);
++static void acx_l_process_disassoc_from_sta(acx_device_t *adev, const wlan_fr_disassoc_t *req);
++static void acx_l_process_disassoc_from_ap(acx_device_t *adev, const wlan_fr_disassoc_t *req);
++static void acx_l_process_deauth_from_sta(acx_device_t *adev, const wlan_fr_deauthen_t *req);
++static void acx_l_process_deauth_from_ap(acx_device_t *adev, const wlan_fr_deauthen_t *req);
++static int acx_l_process_probe_response(acx_device_t *adev, wlan_fr_proberesp_t *req, const rxbuffer_t *rxbuf);
++static int acx_l_process_assocresp(acx_device_t *adev, const wlan_fr_assocresp_t *req);
++static int acx_l_process_reassocresp(acx_device_t *adev, const wlan_fr_reassocresp_t *req);
++static int acx_l_process_authen(acx_device_t *adev, const wlan_fr_authen_t *req);
++static int acx_l_transmit_assocresp(acx_device_t *adev, const wlan_fr_assocreq_t *req);
++static int acx_l_transmit_reassocresp(acx_device_t *adev, const wlan_fr_reassocreq_t *req);
++static int acx_l_transmit_deauthen(acx_device_t *adev, const u8 *addr, u16 reason);
++static int acx_l_transmit_authen1(acx_device_t *adev);
++static int acx_l_transmit_authen2(acx_device_t *adev, const wlan_fr_authen_t *req, client_t *clt);
++static int acx_l_transmit_authen3(acx_device_t *adev, const wlan_fr_authen_t *req);
++static int acx_l_transmit_authen4(acx_device_t *adev, const wlan_fr_authen_t *req);
++static int acx_l_transmit_assoc_req(acx_device_t *adev);
++
++
++/***********************************************************************
++*/
++#if ACX_DEBUG
++unsigned int acx_debug /* will add __read_mostly later */ = ACX_DEFAULT_MSG;
++/* parameter is 'debug', corresponding var is acx_debug */
++module_param_named(debug, acx_debug, uint, 0);
++MODULE_PARM_DESC(debug, "Debug level mask (see L_xxx constants)");
++#endif
++
++#ifdef MODULE_LICENSE
++MODULE_LICENSE("Dual MPL/GPL");
++#endif
++/* USB had this: MODULE_AUTHOR("Martin Wawro <martin.wawro AT uni-dortmund.de>"); */
++MODULE_AUTHOR("ACX100 Open Source Driver development team");
++MODULE_DESCRIPTION("Driver for TI ACX1xx based wireless cards (CardBus/PCI/USB)");
++
++
++/***********************************************************************
++*/
++/* Probably a number of acx's intermediate buffers for USB transfers,
++** not to be confused with number of descriptors in tx/rx rings
++** (which are not directly accessible to host in USB devices) */
++#define USB_RX_CNT 10
++#define USB_TX_CNT 10
++
++
++/***********************************************************************
++*/
++
++/* minutes to wait until next radio recalibration: */
++#define RECALIB_PAUSE 5
++
++/* Please keep acx_reg_domain_ids_len in sync... */
++const u8 acx_reg_domain_ids[acx_reg_domain_ids_len] =
++      { 0x10, 0x20, 0x30, 0x31, 0x32, 0x40, 0x41, 0x51 };
++static const u16 reg_domain_channel_masks[acx_reg_domain_ids_len] =
++#ifdef ACX_ALLOW_ALLCHANNELS
++      { 0x3fff, 0x07ff, 0x1fff, 0x0600, 0x1e00, 0x2000, 0x3fff, 0x01fc };
++#else
++      { 0x07ff, 0x07ff, 0x1fff, 0x0600, 0x1e00, 0x2000, 0x3fff, 0x01fc };
++#endif
++const char * const
++acx_reg_domain_strings[] = {
++      /* 0 */ " 1-11 FCC (USA)",
++      /* 1 */ " 1-11 DOC/IC (Canada)",
++/* BTW: WLAN use in ETSI is regulated by ETSI standard EN 300 328-2 V1.1.2 */
++      /* 2 */ " 1-13 ETSI (Europe)",
++      /* 3 */ "10-11 Spain",
++      /* 4 */ "10-13 France",
++      /* 5 */ "   14 MKK (Japan)",
++      /* 6 */ " 1-14 MKK1",
++      /* 7 */ "  3-9 Israel (not all firmware versions)",
++      NULL /* needs to remain as last entry */
++};
++
++
++
++/***********************************************************************
++** Debugging support
++*/
++#ifdef PARANOID_LOCKING
++static unsigned max_lock_time;
++static unsigned max_sem_time;
++
++void
++acx_lock_unhold() { max_lock_time = 0; }
++void
++acx_sem_unhold() { max_sem_time = 0; }
++
++static inline const char*
++sanitize_str(const char *s)
++{
++      const char* t = strrchr(s, '/');
++      if (t) return t + 1;
++      return s;
++}
++
++void
++acx_lock_debug(acx_device_t *adev, const char* where)
++{
++      unsigned int count = 100*1000*1000;
++      where = sanitize_str(where);
++      while (--count) {
++              if (!spin_is_locked(&adev->lock)) break;
++              cpu_relax();
++      }
++      if (!count) {
++              printk(KERN_EMERG "LOCKUP: already taken at %s!\n", adev->last_lock);
++              BUG();
++      }
++      adev->last_lock = where;
++      rdtscl(adev->lock_time);
++}
++void
++acx_unlock_debug(acx_device_t *adev, const char* where)
++{
++#ifdef SMP
++      if (!spin_is_locked(&adev->lock)) {
++              where = sanitize_str(where);
++              printk(KERN_EMERG "STRAY UNLOCK at %s!\n", where);
++              BUG();
++      }
++#endif
++      if (acx_debug & L_LOCK) {
++              unsigned long diff;
++              rdtscl(diff);
++              diff -= adev->lock_time;
++              if (diff > max_lock_time) {
++                      where = sanitize_str(where);
++                      printk("max lock hold time %ld CPU ticks from %s "
++                              "to %s\n", diff, adev->last_lock, where);
++                      max_lock_time = diff;
++              }
++      }
++}
++void
++acx_down_debug(acx_device_t *adev, const char* where)
++{
++      int sem_count;
++      unsigned long timeout = jiffies + 5*HZ;
++
++      where = sanitize_str(where);
++
++      for (;;) {
++              sem_count = atomic_read(&adev->sem.count);
++              if (sem_count) break;
++              if (time_after(jiffies, timeout))
++                      break;
++              msleep(5);
++      }
++      if (!sem_count) {
++              printk(KERN_EMERG "D STATE at %s! last sem at %s\n",
++                      where, adev->last_sem);
++              dump_stack();
++      }
++      adev->last_sem = where;
++      adev->sem_time = jiffies;
++      down(&adev->sem);
++      if (acx_debug & L_LOCK) {
++              printk("%s: sem_down %d -> %d\n",
++                      where, sem_count, atomic_read(&adev->sem.count));
++      }
++}
++void
++acx_up_debug(acx_device_t *adev, const char* where)
++{
++      int sem_count = atomic_read(&adev->sem.count);
++      if (sem_count) {
++              where = sanitize_str(where);
++              printk(KERN_EMERG "STRAY UP at %s! sem.count=%d\n", where, sem_count);
++              dump_stack();
++      }
++      if (acx_debug & L_LOCK) {
++              unsigned long diff = jiffies - adev->sem_time;
++              if (diff > max_sem_time) {
++                      where = sanitize_str(where);
++                      printk("max sem hold time %ld jiffies from %s "
++                              "to %s\n", diff, adev->last_sem, where);
++                      max_sem_time = diff;
++              }
++      }
++      up(&adev->sem);
++      if (acx_debug & L_LOCK) {
++              where = sanitize_str(where);
++              printk("%s: sem_up %d -> %d\n",
++                      where, sem_count, atomic_read(&adev->sem.count));
++      }
++}
++#endif /* PARANOID_LOCKING */
++
++
++/***********************************************************************
++*/
++#if ACX_DEBUG > 1
++
++static int acx_debug_func_indent;
++#define DEBUG_TSC 0
++#define FUNC_INDENT_INCREMENT 2
++
++#if DEBUG_TSC
++#define TIMESTAMP(d) unsigned long d; rdtscl(d)
++#else
++#define TIMESTAMP(d) unsigned long d = jiffies
++#endif
++
++static const char
++spaces[] = "          " "          "; /* Nx10 spaces */
++
++void
++log_fn_enter(const char *funcname)
++{
++      int indent;
++      TIMESTAMP(d);
++
++      indent = acx_debug_func_indent;
++      if (indent >= sizeof(spaces))
++              indent = sizeof(spaces)-1;
++
++      printk("%08ld %s==> %s\n",
++              d % 100000000,
++              spaces + (sizeof(spaces)-1) - indent,
++              funcname
++      );
++
++      acx_debug_func_indent += FUNC_INDENT_INCREMENT;
++}
++void
++log_fn_exit(const char *funcname)
++{
++      int indent;
++      TIMESTAMP(d);
++
++      acx_debug_func_indent -= FUNC_INDENT_INCREMENT;
++
++      indent = acx_debug_func_indent;
++      if (indent >= sizeof(spaces))
++              indent = sizeof(spaces)-1;
++
++      printk("%08ld %s<== %s\n",
++              d % 100000000,
++              spaces + (sizeof(spaces)-1) - indent,
++              funcname
++      );
++}
++void
++log_fn_exit_v(const char *funcname, int v)
++{
++      int indent;
++      TIMESTAMP(d);
++
++      acx_debug_func_indent -= FUNC_INDENT_INCREMENT;
++
++      indent = acx_debug_func_indent;
++      if (indent >= sizeof(spaces))
++              indent = sizeof(spaces)-1;
++
++      printk("%08ld %s<== %s: %08X\n",
++              d % 100000000,
++              spaces + (sizeof(spaces)-1) - indent,
++              funcname,
++              v
++      );
++}
++#endif /* ACX_DEBUG > 1 */
++
++
++/***********************************************************************
++** Basically a msleep with logging
++*/
++void
++acx_s_msleep(int ms)
++{
++      FN_ENTER;
++      msleep(ms);
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++** Not inlined: it's larger than it seems
++*/
++void
++acx_print_mac(const char *head, const u8 *mac, const char *tail)
++{
++      printk("%s"MACSTR"%s", head, MAC(mac), tail);
++}
++
++
++/***********************************************************************
++** acx_get_status_name
++*/
++static const char*
++acx_get_status_name(u16 status)
++{
++      static const char * const str[] = {
++              "STOPPED", "SCANNING", "WAIT_AUTH",
++              "AUTHENTICATED", "ASSOCIATED", "INVALID??"
++      };
++      if (status > VEC_SIZE(str)-1)
++              status = VEC_SIZE(str)-1;
++
++      return str[status];
++}
++
++
++/***********************************************************************
++** acx_get_packet_type_string
++*/
++#if ACX_DEBUG
++const char*
++acx_get_packet_type_string(u16 fc)
++{
++      static const char * const mgmt_arr[] = {
++              "MGMT/AssocReq", "MGMT/AssocResp", "MGMT/ReassocReq",
++              "MGMT/ReassocResp", "MGMT/ProbeReq", "MGMT/ProbeResp",
++              "MGMT/UNKNOWN", "MGMT/UNKNOWN", "MGMT/Beacon", "MGMT/ATIM",
++              "MGMT/Disassoc", "MGMT/Authen", "MGMT/Deauthen"
++      };
++      static const char * const ctl_arr[] = {
++              "CTL/PSPoll", "CTL/RTS", "CTL/CTS", "CTL/Ack", "CTL/CFEnd",
++              "CTL/CFEndCFAck"
++      };
++      static const char * const data_arr[] = {
++              "DATA/DataOnly", "DATA/Data CFAck", "DATA/Data CFPoll",
++              "DATA/Data CFAck/CFPoll", "DATA/Null", "DATA/CFAck",
++              "DATA/CFPoll", "DATA/CFAck/CFPoll"
++      };
++      const char *str;
++      u8 fstype = (WF_FC_FSTYPE & fc) >> 4;
++      u8 ctl;
++
++      switch (WF_FC_FTYPE & fc) {
++      case WF_FTYPE_MGMT:
++              if (fstype < VEC_SIZE(mgmt_arr))
++                      str = mgmt_arr[fstype];
++              else
++                      str = "MGMT/UNKNOWN";
++              break;
++      case WF_FTYPE_CTL:
++              ctl = fstype - 0x0a;
++              if (ctl < VEC_SIZE(ctl_arr))
++                      str = ctl_arr[ctl];
++              else
++                      str = "CTL/UNKNOWN";
++              break;
++      case WF_FTYPE_DATA:
++              if (fstype < VEC_SIZE(data_arr))
++                      str = data_arr[fstype];
++              else
++                      str = "DATA/UNKNOWN";
++              break;
++      default:
++              str = "UNKNOWN";
++              break;
++      }
++      return str;
++}
++#endif
++
++
++/***********************************************************************
++** acx_wlan_reason_str
++*/
++static inline const char*
++acx_wlan_reason_str(u16 reason)
++{
++      static const char* const reason_str[] = {
++      /*  0 */        "?",
++      /*  1 */        "unspecified",
++      /*  2 */        "prev auth is not valid",
++      /*  3 */        "leaving BBS",
++      /*  4 */        "due to inactivity",
++      /*  5 */        "AP is busy",
++      /*  6 */        "got class 2 frame from non-auth'ed STA",
++      /*  7 */        "got class 3 frame from non-assoc'ed STA",
++      /*  8 */        "STA has left BSS",
++      /*  9 */        "assoc without auth is not allowed",
++      /* 10 */        "bad power setting (802.11h)",
++      /* 11 */        "bad channel (802.11i)",
++      /* 12 */        "?",
++      /* 13 */        "invalid IE",
++      /* 14 */        "MIC failure",
++      /* 15 */        "four-way handshake timeout",
++      /* 16 */        "group key handshake timeout",
++      /* 17 */        "IE is different",
++      /* 18 */        "invalid group cipher",
++      /* 19 */        "invalid pairwise cipher",
++      /* 20 */        "invalid AKMP",
++      /* 21 */        "unsupported RSN version",
++      /* 22 */        "invalid RSN IE cap",
++      /* 23 */        "802.1x failed",
++      /* 24 */        "cipher suite rejected"
++      };
++      return reason < VEC_SIZE(reason_str) ? reason_str[reason] : "?";
++}
++
++
++/***********************************************************************
++** acx_cmd_status_str
++*/
++const char*
++acx_cmd_status_str(unsigned int state)
++{
++      static const char * const cmd_error_strings[] = {
++              "Idle",
++              "Success",
++              "Unknown Command",
++              "Invalid Information Element",
++              "Channel rejected",
++              "Channel invalid in current regulatory domain",
++              "MAC invalid",
++              "Command rejected (read-only information element)",
++              "Command rejected",
++              "Already asleep",
++              "TX in progress",
++              "Already awake",
++              "Write only",
++              "RX in progress",
++              "Invalid parameter",
++              "Scan in progress",
++              "Failed"
++      };
++      return state < VEC_SIZE(cmd_error_strings) ?
++                      cmd_error_strings[state] : "?";
++}
++
++
++/***********************************************************************
++** get_status_string
++*/
++static inline const char*
++get_status_string(unsigned int status)
++{
++      /* A bit shortened, but hopefully still understandable */
++      static const char * const status_str[] = {
++      /* 0 */ "Successful",
++      /* 1 */ "Unspecified failure",
++      /* 2 */ "reserved",
++      /* 3 */ "reserved",
++      /* 4 */ "reserved",
++      /* 5 */ "reserved",
++      /* 6 */ "reserved",
++      /* 7 */ "reserved",
++      /* 8 */ "reserved",
++      /* 9 */ "reserved",
++      /*10 */ "Cannot support all requested capabilities in Capability Information field",
++      /*11 */ "Reassoc denied (reason outside of 802.11b scope)",
++      /*12 */ "Assoc denied (reason outside of 802.11b scope) -- maybe MAC filtering by peer?",
++      /*13 */ "Responding station doesnt support specified auth algorithm -- maybe WEP auth Open vs. Restricted?",
++      /*14 */ "Auth rejected: wrong transaction sequence number",
++      /*15 */ "Auth rejected: challenge failure",
++      /*16 */ "Auth rejected: timeout for next frame in sequence",
++      /*17 */ "Assoc denied: too many STAs on this AP",
++      /*18 */ "Assoc denied: requesting STA doesnt support all data rates in basic set",
++      /*19 */ "Assoc denied: requesting STA doesnt support Short Preamble",
++      /*20 */ "Assoc denied: requesting STA doesnt support PBCC Modulation",
++      /*21 */ "Assoc denied: requesting STA doesnt support Channel Agility"
++      /*22 */ "reserved",
++      /*23 */ "reserved",
++      /*24 */ "reserved",
++      /*25 */ "Assoc denied: requesting STA doesnt support Short Slot Time",
++      /*26 */ "Assoc denied: requesting STA doesnt support DSSS-OFDM"
++      };
++
++      return status_str[status < VEC_SIZE(status_str) ? status : 2];
++}
++
++
++/***********************************************************************
++*/
++void
++acx_log_bad_eid(wlan_hdr_t* hdr, int len, wlan_ie_t* ie_ptr)
++{
++      if (acx_debug & L_ASSOC) {
++              int offset = (u8*)ie_ptr - (u8*)hdr;
++              printk("acx: unknown EID %d in mgmt frame at offset %d. IE: ",
++                              ie_ptr->eid, offset);
++      /* IE len can be bogus, IE can extend past packet end. Oh well... */
++              acx_dump_bytes(ie_ptr, ie_ptr->len + 2);
++              if (acx_debug & L_DATA) {
++                      printk("frame (%s): ",
++                      acx_get_packet_type_string(le16_to_cpu(hdr->fc)));
++                      acx_dump_bytes(hdr, len);
++              }
++      }
++}
++
++
++/***********************************************************************
++*/
++#if ACX_DEBUG
++void
++acx_dump_bytes(const void *data, int num)
++{
++      const u8* ptr = (const u8*)data;
++
++      if (num <= 0) {
++              printk("\n");
++              return;
++      }
++
++      while (num >= 16) {
++              printk( "%02X %02X %02X %02X %02X %02X %02X %02X "
++                      "%02X %02X %02X %02X %02X %02X %02X %02X\n",
++                      ptr[0], ptr[1], ptr[2], ptr[3],
++                      ptr[4], ptr[5], ptr[6], ptr[7],
++                      ptr[8], ptr[9], ptr[10], ptr[11],
++                      ptr[12], ptr[13], ptr[14], ptr[15]);
++              num -= 16;
++              ptr += 16;
++      }
++      if (num > 0) {
++              while (--num > 0)
++                      printk("%02X ", *ptr++);
++              printk("%02X\n", *ptr);
++      }
++}
++#endif
++
++
++/***********************************************************************
++** acx_s_get_firmware_version
++*/
++void
++acx_s_get_firmware_version(acx_device_t *adev)
++{
++      fw_ver_t fw;
++      u8 hexarr[4] = { 0, 0, 0, 0 };
++      int hexidx = 0, val = 0;
++      const char *num;
++      char c;
++
++      FN_ENTER;
++
++      memset(fw.fw_id, 'E', FW_ID_SIZE);
++      acx_s_interrogate(adev, &fw, ACX1xx_IE_FWREV);
++      memcpy(adev->firmware_version, fw.fw_id, FW_ID_SIZE);
++      adev->firmware_version[FW_ID_SIZE] = '\0';
++
++      log(L_DEBUG, "fw_ver: fw_id='%s' hw_id=%08X\n",
++                              adev->firmware_version, fw.hw_id);
++
++      if (strncmp(fw.fw_id, "Rev ", 4) != 0) {
++              printk("acx: strange firmware version string "
++                      "'%s', please report\n", adev->firmware_version);
++              adev->firmware_numver = 0x01090407; /* assume 1.9.4.7 */
++      } else {
++              num = &fw.fw_id[4];
++              while (1) {
++                      c = *num++;
++                      if ((c == '.') || (c == '\0')) {
++                              hexarr[hexidx++] = val;
++                              if ((hexidx > 3) || (c == '\0')) /* end? */
++                                      break;
++                              val = 0;
++                              continue;
++                      }
++                      if ((c >= '0') && (c <= '9'))
++                              c -= '0';
++                      else
++                              c = c - 'a' + (char)10;
++                      val = val*16 + c;
++              }
++
++              adev->firmware_numver = (u32)(
++                              (hexarr[0] << 24) | (hexarr[1] << 16)
++                              | (hexarr[2] << 8) | hexarr[3]);
++              log(L_DEBUG, "firmware_numver 0x%08X\n", adev->firmware_numver);
++      }
++      if (IS_ACX111(adev)) {
++              if (adev->firmware_numver == 0x00010011) {
++                      /* This one does not survive floodpinging */
++                      printk("acx: firmware '%s' is known to be buggy, "
++                              "please upgrade\n", adev->firmware_version);
++              }
++      }
++
++      adev->firmware_id = le32_to_cpu(fw.hw_id);
++
++      /* we're able to find out more detailed chip names now */
++      switch (adev->firmware_id & 0xffff0000) {
++              case 0x01010000:
++              case 0x01020000:
++                      adev->chip_name = "TNETW1100A";
++                      break;
++              case 0x01030000:
++                      adev->chip_name = "TNETW1100B";
++                      break;
++              case 0x03000000:
++              case 0x03010000:
++                      adev->chip_name = "TNETW1130";
++                      break;
++              case 0x04030000: /* 0x04030101 is TNETW1450 */
++                      adev->chip_name = "TNETW1450";
++                      break;
++              default:
++                      printk("acx: unknown chip ID 0x%08X, "
++                              "please report\n", adev->firmware_id);
++                      break;
++      }
++
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++** acx_display_hardware_details
++**
++** Displays hw/fw version, radio type etc...
++*/
++void
++acx_display_hardware_details(acx_device_t *adev)
++{
++      const char *radio_str, *form_str;
++
++      FN_ENTER;
++
++      switch (adev->radio_type) {
++      case RADIO_MAXIM_0D:
++              radio_str = "Maxim";
++              break;
++      case RADIO_RFMD_11:
++              radio_str = "RFMD";
++              break;
++      case RADIO_RALINK_15:
++              radio_str = "Ralink";
++              break;
++      case RADIO_RADIA_16:
++              radio_str = "Radia";
++              break;
++      case RADIO_UNKNOWN_17:
++              /* TI seems to have a radio which is
++               * additionally 802.11a capable, too */
++              radio_str = "802.11a/b/g radio?! Please report";
++              break;
++      case RADIO_UNKNOWN_19:
++              radio_str = "A radio used by Safecom cards?! Please report";
++              break;
++      case RADIO_UNKNOWN_1B:
++              radio_str = "An unknown radio used by TNETW1450 USB adapters";
++              break;
++      default:
++              radio_str = "UNKNOWN, please report radio type name!";
++              break;
++      }
++
++      switch (adev->form_factor) {
++      case 0x00:
++              form_str = "unspecified";
++              break;
++      case 0x01:
++              form_str = "(mini-)PCI / CardBus";
++              break;
++      case 0x02:
++              form_str = "USB";
++              break;
++      case 0x03:
++              form_str = "Compact Flash";
++              break;
++      default:
++              form_str = "UNKNOWN, please report";
++              break;
++      }
++
++      printk("acx: === chipset %s, radio type 0x%02X (%s), "
++              "form factor 0x%02X (%s), EEPROM version 0x%02X: "
++              "uploaded firmware '%s' ===\n",
++              adev->chip_name, adev->radio_type, radio_str,
++              adev->form_factor, form_str, adev->eeprom_version,
++              adev->firmware_version);
++
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++*/
++int
++acx_e_change_mtu(struct net_device *ndev, int mtu)
++{
++      enum {
++              MIN_MTU = 256,
++              MAX_MTU = WLAN_DATA_MAXLEN - (ETH_HLEN)
++      };
++
++      if (mtu < MIN_MTU || mtu > MAX_MTU)
++              return -EINVAL;
++
++      ndev->mtu = mtu;
++      return 0;
++}
++
++
++/***********************************************************************
++** acx_e_get_stats, acx_e_get_wireless_stats
++*/
++struct net_device_stats*
++acx_e_get_stats(struct net_device *ndev)
++{
++      acx_device_t *adev = ndev2adev(ndev);
++      return &adev->stats;
++}
++
++struct iw_statistics*
++acx_e_get_wireless_stats(struct net_device *ndev)
++{
++      acx_device_t *adev = ndev2adev(ndev);
++      return &adev->wstats;
++}
++
++
++/***********************************************************************
++** maps acx111 tx descr rate field to acx100 one
++*/
++const u8
++acx_bitpos2rate100[] = {
++      RATE100_1       ,/* 0 */
++      RATE100_2       ,/* 1 */
++      RATE100_5       ,/* 2 */
++      RATE100_2       ,/* 3, should not happen */
++      RATE100_2       ,/* 4, should not happen */
++      RATE100_11      ,/* 5 */
++      RATE100_2       ,/* 6, should not happen */
++      RATE100_2       ,/* 7, should not happen */
++      RATE100_22      ,/* 8 */
++      RATE100_2       ,/* 9, should not happen */
++      RATE100_2       ,/* 10, should not happen */
++      RATE100_2       ,/* 11, should not happen */
++      RATE100_2       ,/* 12, should not happen */
++      RATE100_2       ,/* 13, should not happen */
++      RATE100_2       ,/* 14, should not happen */
++      RATE100_2       ,/* 15, should not happen */
++};
++
++u8
++acx_rate111to100(u16 r) {
++      return acx_bitpos2rate100[highest_bit(r)];
++}
++
++
++/***********************************************************************
++** Calculate level like the feb 2003 windows driver seems to do
++*/
++static u8
++acx_signal_to_winlevel(u8 rawlevel)
++{
++      /* u8 winlevel = (u8) (0.5 + 0.625 * rawlevel); */
++      u8 winlevel = ((4 + (rawlevel * 5)) / 8);
++
++      if (winlevel > 100)
++              winlevel = 100;
++      return winlevel;
++}
++
++u8
++acx_signal_determine_quality(u8 signal, u8 noise)
++{
++      int qual;
++
++      qual = (((signal - 30) * 100 / 70) + (100 - noise * 4)) / 2;
++
++      if (qual > 100)
++              return 100;
++      if (qual < 0)
++              return 0;
++      return qual;
++}
++
++
++/***********************************************************************
++** Interrogate/configure commands
++*/
++
++/* FIXME: the lengths given here probably aren't always correct.
++ * They should be gradually replaced by proper "sizeof(acx1XX_ie_XXXX)-4",
++ * unless the firmware actually expects a different length than the struct length */
++static const u16
++acx100_ie_len[] = {
++      0,
++      ACX100_IE_ACX_TIMER_LEN,
++      sizeof(acx100_ie_powersave_t)-4, /* is that 6 or 8??? */
++      ACX1xx_IE_QUEUE_CONFIG_LEN,
++      ACX100_IE_BLOCK_SIZE_LEN,
++      ACX1xx_IE_MEMORY_CONFIG_OPTIONS_LEN,
++      ACX1xx_IE_RATE_FALLBACK_LEN,
++      ACX100_IE_WEP_OPTIONS_LEN,
++      ACX1xx_IE_MEMORY_MAP_LEN, /*    ACX1xx_IE_SSID_LEN, */
++      0,
++      ACX1xx_IE_ASSOC_ID_LEN,
++      0,
++      ACX111_IE_CONFIG_OPTIONS_LEN,
++      ACX1xx_IE_FWREV_LEN,
++      ACX1xx_IE_FCS_ERROR_COUNT_LEN,
++      ACX1xx_IE_MEDIUM_USAGE_LEN,
++      ACX1xx_IE_RXCONFIG_LEN,
++      0,
++      0,
++      sizeof(fw_stats_t)-4,
++      0,
++      ACX1xx_IE_FEATURE_CONFIG_LEN,
++      ACX111_IE_KEY_CHOOSE_LEN,
++      ACX1FF_IE_MISC_CONFIG_TABLE_LEN,
++      ACX1FF_IE_WONE_CONFIG_LEN,
++      0,
++      ACX1FF_IE_TID_CONFIG_LEN,
++      0,
++      0,
++      0,
++      ACX1FF_IE_CALIB_ASSESSMENT_LEN,
++      ACX1FF_IE_BEACON_FILTER_OPTIONS_LEN,
++      ACX1FF_IE_LOW_RSSI_THRESH_OPT_LEN,
++      ACX1FF_IE_NOISE_HISTOGRAM_RESULTS_LEN,
++      0,
++      ACX1FF_IE_PACKET_DETECT_THRESH_LEN,
++      ACX1FF_IE_TX_CONFIG_OPTIONS_LEN,
++      ACX1FF_IE_CCA_THRESHOLD_LEN,
++      ACX1FF_IE_EVENT_MASK_LEN,
++      ACX1FF_IE_DTIM_PERIOD_LEN,
++      0,
++      ACX1FF_IE_ACI_CONFIG_SET_LEN,
++      0,
++      0,
++      0,
++      0,
++      0,
++      0,
++      ACX1FF_IE_EEPROM_VER_LEN,
++};
++
++static const u16
++acx100_ie_len_dot11[] = {
++      0,
++      ACX1xx_IE_DOT11_STATION_ID_LEN,
++      0,
++      ACX100_IE_DOT11_BEACON_PERIOD_LEN,
++      ACX1xx_IE_DOT11_DTIM_PERIOD_LEN,
++      ACX1xx_IE_DOT11_SHORT_RETRY_LIMIT_LEN,
++      ACX1xx_IE_DOT11_LONG_RETRY_LIMIT_LEN,
++      ACX100_IE_DOT11_WEP_DEFAULT_KEY_WRITE_LEN,
++      ACX1xx_IE_DOT11_MAX_XMIT_MSDU_LIFETIME_LEN,
++      0,
++      ACX1xx_IE_DOT11_CURRENT_REG_DOMAIN_LEN,
++      ACX1xx_IE_DOT11_CURRENT_ANTENNA_LEN,
++      0,
++      ACX1xx_IE_DOT11_TX_POWER_LEVEL_LEN,
++      ACX1xx_IE_DOT11_CURRENT_CCA_MODE_LEN,
++      ACX100_IE_DOT11_ED_THRESHOLD_LEN,
++      ACX1xx_IE_DOT11_WEP_DEFAULT_KEY_SET_LEN,
++      0,
++      0,
++      0,
++};
++
++static const u16
++acx111_ie_len[] = {
++      0,
++      ACX100_IE_ACX_TIMER_LEN,
++      sizeof(acx111_ie_powersave_t)-4,
++      ACX1xx_IE_QUEUE_CONFIG_LEN,
++      ACX100_IE_BLOCK_SIZE_LEN,
++      ACX1xx_IE_MEMORY_CONFIG_OPTIONS_LEN,
++      ACX1xx_IE_RATE_FALLBACK_LEN,
++      ACX100_IE_WEP_OPTIONS_LEN,
++      ACX1xx_IE_MEMORY_MAP_LEN, /*    ACX1xx_IE_SSID_LEN, */
++      0,
++      ACX1xx_IE_ASSOC_ID_LEN,
++      0,
++      ACX111_IE_CONFIG_OPTIONS_LEN,
++      ACX1xx_IE_FWREV_LEN,
++      ACX1xx_IE_FCS_ERROR_COUNT_LEN,
++      ACX1xx_IE_MEDIUM_USAGE_LEN,
++      ACX1xx_IE_RXCONFIG_LEN,
++      0,
++      0,
++      sizeof(fw_stats_t)-4,
++      0,
++      ACX1xx_IE_FEATURE_CONFIG_LEN,
++      ACX111_IE_KEY_CHOOSE_LEN,
++      ACX1FF_IE_MISC_CONFIG_TABLE_LEN,
++      ACX1FF_IE_WONE_CONFIG_LEN,
++      0,
++      ACX1FF_IE_TID_CONFIG_LEN,
++      0,
++      0,
++      0,
++      ACX1FF_IE_CALIB_ASSESSMENT_LEN,
++      ACX1FF_IE_BEACON_FILTER_OPTIONS_LEN,
++      ACX1FF_IE_LOW_RSSI_THRESH_OPT_LEN,
++      ACX1FF_IE_NOISE_HISTOGRAM_RESULTS_LEN,
++      0,
++      ACX1FF_IE_PACKET_DETECT_THRESH_LEN,
++      ACX1FF_IE_TX_CONFIG_OPTIONS_LEN,
++      ACX1FF_IE_CCA_THRESHOLD_LEN,
++      ACX1FF_IE_EVENT_MASK_LEN,
++      ACX1FF_IE_DTIM_PERIOD_LEN,
++      0,
++      ACX1FF_IE_ACI_CONFIG_SET_LEN,
++      0,
++      0,
++      0,
++      0,
++      0,
++      0,
++      ACX1FF_IE_EEPROM_VER_LEN,
++};
++
++static const u16
++acx111_ie_len_dot11[] = {
++      0,
++      ACX1xx_IE_DOT11_STATION_ID_LEN,
++      0,
++      ACX100_IE_DOT11_BEACON_PERIOD_LEN,
++      ACX1xx_IE_DOT11_DTIM_PERIOD_LEN,
++      ACX1xx_IE_DOT11_SHORT_RETRY_LIMIT_LEN,
++      ACX1xx_IE_DOT11_LONG_RETRY_LIMIT_LEN,
++      ACX100_IE_DOT11_WEP_DEFAULT_KEY_WRITE_LEN,
++      ACX1xx_IE_DOT11_MAX_XMIT_MSDU_LIFETIME_LEN,
++      0,
++      ACX1xx_IE_DOT11_CURRENT_REG_DOMAIN_LEN,
++      ACX1xx_IE_DOT11_CURRENT_ANTENNA_LEN,
++      0,
++      ACX1xx_IE_DOT11_TX_POWER_LEVEL_LEN,
++      ACX1xx_IE_DOT11_CURRENT_CCA_MODE_LEN,
++      ACX100_IE_DOT11_ED_THRESHOLD_LEN,
++      ACX1xx_IE_DOT11_WEP_DEFAULT_KEY_SET_LEN,
++      0,
++      0,
++      0,
++};
++
++
++#undef FUNC
++#define FUNC "configure"
++#if !ACX_DEBUG
++int
++acx_s_configure(acx_device_t *adev, void *pdr, int type)
++{
++#else
++int
++acx_s_configure_debug(acx_device_t *adev, void *pdr, int type, const char* typestr)
++{
++#endif
++      u16 len;
++      int res;
++
++      if (type < 0x1000)
++              len = adev->ie_len[type];
++      else
++              len = adev->ie_len_dot11[type - 0x1000];
++
++      log(L_CTL, FUNC"(type:%s,len:%u)\n", typestr, len);
++      if (unlikely(!len)) {
++              log(L_DEBUG, "zero-length type %s?!\n", typestr);
++      }
++
++      ((acx_ie_generic_t *)pdr)->type = cpu_to_le16(type);
++      ((acx_ie_generic_t *)pdr)->len = cpu_to_le16(len);
++      res = acx_s_issue_cmd(adev, ACX1xx_CMD_CONFIGURE, pdr, len + 4);
++      if (unlikely(OK != res)) {
++#if ACX_DEBUG
++              printk("%s: "FUNC"(type:%s) FAILED\n", adev->ndev->name, typestr);
++#else
++              printk("%s: "FUNC"(type:0x%X) FAILED\n", adev->ndev->name, type);
++#endif
++              /* dump_stack() is already done in issue_cmd() */
++      }
++      return res;
++}
++
++#undef FUNC
++#define FUNC "interrogate"
++#if !ACX_DEBUG
++int
++acx_s_interrogate(acx_device_t *adev, void *pdr, int type)
++{
++#else
++int
++acx_s_interrogate_debug(acx_device_t *adev, void *pdr, int type,
++              const char* typestr)
++{
++#endif
++      u16 len;
++      int res;
++
++      /* FIXME: no check whether this exceeds the array yet.
++       * We should probably remember the number of entries... */
++      if (type < 0x1000)
++              len = adev->ie_len[type];
++      else
++              len = adev->ie_len_dot11[type-0x1000];
++
++      log(L_CTL, FUNC"(type:%s,len:%u)\n", typestr, len);
++
++      ((acx_ie_generic_t *)pdr)->type = cpu_to_le16(type);
++      ((acx_ie_generic_t *)pdr)->len = cpu_to_le16(len);
++      res = acx_s_issue_cmd(adev, ACX1xx_CMD_INTERROGATE, pdr, len + 4);
++      if (unlikely(OK != res)) {
++#if ACX_DEBUG
++              printk("%s: "FUNC"(type:%s) FAILED\n", adev->ndev->name, typestr);
++#else
++              printk("%s: "FUNC"(type:0x%X) FAILED\n", adev->ndev->name, type);
++#endif
++              /* dump_stack() is already done in issue_cmd() */
++      }
++      return res;
++}
++
++#if CMD_DISCOVERY
++void
++great_inquisitor(acx_device_t *adev)
++{
++      static struct {
++              u16     type;
++              u16     len;
++              /* 0x200 was too large here: */
++              u8      data[0x100 - 4];
++      } ACX_PACKED ie;
++      u16 type;
++
++      FN_ENTER;
++
++      /* 0..0x20, 0x1000..0x1020 */
++      for (type = 0; type <= 0x1020; type++) {
++              if (type == 0x21)
++                      type = 0x1000;
++              ie.type = cpu_to_le16(type);
++              ie.len = cpu_to_le16(sizeof(ie) - 4);
++              acx_s_issue_cmd(adev, ACX1xx_CMD_INTERROGATE, &ie, sizeof(ie));
++      }
++      FN_EXIT0;
++}
++#endif
++
++
++#ifdef CONFIG_PROC_FS
++/***********************************************************************
++** /proc files
++*/
++/***********************************************************************
++** acx_l_proc_output
++** Generate content for our /proc entry
++**
++** Arguments:
++**    buf is a pointer to write output to
++**    adev is the usual pointer to our private struct acx_device
++** Returns:
++**    number of bytes actually written to buf
++** Side effects:
++**    none
++*/
++static int
++acx_l_proc_output(char *buf, acx_device_t *adev)
++{
++      char *p = buf;
++      int i;
++
++      FN_ENTER;
++
++      p += sprintf(p,
++              "acx driver version:\t\t" ACX_RELEASE "\n"
++              "Wireless extension version:\t" STRING(WIRELESS_EXT) "\n"
++              "chip name:\t\t\t%s (0x%08X)\n"
++              "radio type:\t\t\t0x%02X\n"
++              "form factor:\t\t\t0x%02X\n"
++              "EEPROM version:\t\t\t0x%02X\n"
++              "firmware version:\t\t%s (0x%08X)\n",
++              adev->chip_name, adev->firmware_id,
++              adev->radio_type,
++              adev->form_factor,
++              adev->eeprom_version,
++              adev->firmware_version, adev->firmware_numver);
++
++      for (i = 0; i < VEC_SIZE(adev->sta_list); i++) {
++              struct client *bss = &adev->sta_list[i];
++              if (!bss->used) continue;
++              p += sprintf(p, "BSS %u BSSID "MACSTR" ESSID %s channel %u "
++                      "Cap 0x%X SIR %u SNR %u\n",
++                      i, MAC(bss->bssid), (char*)bss->essid, bss->channel,
++                      bss->cap_info, bss->sir, bss->snr);
++      }
++      p += sprintf(p, "status:\t\t\t%u (%s)\n",
++                      adev->status, acx_get_status_name(adev->status));
++
++      FN_EXIT1(p - buf);
++      return p - buf;
++}
++
++
++/***********************************************************************
++*/
++static int
++acx_s_proc_diag_output(char *buf, acx_device_t *adev)
++{
++      char *p = buf;
++      unsigned long flags;
++      unsigned int len = 0, partlen;
++      u32 temp1, temp2;
++      u8 *st, *st_end;
++#ifdef __BIG_ENDIAN
++      u8 *st2;
++#endif
++      fw_stats_t *fw_stats;
++      char *part_str = NULL;
++      fw_stats_tx_t *tx = NULL;
++      fw_stats_rx_t *rx = NULL;
++      fw_stats_dma_t *dma = NULL;
++      fw_stats_irq_t *irq = NULL;
++      fw_stats_wep_t *wep = NULL;
++      fw_stats_pwr_t *pwr = NULL;
++      fw_stats_mic_t *mic = NULL;
++      fw_stats_aes_t *aes = NULL;
++      fw_stats_event_t *evt = NULL;
++
++      FN_ENTER;
++
++      acx_lock(adev, flags);
++
++#if defined (ACX_MEM)
++      p = acxmem_s_proc_diag_output(p, adev);
++#else
++      if (IS_PCI(adev))
++              p = acxpci_s_proc_diag_output(p, adev);
++#endif
++
++      p += sprintf(p,
++              "\n"
++              "** network status **\n"
++              "dev_state_mask 0x%04X\n"
++              "status %u (%s), "
++              "mode %u, channel %u, "
++              "reg_dom_id 0x%02X, reg_dom_chanmask 0x%04X, ",
++              adev->dev_state_mask,
++              adev->status, acx_get_status_name(adev->status),
++              adev->mode, adev->channel,
++              adev->reg_dom_id, adev->reg_dom_chanmask
++              );
++      p += sprintf(p,
++              "ESSID \"%s\", essid_active %d, essid_len %d, "
++              "essid_for_assoc \"%s\", nick \"%s\"\n"
++              "WEP ena %d, restricted %d, idx %d\n",
++              adev->essid, adev->essid_active, (int)adev->essid_len,
++              adev->essid_for_assoc, adev->nick,
++              adev->wep_enabled, adev->wep_restricted,
++              adev->wep_current_index);
++      p += sprintf(p, "dev_addr  "MACSTR"\n", MAC(adev->dev_addr));
++      p += sprintf(p, "bssid     "MACSTR"\n", MAC(adev->bssid));
++      p += sprintf(p, "ap_filter "MACSTR"\n", MAC(adev->ap));
++
++      p += sprintf(p,
++              "\n"
++              "** PHY status **\n"
++              "tx_disabled %d, tx_level_dbm %d\n" /* "tx_level_val %d, tx_level_auto %d\n" */
++              "sensitivity %d, antenna 0x%02X, ed_threshold %d, cca %d, preamble_mode %d\n"
++              "rate_basic 0x%04X, rate_oper 0x%04X\n"
++              "rts_threshold %d, frag_threshold %d, short_retry %d, long_retry %d\n"
++              "msdu_lifetime %d, listen_interval %d, beacon_interval %d\n",
++              adev->tx_disabled, adev->tx_level_dbm, /* adev->tx_level_val, adev->tx_level_auto, */
++              adev->sensitivity, adev->antenna, adev->ed_threshold, adev->cca, adev->preamble_mode,
++              adev->rate_basic, adev->rate_oper,
++              adev->rts_threshold, adev->frag_threshold, adev->short_retry, adev->long_retry,
++              adev->msdu_lifetime, adev->listen_interval, adev->beacon_interval);
++
++      acx_unlock(adev, flags);
++
++      p += sprintf(p,
++              "\n"
++              "** Firmware **\n"
++              "NOTE: version dependent statistics layout, "
++              "please report if you suspect wrong parsing!\n"
++              "\n"
++              "version \"%s\"\n", adev->firmware_version);
++
++      /* TODO: may replace kmalloc/memset with kzalloc once
++       * Linux 2.6.14 is widespread */
++      fw_stats = kmalloc(sizeof(*fw_stats), GFP_KERNEL);
++      if (!fw_stats) {
++              FN_EXIT1(0);
++              return 0;
++      }
++      memset(fw_stats, 0, sizeof(*fw_stats));
++
++      st = (u8 *)fw_stats;
++
++      part_str = "statistics query command";
++
++      if (OK != acx_s_interrogate(adev, st, ACX1xx_IE_FIRMWARE_STATISTICS))
++              goto fw_stats_end;
++
++      st += sizeof(u16);
++      len = *(u16 *)st;
++
++      if (len > sizeof(*fw_stats)) {
++              p += sprintf(p,
++                      "firmware version with bigger fw_stats struct detected\n"
++                      "(%u vs. %u), please report\n", len, sizeof(fw_stats_t));
++              if (len > sizeof(*fw_stats)) {
++                      p += sprintf(p, "struct size exceeded allocation!\n");
++                      len = sizeof(*fw_stats);
++              }
++      }
++      st += sizeof(u16);
++      st_end = st - 2*sizeof(u16) + len;
++
++#ifdef __BIG_ENDIAN
++      /* let's make one bold assumption here:
++       * (hopefully!) *all* statistics fields are u32 only,
++       * thus if we need to make endianness corrections
++       * we can simply do them in one go, in advance */
++      st2 = (u8 *)fw_stats;
++      for (temp1 = 0; temp1 < len; temp1 += 4, st2 += 4)
++              *(u32 *)st2 = le32_to_cpu(*(u32 *)st2);
++#endif
++
++      part_str = "Rx/Tx";
++
++      /* directly at end of a struct part? --> no error! */
++      if (st == st_end)
++              goto fw_stats_end;
++
++      tx = (fw_stats_tx_t *)st;
++      st += sizeof(fw_stats_tx_t);
++      rx = (fw_stats_rx_t *)st;
++      st += sizeof(fw_stats_rx_t);
++      partlen = sizeof(fw_stats_tx_t) + sizeof(fw_stats_rx_t);
++
++      if (IS_ACX100(adev)) {
++              /* at least ACX100 PCI F/W 1.9.8.b
++               * and ACX100 USB F/W 1.0.7-USB
++               * don't have those two fields... */
++              st -= 2*sizeof(u32);
++
++              /* our parsing doesn't quite match this firmware yet,
++               * log failure */
++              if (st > st_end)
++                      goto fw_stats_fail;
++              temp1 = temp2 = 999999999;
++      } else {
++              if (st > st_end)
++                      goto fw_stats_fail;
++              temp1 = rx->rx_aci_events;
++              temp2 = rx->rx_aci_resets;
++      }
++
++      p += sprintf(p,
++              "%s:\n"
++              "  tx_desc_overfl %u\n"
++              "  rx_OutOfMem %u, rx_hdr_overfl %u, rx_hw_stuck %u\n"
++              "  rx_dropped_frame %u, rx_frame_ptr_err %u, rx_xfr_hint_trig %u\n"
++              "  rx_aci_events %u, rx_aci_resets %u\n",
++              part_str,
++              tx->tx_desc_of,
++              rx->rx_oom,
++              rx->rx_hdr_of,
++              rx->rx_hw_stuck,
++              rx->rx_dropped_frame,
++              rx->rx_frame_ptr_err,
++              rx->rx_xfr_hint_trig,
++              temp1,
++              temp2);
++
++      part_str = "DMA";
++
++      if (st == st_end)
++              goto fw_stats_end;
++
++      dma = (fw_stats_dma_t *)st;
++      partlen = sizeof(fw_stats_dma_t);
++      st += partlen;
++
++      if (st > st_end)
++              goto fw_stats_fail;
++
++      p += sprintf(p,
++              "%s:\n"
++              "  rx_dma_req %u, rx_dma_err %u, tx_dma_req %u, tx_dma_err %u\n",
++              part_str,
++              dma->rx_dma_req,
++              dma->rx_dma_err,
++              dma->tx_dma_req,
++              dma->tx_dma_err);
++
++      part_str = "IRQ";
++
++      if (st == st_end)
++              goto fw_stats_end;
++
++      irq = (fw_stats_irq_t *)st;
++      partlen = sizeof(fw_stats_irq_t);
++      st += partlen;
++
++      if (st > st_end)
++              goto fw_stats_fail;
++
++      p += sprintf(p,
++              "%s:\n"
++              "  cmd_cplt %u, fiq %u\n"
++              "  rx_hdrs %u, rx_cmplt %u, rx_mem_overfl %u, rx_rdys %u\n"
++              "  irqs %u, tx_procs %u, decrypt_done %u\n"
++              "  dma_0_done %u, dma_1_done %u, tx_exch_complet %u\n"
++              "  commands %u, rx_procs %u, hw_pm_mode_changes %u\n"
++              "  host_acks %u, pci_pm %u, acm_wakeups %u\n",
++              part_str,
++              irq->cmd_cplt,
++              irq->fiq,
++              irq->rx_hdrs,
++              irq->rx_cmplt,
++              irq->rx_mem_of,
++              irq->rx_rdys,
++              irq->irqs,
++              irq->tx_procs,
++              irq->decrypt_done,
++              irq->dma_0_done,
++              irq->dma_1_done,
++              irq->tx_exch_complet,
++              irq->commands,
++              irq->rx_procs,
++              irq->hw_pm_mode_changes,
++              irq->host_acks,
++              irq->pci_pm,
++              irq->acm_wakeups);
++
++      part_str = "WEP";
++
++      if (st == st_end)
++              goto fw_stats_end;
++
++      wep = (fw_stats_wep_t *)st;
++      partlen = sizeof(fw_stats_wep_t);
++      st += partlen;
++
++      if (
++          (IS_PCI(adev) && IS_ACX100(adev))
++      ||  (IS_USB(adev) && IS_ACX100(adev))
++      ||  (IS_MEM(adev) && IS_ACX100(adev))
++      ) {
++              /* at least ACX100 PCI F/W 1.9.8.b,
++               * ACX100 USB F/W 1.0.7-USB
++               * and ACX100 Generic Slave F/W 1.10.7.K
++               * don't have those two fields...
++               */
++              st -= 2*sizeof(u32);
++              if (st > st_end)
++                      goto fw_stats_fail;
++              temp1 = temp2 = 999999999;
++      } else {
++              if (st > st_end)
++                      goto fw_stats_fail;
++              temp1 = wep->wep_pkt_decrypt;
++              temp2 = wep->wep_decrypt_irqs;
++      }
++
++      p += sprintf(p,
++              "%s:\n"
++              "  wep_key_count %u, wep_default_key_count %u, dot11_def_key_mib %u\n"
++              "  wep_key_not_found %u, wep_decrypt_fail %u\n"
++              "  wep_pkt_decrypt %u, wep_decrypt_irqs %u\n",
++              part_str,
++              wep->wep_key_count,
++              wep->wep_default_key_count,
++              wep->dot11_def_key_mib,
++              wep->wep_key_not_found,
++              wep->wep_decrypt_fail,
++              temp1,
++              temp2);
++
++      part_str = "power";
++
++      if (st == st_end)
++              goto fw_stats_end;
++
++      pwr = (fw_stats_pwr_t *)st;
++      partlen = sizeof(fw_stats_pwr_t);
++      st += partlen;
++
++      if (st > st_end)
++              goto fw_stats_fail;
++
++      p += sprintf(p,
++              "%s:\n"
++              "  tx_start_ctr %u, no_ps_tx_too_short %u\n"
++              "  rx_start_ctr %u, no_ps_rx_too_short %u\n"
++              "  lppd_started %u\n"
++              "  no_lppd_too_noisy %u, no_lppd_too_short %u, no_lppd_matching_frame %u\n",
++              part_str,
++              pwr->tx_start_ctr,
++              pwr->no_ps_tx_too_short,
++              pwr->rx_start_ctr,
++              pwr->no_ps_rx_too_short,
++              pwr->lppd_started,
++              pwr->no_lppd_too_noisy,
++              pwr->no_lppd_too_short,
++              pwr->no_lppd_matching_frame);
++
++      part_str = "MIC";
++
++      if (st == st_end)
++              goto fw_stats_end;
++
++      mic = (fw_stats_mic_t *)st;
++      partlen = sizeof(fw_stats_mic_t);
++      st += partlen;
++
++      if (st > st_end)
++              goto fw_stats_fail;
++
++      p += sprintf(p,
++              "%s:\n"
++              "  mic_rx_pkts %u, mic_calc_fail %u\n",
++              part_str,
++              mic->mic_rx_pkts,
++              mic->mic_calc_fail);
++
++      part_str = "AES";
++
++      if (st == st_end)
++              goto fw_stats_end;
++
++      aes = (fw_stats_aes_t *)st;
++      partlen = sizeof(fw_stats_aes_t);
++      st += partlen;
++
++      if (st > st_end)
++              goto fw_stats_fail;
++
++      p += sprintf(p,
++              "%s:\n"
++              "  aes_enc_fail %u, aes_dec_fail %u\n"
++              "  aes_enc_pkts %u, aes_dec_pkts %u\n"
++              "  aes_enc_irq %u, aes_dec_irq %u\n",
++              part_str,
++              aes->aes_enc_fail,
++              aes->aes_dec_fail,
++              aes->aes_enc_pkts,
++              aes->aes_dec_pkts,
++              aes->aes_enc_irq,
++              aes->aes_dec_irq);
++
++      part_str = "event";
++
++      if (st == st_end)
++              goto fw_stats_end;
++
++      evt = (fw_stats_event_t *)st;
++      partlen = sizeof(fw_stats_event_t);
++      st += partlen;
++
++      if (st > st_end)
++              goto fw_stats_fail;
++
++      p += sprintf(p,
++              "%s:\n"
++              "  heartbeat %u, calibration %u\n"
++              "  rx_mismatch %u, rx_mem_empty %u, rx_pool %u\n"
++              "  oom_late %u\n"
++              "  phy_tx_err %u, tx_stuck %u\n",
++              part_str,
++              evt->heartbeat,
++              evt->calibration,
++              evt->rx_mismatch,
++              evt->rx_mem_empty,
++              evt->rx_pool,
++              evt->oom_late,
++              evt->phy_tx_err,
++              evt->tx_stuck);
++
++      if (st < st_end)
++              goto fw_stats_bigger;
++
++      goto fw_stats_end;
++
++fw_stats_fail:
++      st -= partlen;
++      p += sprintf(p,
++              "failed at %s part (size %u), offset %u (struct size %u), "
++              "please report\n", part_str, partlen,
++              (int)st - (int)fw_stats, len);
++
++fw_stats_bigger:
++      for (; st < st_end; st += 4)
++              p += sprintf(p,
++                      "UNKN%3d: %u\n", (int)st - (int)fw_stats, *(u32 *)st);
++
++fw_stats_end:
++      kfree(fw_stats);
++
++      FN_EXIT1(p - buf);
++      return p - buf;
++}
++
++
++/***********************************************************************
++*/
++static int
++acx_s_proc_phy_output(char *buf, acx_device_t *adev)
++{
++      char *p = buf;
++      int i;
++
++      FN_ENTER;
++
++      /*
++      if (RADIO_RFMD_11 != adev->radio_type) {
++              printk("sorry, not yet adapted for radio types "
++                      "other than RFMD, please verify "
++                      "PHY size etc. first!\n");
++              goto end;
++      }
++      */
++
++      /* The PHY area is only 0x80 bytes long; further pages after that
++       * only have some page number registers with altered value,
++       * all other registers remain the same. */
++      for (i = 0; i < 0x80; i++) {
++              acx_s_read_phy_reg(adev, i, p++);
++      }
++
++      FN_EXIT1(p - buf);
++      return p - buf;
++}
++
++
++/***********************************************************************
++** acx_e_read_proc_XXXX
++** Handle our /proc entry
++**
++** Arguments:
++**    standard kernel read_proc interface
++** Returns:
++**    number of bytes written to buf
++** Side effects:
++**    none
++*/
++static int
++acx_e_read_proc(char *buf, char **start, off_t offset, int count,
++                   int *eof, void *data)
++{
++      acx_device_t *adev = (acx_device_t*)data;
++      unsigned long flags;
++      int length;
++
++      FN_ENTER;
++
++      acx_sem_lock(adev);
++      acx_lock(adev, flags);
++      /* fill buf */
++      length = acx_l_proc_output(buf, adev);
++      acx_unlock(adev, flags);
++      acx_sem_unlock(adev);
++
++      /* housekeeping */
++      if (length <= offset + count)
++              *eof = 1;
++      *start = buf + offset;
++      length -= offset;
++      if (length > count)
++              length = count;
++      if (length < 0)
++              length = 0;
++      FN_EXIT1(length);
++      return length;
++}
++
++static char _buf[32768];
++static int
++acx_e_read_proc_diag(char *buf, char **start, off_t offset, int count,
++                   int *eof, void *data)
++{
++      acx_device_t *adev = (acx_device_t*)data;
++      int length;
++
++      FN_ENTER;
++
++      acx_sem_lock(adev);
++      /* fill buf */
++      length = acx_s_proc_diag_output(_buf, adev);
++      acx_sem_unlock(adev);
++
++      memcpy(buf, _buf + offset, count);
++
++      /* housekeeping */
++      if (length <= offset + count)
++              *eof = 1;
++      *start = count;
++      length -= offset;
++      if (length > count)
++              length = count;
++      if (length < 0)
++              length = 0;
++      FN_EXIT1(length);
++      return length;
++}
++
++static int
++acx_e_read_proc_eeprom(char *buf, char **start, off_t offset, int count,
++                   int *eof, void *data)
++{
++      acx_device_t *adev = (acx_device_t*)data;
++      int length;
++
++      FN_ENTER;
++
++      /* fill buf */
++      length = 0;
++#if defined (ACX_MEM)
++              acx_sem_lock(adev);
++              length = acxmem_proc_eeprom_output(buf, adev);
++              acx_sem_unlock(adev);
++#else
++      if (IS_PCI(adev)) {
++              acx_sem_lock(adev);
++              length = acxpci_proc_eeprom_output(buf, adev);
++              acx_sem_unlock(adev);
++      }
++#endif
++
++      /* housekeeping */
++      if (length <= offset + count)
++              *eof = 1;
++      *start = buf + offset;
++      length -= offset;
++      if (length > count)
++              length = count;
++      if (length < 0)
++              length = 0;
++      FN_EXIT1(length);
++      return length;
++}
++
++static int
++acx_e_read_proc_phy(char *buf, char **start, off_t offset, int count,
++                   int *eof, void *data)
++{
++      acx_device_t *adev = (acx_device_t*)data;
++      int length;
++
++      FN_ENTER;
++
++      acx_sem_lock(adev);
++      /* fill buf */
++      length = acx_s_proc_phy_output(buf, adev);
++      acx_sem_unlock(adev);
++
++      /* housekeeping */
++      if (length <= offset + count)
++              *eof = 1;
++      *start = buf + offset;
++      length -= offset;
++      if (length > count)
++              length = count;
++      if (length < 0)
++              length = 0;
++      FN_EXIT1(length);
++      return length;
++}
++
++
++/***********************************************************************
++** /proc files registration
++*/
++static const char * const
++proc_files[] = { "", "_diag", "_eeprom", "_phy" };
++
++static read_proc_t * const
++proc_funcs[] = {
++      acx_e_read_proc,
++      acx_e_read_proc_diag,
++      acx_e_read_proc_eeprom,
++      acx_e_read_proc_phy
++};
++
++static int
++manage_proc_entries(const struct net_device *ndev, int remove)
++{
++      acx_device_t *adev = ndev2adev((struct net_device *)ndev);
++      char procbuf[80];
++      int i;
++
++      for (i = 0; i < VEC_SIZE(proc_files); i++)      {
++              snprintf(procbuf, sizeof(procbuf),
++                      "driver/acx_%s%s", ndev->name, proc_files[i]);
++              log(L_INIT, "%sing /proc entry %s\n",
++                      remove ? "remov" : "creat", procbuf);
++              if (!remove) {
++                      if (!create_proc_read_entry(procbuf, 0, 0, proc_funcs[i], adev)) {
++                              printk("acx: cannot register /proc entry %s\n", procbuf);
++                              return NOT_OK;
++                      }
++              } else {
++                      remove_proc_entry(procbuf, NULL);
++              }
++      }
++      return OK;
++}
++
++int
++acx_proc_register_entries(const struct net_device *ndev)
++{
++      return manage_proc_entries(ndev, 0);
++}
++
++int
++acx_proc_unregister_entries(const struct net_device *ndev)
++{
++      return manage_proc_entries(ndev, 1);
++}
++#endif /* CONFIG_PROC_FS */
++
++
++/***********************************************************************
++** acx_cmd_join_bssid
++**
++** Common code for both acx100 and acx111.
++*/
++/* NB: does NOT match RATE100_nn but matches ACX[111]_SCAN_RATE_n */
++static const u8
++bitpos2genframe_txrate[] = {
++      10,     /*  0.  1 Mbit/s */
++      20,     /*  1.  2 Mbit/s */
++      55,     /*  2.  5.5 Mbit/s */
++      0x0B,   /*  3.  6 Mbit/s */
++      0x0F,   /*  4.  9 Mbit/s */
++      110,    /*  5. 11 Mbit/s */
++      0x0A,   /*  6. 12 Mbit/s */
++      0x0E,   /*  7. 18 Mbit/s */
++      220,    /*  8. 22 Mbit/s */
++      0x09,   /*  9. 24 Mbit/s */
++      0x0D,   /* 10. 36 Mbit/s */
++      0x08,   /* 11. 48 Mbit/s */
++      0x0C,   /* 12. 54 Mbit/s */
++      10,     /* 13.  1 Mbit/s, should never happen */
++      10,     /* 14.  1 Mbit/s, should never happen */
++      10,     /* 15.  1 Mbit/s, should never happen */
++};
++
++/* Looks scary, eh?
++** Actually, each one compiled into one AND and one SHIFT,
++** 31 bytes in x86 asm (more if uints are replaced by u16/u8) */
++static inline unsigned int
++rate111to5bits(unsigned int rate)
++{
++      return (rate & 0x7)
++      | ( (rate & RATE111_11) / (RATE111_11/JOINBSS_RATES_11) )
++      | ( (rate & RATE111_22) / (RATE111_22/JOINBSS_RATES_22) )
++      ;
++}
++
++static void
++acx_s_cmd_join_bssid(acx_device_t *adev, const u8 *bssid)
++{
++      acx_joinbss_t tmp;
++      int dtim_interval;
++      int i;
++
++      if (mac_is_zero(bssid))
++              return;
++
++      FN_ENTER;
++
++      dtim_interval = (ACX_MODE_0_ADHOC == adev->mode) ?
++                      1 : adev->dtim_interval;
++
++      memset(&tmp, 0, sizeof(tmp));
++
++      for (i = 0; i < ETH_ALEN; i++) {
++              tmp.bssid[i] = bssid[ETH_ALEN-1 - i];
++      }
++
++      tmp.beacon_interval = cpu_to_le16(adev->beacon_interval);
++
++      /* Basic rate set. Control frame responses (such as ACK or CTS frames)
++      ** are sent with one of these rates */
++      if (IS_ACX111(adev)) {
++              /* It was experimentally determined that rates_basic
++              ** can take 11g rates as well, not only rates
++              ** defined with JOINBSS_RATES_BASIC111_nnn.
++              ** Just use RATE111_nnn constants... */
++              tmp.u.acx111.dtim_interval = dtim_interval;
++              tmp.u.acx111.rates_basic = cpu_to_le16(adev->rate_basic);
++              log(L_ASSOC, "rates_basic:%04X, rates_supported:%04X\n",
++                      adev->rate_basic, adev->rate_oper);
++      } else {
++              tmp.u.acx100.dtim_interval = dtim_interval;
++              tmp.u.acx100.rates_basic = rate111to5bits(adev->rate_basic);
++              tmp.u.acx100.rates_supported = rate111to5bits(adev->rate_oper);
++              log(L_ASSOC, "rates_basic:%04X->%02X, "
++                      "rates_supported:%04X->%02X\n",
++                      adev->rate_basic, tmp.u.acx100.rates_basic,
++                      adev->rate_oper, tmp.u.acx100.rates_supported);
++      }
++
++      /* Setting up how Beacon, Probe Response, RTS, and PS-Poll frames
++      ** will be sent (rate/modulation/preamble) */
++      tmp.u.txrate.genfrm_txrate = bitpos2genframe_txrate[lowest_bit(adev->rate_basic)];
++      tmp.genfrm_mod_pre = 0; /* FIXME: was = adev->capab_short (which was always 0); */
++      /* we can use short pre *if* all peers can understand it */
++      /* FIXME #2: we need to correctly set PBCC/OFDM bits here too */
++
++      /* we switch fw to STA mode in MONITOR mode, it seems to be
++      ** the only mode where fw does not emit beacons by itself
++      ** but allows us to send anything (we really want to retain
++      ** ability to tx arbitrary frames in MONITOR mode)
++      */
++      tmp.macmode = (adev->mode != ACX_MODE_MONITOR ? adev->mode : ACX_MODE_2_STA);
++      tmp.channel = adev->channel;
++      tmp.essid_len = adev->essid_len;
++      /* NOTE: the code memcpy'd essid_len + 1 before, which is WRONG! */
++      memcpy(tmp.essid, adev->essid, tmp.essid_len);
++      acx_s_issue_cmd(adev, ACX1xx_CMD_JOIN, &tmp, tmp.essid_len + 0x11);
++
++      log(L_ASSOC|L_DEBUG, "BSS_Type = %u\n", tmp.macmode);
++      acxlog_mac(L_ASSOC|L_DEBUG, "JoinBSSID MAC:", adev->bssid, "\n");
++
++      acx_update_capabilities(adev);
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++** acx_s_cmd_start_scan
++**
++** Issue scan command to the hardware
++**
++** unified function for both ACX111 and ACX100
++*/
++static void
++acx_s_scan_chan(acx_device_t *adev)
++{
++      union {
++              acx111_scan_t acx111;
++              acx100_scan_t acx100;
++      } s;
++
++      FN_ENTER;
++
++      memset(&s, 0, sizeof(s));
++
++      /* first common positions... */
++
++      s.acx111.count = cpu_to_le16(adev->scan_count);
++      s.acx111.rate = adev->scan_rate;
++      s.acx111.options = adev->scan_mode;
++      s.acx111.chan_duration = cpu_to_le16(adev->scan_duration);
++      s.acx111.max_probe_delay = cpu_to_le16(adev->scan_probe_delay);
++
++      /* ...then differences */
++
++      if (IS_ACX111(adev)) {
++              s.acx111.channel_list_select = 0; /* scan every allowed channel */
++              /*s.acx111.channel_list_select = 1;*/ /* scan given channels */
++              /*s.acx111.modulation = 0x40;*/ /* long preamble? OFDM? -> only for active scan */
++              s.acx111.modulation = 0;
++              /*s.acx111.channel_list[0] = 6;
++              s.acx111.channel_list[1] = 4;*/
++      } else {
++              s.acx100.start_chan = cpu_to_le16(1);
++              s.acx100.flags = cpu_to_le16(0x8000);
++      }
++
++      acx_s_issue_cmd(adev, ACX1xx_CMD_SCAN, &s, sizeof(s));
++      FN_EXIT0;
++}
++
++
++void
++acx_s_cmd_start_scan(acx_device_t *adev)
++{
++      /* time_before check is 'just in case' thing */
++      if (!(adev->irq_status & HOST_INT_SCAN_COMPLETE)
++       && time_before(jiffies, adev->scan_start + 10*HZ)
++      ) {
++              log(L_INIT, "start_scan: seems like previous scan "
++              "is still running. Not starting anew. Please report\n");
++              return;
++      }
++
++      log(L_INIT, "starting radio scan\n");
++      /* remember that fw is commanded to do scan */
++      adev->scan_start = jiffies;
++      CLEAR_BIT(adev->irq_status, HOST_INT_SCAN_COMPLETE);
++      /* issue it */
++      acx_s_scan_chan(adev);
++}
++
++
++/***********************************************************************
++** acx111 feature config
++*/
++static int
++acx111_s_get_feature_config(acx_device_t *adev,
++              u32 *feature_options, u32 *data_flow_options)
++{
++      struct acx111_ie_feature_config feat;
++
++      if (!IS_ACX111(adev)) {
++              return NOT_OK;
++      }
++
++      memset(&feat, 0, sizeof(feat));
++
++      if (OK != acx_s_interrogate(adev, &feat, ACX1xx_IE_FEATURE_CONFIG)) {
++              return NOT_OK;
++      }
++      log(L_DEBUG,
++              "got Feature option:0x%X, DataFlow option: 0x%X\n",
++              feat.feature_options,
++              feat.data_flow_options);
++
++      if (feature_options)
++              *feature_options = le32_to_cpu(feat.feature_options);
++      if (data_flow_options)
++              *data_flow_options = le32_to_cpu(feat.data_flow_options);
++
++      return OK;
++}
++
++static int
++acx111_s_set_feature_config(acx_device_t *adev,
++      u32 feature_options, u32 data_flow_options,
++      unsigned int mode /* 0 == remove, 1 == add, 2 == set */)
++{
++      struct acx111_ie_feature_config feat;
++
++      if (!IS_ACX111(adev)) {
++              return NOT_OK;
++      }
++
++      if ((mode < 0) || (mode > 2))
++              return NOT_OK;
++
++      if (mode != 2)
++              /* need to modify old data */
++              acx111_s_get_feature_config(adev, &feat.feature_options, &feat.data_flow_options);
++      else {
++              /* need to set a completely new value */
++              feat.feature_options = 0;
++              feat.data_flow_options = 0;
++      }
++
++      if (mode == 0) { /* remove */
++              CLEAR_BIT(feat.feature_options, cpu_to_le32(feature_options));
++              CLEAR_BIT(feat.data_flow_options, cpu_to_le32(data_flow_options));
++      } else { /* add or set */
++              SET_BIT(feat.feature_options, cpu_to_le32(feature_options));
++              SET_BIT(feat.data_flow_options, cpu_to_le32(data_flow_options));
++      }
++
++      log(L_DEBUG,
++              "old: feature 0x%08X dataflow 0x%08X. mode: %u\n"
++              "new: feature 0x%08X dataflow 0x%08X\n",
++              feature_options, data_flow_options, mode,
++              le32_to_cpu(feat.feature_options),
++              le32_to_cpu(feat.data_flow_options));
++
++      if (OK != acx_s_configure(adev, &feat, ACX1xx_IE_FEATURE_CONFIG)) {
++              return NOT_OK;
++      }
++
++      return OK;
++}
++
++static inline int
++acx111_s_feature_off(acx_device_t *adev, u32 f, u32 d)
++{
++      return acx111_s_set_feature_config(adev, f, d, 0);
++}
++static inline int
++acx111_s_feature_on(acx_device_t *adev, u32 f, u32 d)
++{
++      return acx111_s_set_feature_config(adev, f, d, 1);
++}
++static inline int
++acx111_s_feature_set(acx_device_t *adev, u32 f, u32 d)
++{
++      return acx111_s_set_feature_config(adev, f, d, 2);
++}
++
++
++/***********************************************************************
++** acx100_s_init_memory_pools
++*/
++static int
++acx100_s_init_memory_pools(acx_device_t *adev, const acx_ie_memmap_t *mmt)
++{
++      acx100_ie_memblocksize_t MemoryBlockSize;
++      acx100_ie_memconfigoption_t MemoryConfigOption;
++      int TotalMemoryBlocks;
++      int RxBlockNum;
++      int TotalRxBlockSize;
++      int TxBlockNum;
++      int TotalTxBlockSize;
++
++      FN_ENTER;
++
++      /* Let's see if we can follow this:
++         first we select our memory block size (which I think is
++         completely arbitrary) */
++      MemoryBlockSize.size = cpu_to_le16(adev->memblocksize);
++
++      /* Then we alert the card to our decision of block size */
++      if (OK != acx_s_configure(adev, &MemoryBlockSize, ACX100_IE_BLOCK_SIZE)) {
++              goto bad;
++      }
++
++      /* We figure out how many total blocks we can create, using
++         the block size we chose, and the beginning and ending
++         memory pointers, i.e.: end-start/size */
++      TotalMemoryBlocks = (le32_to_cpu(mmt->PoolEnd) - le32_to_cpu(mmt->PoolStart)) / adev->memblocksize;
++
++      log(L_DEBUG, "TotalMemoryBlocks=%u (%u bytes)\n",
++              TotalMemoryBlocks, TotalMemoryBlocks*adev->memblocksize);
++
++      /* MemoryConfigOption.DMA_config bitmask:
++                      access to ACX memory is to be done:
++      0x00080000      using PCI conf space?!
++      0x00040000      using IO instructions?
++      0x00000000      using memory access instructions
++      0x00020000      using local memory block linked list (else what?)
++      0x00010000      using host indirect descriptors (else host must access ACX memory?)
++      */
++#if defined (ACX_MEM)
++              /*
++               * ACX ignores DMA_config for generic slave mode.
++               */
++              MemoryConfigOption.DMA_config = 0;
++              /* Declare start of the Rx host pool */
++              MemoryConfigOption.pRxHostDesc = cpu2acx(0);
++              log(L_DEBUG, "pRxHostDesc 0x%08X, rxhostdesc_startphy 0x%lX\n",
++                              acx2cpu(MemoryConfigOption.pRxHostDesc),
++                              (long)adev->rxhostdesc_startphy);
++#else
++      if (IS_PCI(adev)) {
++              MemoryConfigOption.DMA_config = cpu_to_le32(0x30000);
++              /* Declare start of the Rx host pool */
++              MemoryConfigOption.pRxHostDesc = cpu2acx(adev->rxhostdesc_startphy);
++              log(L_DEBUG, "pRxHostDesc 0x%08X, rxhostdesc_startphy 0x%lX\n",
++                              acx2cpu(MemoryConfigOption.pRxHostDesc),
++                              (long)adev->rxhostdesc_startphy);
++      } else {
++              MemoryConfigOption.DMA_config = cpu_to_le32(0x20000);
++      }
++#endif
++
++      /* 50% of the allotment of memory blocks go to tx descriptors */
++      TxBlockNum = TotalMemoryBlocks / 2;
++      MemoryConfigOption.TxBlockNum = cpu_to_le16(TxBlockNum);
++
++      /* and 50% go to the rx descriptors */
++      RxBlockNum = TotalMemoryBlocks - TxBlockNum;
++      MemoryConfigOption.RxBlockNum = cpu_to_le16(RxBlockNum);
++
++      /* size of the tx and rx descriptor queues */
++      TotalTxBlockSize = TxBlockNum * adev->memblocksize;
++      TotalRxBlockSize = RxBlockNum * adev->memblocksize;
++      log(L_DEBUG, "TxBlockNum %u RxBlockNum %u TotalTxBlockSize %u "
++              "TotalTxBlockSize %u\n", TxBlockNum, RxBlockNum,
++              TotalTxBlockSize, TotalRxBlockSize);
++
++
++      /* align the tx descriptor queue to an alignment of 0x20 (32 bytes) */
++      MemoryConfigOption.rx_mem =
++              cpu_to_le32((le32_to_cpu(mmt->PoolStart) + 0x1f) & ~0x1f);
++
++      /* align the rx descriptor queue to units of 0x20
++       * and offset it by the tx descriptor queue */
++      MemoryConfigOption.tx_mem =
++              cpu_to_le32((le32_to_cpu(mmt->PoolStart) + TotalRxBlockSize + 0x1f) & ~0x1f);
++      log(L_DEBUG, "rx_mem %08X rx_mem %08X\n",
++              MemoryConfigOption.tx_mem, MemoryConfigOption.rx_mem);
++
++      /* alert the device to our decision */
++      if (OK != acx_s_configure(adev, &MemoryConfigOption, ACX1xx_IE_MEMORY_CONFIG_OPTIONS)) {
++              goto bad;
++      }
++
++      /* and tell the device to kick it into gear */
++      if (OK != acx_s_issue_cmd(adev, ACX100_CMD_INIT_MEMORY, NULL, 0)) {
++              goto bad;
++      }
++#ifdef ACX_MEM
++      /*
++       * slave memory interface has to manage the transmit pools for the ACX,
++       * so it needs to know what we chose here.
++       */
++      adev->acx_txbuf_start = MemoryConfigOption.tx_mem;
++      adev->acx_txbuf_numblocks = MemoryConfigOption.TxBlockNum;
++#endif
++
++      FN_EXIT1(OK);
++      return OK;
++bad:
++      FN_EXIT1(NOT_OK);
++      return NOT_OK;
++}
++
++
++/***********************************************************************
++** acx100_s_create_dma_regions
++**
++** Note that this fn messes up heavily with hardware, but we cannot
++** lock it (we need to sleep). Not a problem since IRQs can't happen
++*/
++static int
++acx100_s_create_dma_regions(acx_device_t *adev)
++{
++      acx100_ie_queueconfig_t queueconf;
++      acx_ie_memmap_t memmap;
++      int res = NOT_OK;
++      u32 tx_queue_start, rx_queue_start;
++
++      FN_ENTER;
++
++      /* read out the acx100 physical start address for the queues */
++      if (OK != acx_s_interrogate(adev, &memmap, ACX1xx_IE_MEMORY_MAP)) {
++              goto fail;
++      }
++
++      tx_queue_start = le32_to_cpu(memmap.QueueStart);
++      rx_queue_start = tx_queue_start + TX_CNT * sizeof(txdesc_t);
++
++      log(L_DEBUG, "initializing Queue Indicator\n");
++
++      memset(&queueconf, 0, sizeof(queueconf));
++
++      /* Not needed for PCI or slave memory, so we can avoid setting them altogether */
++      if (IS_USB(adev)) {
++              queueconf.NumTxDesc = USB_TX_CNT;
++              queueconf.NumRxDesc = USB_RX_CNT;
++      }
++
++      /* calculate size of queues */
++      queueconf.AreaSize = cpu_to_le32(
++                      TX_CNT * sizeof(txdesc_t) +
++                      RX_CNT * sizeof(rxdesc_t) + 8
++                      );
++      queueconf.NumTxQueues = 1;  /* number of tx queues */
++      /* sets the beginning of the tx descriptor queue */
++      queueconf.TxQueueStart = memmap.QueueStart;
++      /* done by memset: queueconf.TxQueuePri = 0; */
++      queueconf.RxQueueStart = cpu_to_le32(rx_queue_start);
++      queueconf.QueueOptions = 1;             /* auto reset descriptor */
++      /* sets the end of the rx descriptor queue */
++      queueconf.QueueEnd = cpu_to_le32(
++                      rx_queue_start + RX_CNT * sizeof(rxdesc_t)
++                      );
++      /* sets the beginning of the next queue */
++      queueconf.HostQueueEnd = cpu_to_le32(le32_to_cpu(queueconf.QueueEnd) + 8);
++      if (OK != acx_s_configure(adev, &queueconf, ACX1xx_IE_QUEUE_CONFIG)) {
++              goto fail;
++      }
++
++#if defined (ACX_MEM)
++      /* sets the beginning of the rx descriptor queue, after the tx descrs */
++              adev->acx_queue_indicator =
++                (queueindicator_t *) le32_to_cpu (queueconf.QueueEnd);
++              if (OK != acxmem_s_create_hostdesc_queues(adev))
++                      goto fail;
++
++              acxmem_create_desc_queues(adev, tx_queue_start, rx_queue_start);
++#else
++      if (IS_PCI(adev)) {
++      /* sets the beginning of the rx descriptor queue, after the tx descrs */
++              if (OK != acxpci_s_create_hostdesc_queues(adev))
++                      goto fail;
++              acxpci_create_desc_queues(adev, tx_queue_start, rx_queue_start);
++      }
++#endif
++
++      if (OK != acx_s_interrogate(adev, &memmap, ACX1xx_IE_MEMORY_MAP)) {
++              goto fail;
++      }
++
++      /*
++       * Have to make sure we skip past the Queue Indicator (QueueEnd) and Host Queue Indicator
++       * maps, each of which are 8 bytes and follow immediately after the transmit and
++       * receive queues.
++       */
++      memmap.PoolStart = cpu_to_le32(
++                      (le32_to_cpu(memmap.QueueEnd) + 4 + 0x1f) & ~0x1f
++                      );
++
++      if (OK != acx_s_configure(adev, &memmap, ACX1xx_IE_MEMORY_MAP)) {
++              goto fail;
++      }
++
++      if (OK != acx100_s_init_memory_pools(adev, &memmap)) {
++              goto fail;
++      }
++
++      res = OK;
++      goto end;
++
++fail:
++      acx_s_msleep(1000); /* ? */
++#if defined (ACX_MEM)
++              acxmem_free_desc_queues(adev);
++#else
++      if (IS_PCI(adev))
++              acxpci_free_desc_queues(adev);
++#endif
++end:
++      FN_EXIT1(res);
++      return res;
++}
++
++
++/***********************************************************************
++** acx111_s_create_dma_regions
++**
++** Note that this fn messes heavily with hardware, but we cannot
++** lock it (we need to sleep). Not a problem since IRQs can't happen
++*/
++#define ACX111_PERCENT(percent) ((percent)/5)
++
++static int
++acx111_s_create_dma_regions(acx_device_t *adev)
++{
++      struct acx111_ie_memoryconfig memconf;
++      struct acx111_ie_queueconfig queueconf;
++      u32 tx_queue_start, rx_queue_start;
++
++      FN_ENTER;
++
++      /* Calculate memory positions and queue sizes */
++
++      /* Set up our host descriptor pool + data pool */
++#if defined (ACX_MEM)
++              if (OK != acxmem_s_create_hostdesc_queues(adev))
++                      goto fail;
++#else
++      if (IS_PCI(adev)) {
++              if (OK != acxpci_s_create_hostdesc_queues(adev))
++                      goto fail;
++      }
++#endif
++
++      memset(&memconf, 0, sizeof(memconf));
++      /* the number of STAs (STA contexts) to support
++      ** NB: was set to 1 and everything seemed to work nevertheless... */
++      memconf.no_of_stations = cpu_to_le16(VEC_SIZE(adev->sta_list));
++      /* specify the memory block size. Default is 256 */
++      memconf.memory_block_size = cpu_to_le16(adev->memblocksize);
++      /* let's use 50%/50% for tx/rx (specify percentage, units of 5%) */
++      memconf.tx_rx_memory_block_allocation = ACX111_PERCENT(50);
++      /* set the count of our queues
++      ** NB: struct acx111_ie_memoryconfig shall be modified
++      ** if we ever will switch to more than one rx and/or tx queue */
++      memconf.count_rx_queues = 1;
++      memconf.count_tx_queues = 1;
++      /* 0 == Busmaster Indirect Memory Organization, which is what we want
++       * (using linked host descs with their allocated mem).
++       * 2 == Generic Bus Slave */
++      /* done by memset: memconf.options = 0; */
++      /* let's use 25% for fragmentations and 75% for frame transfers
++       * (specified in units of 5%) */
++      memconf.fragmentation = ACX111_PERCENT(75);
++      /* Rx descriptor queue config */
++      memconf.rx_queue1_count_descs = RX_CNT;
++      memconf.rx_queue1_type = 7; /* must be set to 7 */
++      /* done by memset: memconf.rx_queue1_prio = 0; low prio */
++#if defined (ACX_MEM)
++              memconf.rx_queue1_host_rx_start = cpu2acx(adev->rxhostdesc_startphy);
++#else
++      if (IS_PCI(adev)) {
++              memconf.rx_queue1_host_rx_start = cpu2acx(adev->rxhostdesc_startphy);
++      }
++#endif
++      /* Tx descriptor queue config */
++      memconf.tx_queue1_count_descs = TX_CNT;
++      /* done by memset: memconf.tx_queue1_attributes = 0; lowest priority */
++
++      /* NB1: this looks wrong: (memconf,ACX1xx_IE_QUEUE_CONFIG),
++      ** (queueconf,ACX1xx_IE_MEMORY_CONFIG_OPTIONS) look swapped, eh?
++      ** But it is actually correct wrt IE numbers.
++      ** NB2: sizeof(memconf) == 28 == 0x1c but configure(ACX1xx_IE_QUEUE_CONFIG)
++      ** writes 0x20 bytes (because same IE for acx100 uses struct acx100_ie_queueconfig
++      ** which is 4 bytes larger. what a mess. TODO: clean it up) */
++      if (OK != acx_s_configure(adev, &memconf, ACX1xx_IE_QUEUE_CONFIG)) {
++              goto fail;
++      }
++
++      acx_s_interrogate(adev, &queueconf, ACX1xx_IE_MEMORY_CONFIG_OPTIONS);
++
++      tx_queue_start = le32_to_cpu(queueconf.tx1_queue_address);
++      rx_queue_start = le32_to_cpu(queueconf.rx1_queue_address);
++
++      log(L_INIT, "dump queue head (from card):\n"
++                     "len: %u\n"
++                     "tx_memory_block_address: %X\n"
++                     "rx_memory_block_address: %X\n"
++                     "tx1_queue address: %X\n"
++                     "rx1_queue address: %X\n",
++                              le16_to_cpu(queueconf.len),
++                              le32_to_cpu(queueconf.tx_memory_block_address),
++                              le32_to_cpu(queueconf.rx_memory_block_address),
++                              tx_queue_start,
++                              rx_queue_start);
++
++#if defined (ACX_MEM)
++              acxmem_create_desc_queues(adev, tx_queue_start, rx_queue_start);
++#else
++      if (IS_PCI(adev))
++              acxpci_create_desc_queues(adev, tx_queue_start, rx_queue_start);
++#endif
++
++      FN_EXIT1(OK);
++      return OK;
++fail:
++#if defined (ACX_MEM)
++              acxmem_free_desc_queues(adev);
++#else
++      if (IS_PCI(adev))
++              acxpci_free_desc_queues(adev);
++#endif
++
++      FN_EXIT1(NOT_OK);
++      return NOT_OK;
++}
++
++
++/***********************************************************************
++*/
++static void
++acx_s_initialize_rx_config(acx_device_t *adev)
++{
++      struct {
++              u16     id;
++              u16     len;
++              u16     rx_cfg1;
++              u16     rx_cfg2;
++      } ACX_PACKED cfg;
++
++      switch (adev->mode) {
++      case ACX_MODE_OFF:
++              adev->rx_config_1 = (u16) (0
++                      /* | RX_CFG1_INCLUDE_RXBUF_HDR  */
++                      /* | RX_CFG1_FILTER_SSID        */
++                      /* | RX_CFG1_FILTER_BCAST       */
++                      /* | RX_CFG1_RCV_MC_ADDR1       */
++                      /* | RX_CFG1_RCV_MC_ADDR0       */
++                      /* | RX_CFG1_FILTER_ALL_MULTI   */
++                      /* | RX_CFG1_FILTER_BSSID       */
++                      /* | RX_CFG1_FILTER_MAC         */
++                      /* | RX_CFG1_RCV_PROMISCUOUS    */
++                      /* | RX_CFG1_INCLUDE_FCS        */
++                      /* | RX_CFG1_INCLUDE_PHY_HDR    */
++                      );
++              adev->rx_config_2 = (u16) (0
++                      /*| RX_CFG2_RCV_ASSOC_REQ       */
++                      /*| RX_CFG2_RCV_AUTH_FRAMES     */
++                      /*| RX_CFG2_RCV_BEACON_FRAMES   */
++                      /*| RX_CFG2_RCV_CONTENTION_FREE */
++                      /*| RX_CFG2_RCV_CTRL_FRAMES     */
++                      /*| RX_CFG2_RCV_DATA_FRAMES     */
++                      /*| RX_CFG2_RCV_BROKEN_FRAMES   */
++                      /*| RX_CFG2_RCV_MGMT_FRAMES     */
++                      /*| RX_CFG2_RCV_PROBE_REQ       */
++                      /*| RX_CFG2_RCV_PROBE_RESP      */
++                      /*| RX_CFG2_RCV_ACK_FRAMES      */
++                      /*| RX_CFG2_RCV_OTHER           */
++                      );
++              break;
++      case ACX_MODE_MONITOR:
++              adev->rx_config_1 = (u16) (0
++                      /* | RX_CFG1_INCLUDE_RXBUF_HDR  */
++                      /* | RX_CFG1_FILTER_SSID        */
++                      /* | RX_CFG1_FILTER_BCAST       */
++                      /* | RX_CFG1_RCV_MC_ADDR1       */
++                      /* | RX_CFG1_RCV_MC_ADDR0       */
++                      /* | RX_CFG1_FILTER_ALL_MULTI   */
++                      /* | RX_CFG1_FILTER_BSSID       */
++                      /* | RX_CFG1_FILTER_MAC         */
++                      | RX_CFG1_RCV_PROMISCUOUS
++                      /* | RX_CFG1_INCLUDE_FCS        */
++                      /* | RX_CFG1_INCLUDE_PHY_HDR    */
++                      );
++              adev->rx_config_2 = (u16) (0
++                      | RX_CFG2_RCV_ASSOC_REQ
++                      | RX_CFG2_RCV_AUTH_FRAMES
++                      | RX_CFG2_RCV_BEACON_FRAMES
++                      | RX_CFG2_RCV_CONTENTION_FREE
++                      | RX_CFG2_RCV_CTRL_FRAMES
++                      | RX_CFG2_RCV_DATA_FRAMES
++                      | RX_CFG2_RCV_BROKEN_FRAMES
++                      | RX_CFG2_RCV_MGMT_FRAMES
++                      | RX_CFG2_RCV_PROBE_REQ
++                      | RX_CFG2_RCV_PROBE_RESP
++                      | RX_CFG2_RCV_ACK_FRAMES
++                      | RX_CFG2_RCV_OTHER
++                      );
++              break;
++      default:
++              adev->rx_config_1 = (u16) (0
++                      /* | RX_CFG1_INCLUDE_RXBUF_HDR  */
++                      /* | RX_CFG1_FILTER_SSID        */
++                      /* | RX_CFG1_FILTER_BCAST       */
++                      /* | RX_CFG1_RCV_MC_ADDR1       */
++                      /* | RX_CFG1_RCV_MC_ADDR0       */
++                      /* | RX_CFG1_FILTER_ALL_MULTI   */
++                      /* | RX_CFG1_FILTER_BSSID       */
++                      | RX_CFG1_FILTER_MAC
++                      /* | RX_CFG1_RCV_PROMISCUOUS    */
++                      /* | RX_CFG1_INCLUDE_FCS        */
++                      /* | RX_CFG1_INCLUDE_PHY_HDR    */
++                      );
++              adev->rx_config_2 = (u16) (0
++                      | RX_CFG2_RCV_ASSOC_REQ
++                      | RX_CFG2_RCV_AUTH_FRAMES
++                      | RX_CFG2_RCV_BEACON_FRAMES
++                      | RX_CFG2_RCV_CONTENTION_FREE
++                      | RX_CFG2_RCV_CTRL_FRAMES
++                      | RX_CFG2_RCV_DATA_FRAMES
++                      /*| RX_CFG2_RCV_BROKEN_FRAMES   */
++                      | RX_CFG2_RCV_MGMT_FRAMES
++                      | RX_CFG2_RCV_PROBE_REQ
++                      | RX_CFG2_RCV_PROBE_RESP
++                      /*| RX_CFG2_RCV_ACK_FRAMES      */
++                      | RX_CFG2_RCV_OTHER
++                      );
++              break;
++      }
++      adev->rx_config_1 |= RX_CFG1_INCLUDE_RXBUF_HDR;
++
++      if ((adev->rx_config_1 & RX_CFG1_INCLUDE_PHY_HDR)
++       || (adev->firmware_numver >= 0x02000000))
++              adev->phy_header_len = IS_ACX111(adev) ? 8 : 4;
++      else
++              adev->phy_header_len = 0;
++
++      log(L_INIT, "setting RXconfig to %04X:%04X\n",
++                      adev->rx_config_1, adev->rx_config_2);
++      cfg.rx_cfg1 = cpu_to_le16(adev->rx_config_1);
++      cfg.rx_cfg2 = cpu_to_le16(adev->rx_config_2);
++      acx_s_configure(adev, &cfg, ACX1xx_IE_RXCONFIG);
++}
++
++
++/***********************************************************************
++** acx_s_set_defaults
++*/
++void
++acx_s_set_defaults(acx_device_t *adev)
++{
++      unsigned long flags;
++
++      FN_ENTER;
++
++      /* do it before getting settings, prevent bogus channel 0 warning */
++      adev->channel = 1;
++
++      /* query some settings from the card.
++       * NOTE: for some settings, e.g. CCA and ED (ACX100!), an initial
++       * query is REQUIRED, otherwise the card won't work correctly! */
++      adev->get_mask = GETSET_ANTENNA|GETSET_SENSITIVITY|GETSET_STATION_ID|GETSET_REG_DOMAIN;
++      /* Only ACX100 supports ED and CCA */
++      if (IS_ACX100(adev))
++              adev->get_mask |= GETSET_CCA|GETSET_ED_THRESH;
++
++      acx_s_update_card_settings(adev);
++
++      acx_lock(adev, flags);
++
++      /* set our global interrupt mask */
++#if defined (ACX_MEM)
++              acxmem_set_interrupt_mask(adev);
++#else
++      if (IS_PCI(adev))
++              acxpci_set_interrupt_mask(adev);
++#endif
++
++      adev->led_power = 1; /* LED is active on startup */
++      adev->brange_max_quality = 60; /* LED blink max quality is 60 */
++      adev->brange_time_last_state_change = jiffies;
++
++      /* copy the MAC address we just got from the card
++       * into our MAC address used during current 802.11 session */
++      MAC_COPY(adev->dev_addr, adev->ndev->dev_addr);
++      MAC_BCAST(adev->ap);
++
++      adev->essid_len =
++              snprintf(adev->essid, sizeof(adev->essid), "STA%02X%02X%02X",
++                      adev->dev_addr[3], adev->dev_addr[4], adev->dev_addr[5]);
++      adev->essid_active = 1;
++
++      /* we have a nick field to waste, so why not abuse it
++       * to announce the driver version? ;-) */
++      strncpy(adev->nick, "acx " ACX_RELEASE, IW_ESSID_MAX_SIZE);
++
++#if defined (ACX_MEM)
++              adev->reg_dom_id = adev->cfgopt_domains.list[0];
++#else
++      if (IS_PCI(adev)) { /* FIXME: this should be made to apply to USB, too! */
++              /* first regulatory domain entry in EEPROM == default reg. domain */
++              adev->reg_dom_id = adev->cfgopt_domains.list[0];
++      }
++#endif
++
++      /* 0xffff would be better, but then we won't get a "scan complete"
++       * interrupt, so our current infrastructure will fail: */
++      adev->scan_count = 1;
++      adev->scan_mode = ACX_SCAN_OPT_ACTIVE;
++      adev->scan_duration = 100;
++      adev->scan_probe_delay = 200;
++      /* reported to break scanning: adev->scan_probe_delay = adev->cfgopt_probe_delay; */
++      adev->scan_rate = ACX_SCAN_RATE_1;
++
++      adev->mode = ACX_MODE_2_STA;
++      adev->auth_alg = WLAN_AUTH_ALG_OPENSYSTEM;
++      adev->listen_interval = 100;
++      adev->beacon_interval = DEFAULT_BEACON_INTERVAL;
++      adev->dtim_interval = DEFAULT_DTIM_INTERVAL;
++
++      adev->msdu_lifetime = DEFAULT_MSDU_LIFETIME;
++
++      adev->rts_threshold = DEFAULT_RTS_THRESHOLD;
++      adev->frag_threshold = 2346;
++
++      /* use standard default values for retry limits */
++      adev->short_retry = 7; /* max. retries for (short) non-RTS packets */
++      adev->long_retry = 4; /* max. retries for long (RTS) packets */
++
++      adev->preamble_mode = 2; /* auto */
++      adev->fallback_threshold = 3;
++      adev->stepup_threshold = 10;
++      adev->rate_bcast = RATE111_1;
++      adev->rate_bcast100 = RATE100_1;
++      adev->rate_basic = RATE111_1 | RATE111_2;
++      adev->rate_auto = 1;
++      if (IS_ACX111(adev)) {
++              adev->rate_oper = RATE111_ALL;
++      } else {
++              adev->rate_oper = RATE111_ACX100_COMPAT;
++      }
++
++      /* Supported Rates element - the rates here are given in units of
++       * 500 kbit/s, plus 0x80 added. See 802.11-1999.pdf item 7.3.2.2 */
++      acx_l_update_ratevector(adev);
++
++      /* set some more defaults */
++      if (IS_ACX111(adev)) {
++              /* 30mW (15dBm) is default, at least in my acx111 card: */
++              adev->tx_level_dbm = 15;
++      } else {
++              /* don't use max. level, since it might be dangerous
++               * (e.g. WRT54G people experience
++               * excessive Tx power damage!) */
++              adev->tx_level_dbm = 18;
++              /*
++               * Lower power for the iPaq hx4700
++               */
++              if (IS_MEM(adev)) {
++                      adev->tx_level_dbm = 14;
++              }
++      }
++      /* adev->tx_level_auto = 1; */
++      if (IS_ACX111(adev)) {
++              /* start with sensitivity level 1 out of 3: */
++              adev->sensitivity = 1;
++      }
++
++/* #define ENABLE_POWER_SAVE */
++#ifdef ENABLE_POWER_SAVE
++      adev->ps_wakeup_cfg = PS_CFG_ENABLE | PS_CFG_WAKEUP_ALL_BEAC;
++      adev->ps_listen_interval = 1;
++      adev->ps_options = PS_OPT_ENA_ENHANCED_PS | PS_OPT_TX_PSPOLL | PS_OPT_STILL_RCV_BCASTS;
++      adev->ps_hangover_period = 30;
++      adev->ps_enhanced_transition_time = 0;
++#else
++      adev->ps_wakeup_cfg = 0;
++      adev->ps_listen_interval = 0;
++      adev->ps_options = 0;
++      adev->ps_hangover_period = 0;
++      adev->ps_enhanced_transition_time = 0;
++#endif
++
++      /* These settings will be set in fw on ifup */
++      adev->set_mask = 0
++              | GETSET_RETRY
++              | SET_MSDU_LIFETIME
++      /* configure card to do rate fallback when in auto rate mode */
++              | SET_RATE_FALLBACK
++              | SET_RXCONFIG
++              | GETSET_TXPOWER
++      /* better re-init the antenna value we got above */
++              | GETSET_ANTENNA
++#if POWER_SAVE_80211
++              | GETSET_POWER_80211
++#endif
++              ;
++
++      acx_unlock(adev, flags);
++      acx_lock_unhold(); /* hold time 844814 CPU ticks @2GHz */
++
++      acx_s_initialize_rx_config(adev);
++
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++** FIXME: this should be solved in a general way for all radio types
++** by decoding the radio firmware module,
++** since it probably has some standard structure describing how to
++** set the power level of the radio module which it controls.
++** Or maybe not, since the radio module probably has a function interface
++** instead which then manages Tx level programming :-\
++*/
++static int
++acx111_s_set_tx_level(acx_device_t *adev, u8 level_dbm)
++{
++      struct acx111_ie_tx_level tx_level;
++
++      /* my acx111 card has two power levels in its configoptions (== EEPROM):
++       * 1 (30mW) [15dBm]
++       * 2 (10mW) [10dBm]
++       * For now, just assume all other acx111 cards have the same.
++       * FIXME: Ideally we would query it here, but we first need a
++       * standard way to query individual configoptions easily.
++       * Well, now we have proper cfgopt txpower variables, but this still
++       * hasn't been done yet, since it also requires dBm <-> mW conversion here... */
++      if (level_dbm <= 12) {
++              tx_level.level = 2; /* 10 dBm */
++              adev->tx_level_dbm = 10;
++      } else {
++              tx_level.level = 1; /* 15 dBm */
++              adev->tx_level_dbm = 15;
++      }
++      if (level_dbm != adev->tx_level_dbm)
++              log(L_INIT, "acx111 firmware has specific "
++                      "power levels only: adjusted %d dBm to %d dBm!\n",
++                      level_dbm, adev->tx_level_dbm);
++
++      return acx_s_configure(adev, &tx_level, ACX1xx_IE_DOT11_TX_POWER_LEVEL);
++}
++
++static int
++acx_s_set_tx_level(acx_device_t *adev, u8 level_dbm)
++{
++      if (IS_ACX111(adev)) {
++              return acx111_s_set_tx_level(adev, level_dbm);
++      }
++#if defined (ACX_MEM)
++              return acx100mem_s_set_tx_level(adev, level_dbm);
++#else
++      if (IS_PCI(adev)) {
++              return acx100pci_s_set_tx_level(adev, level_dbm);
++      }
++#endif
++      return OK;
++}
++
++
++/***********************************************************************
++*/
++#ifdef UNUSED
++/* Returns the current tx level (ACX111) */
++static u8
++acx111_s_get_tx_level(acx_device_t *adev)
++{
++      struct acx111_ie_tx_level tx_level;
++
++      tx_level.level = 0;
++      acx_s_interrogate(adev, &tx_level, ACX1xx_IE_DOT11_TX_POWER_LEVEL);
++      return tx_level.level;
++}
++#endif
++
++
++/***********************************************************************
++** acx_l_rxmonitor
++** Called from IRQ context only
++*/
++static void
++acx_l_rxmonitor(acx_device_t *adev, const rxbuffer_t *rxbuf)
++{
++      wlansniffrm_t *msg;
++      struct sk_buff *skb;
++      void *datap;
++      unsigned int skb_len;
++      int payload_offset;
++
++      FN_ENTER;
++
++      /* we are in big luck: the acx100 doesn't modify any of the fields */
++      /* in the 802.11 frame. just pass this packet into the PF_PACKET */
++      /* subsystem. yeah. */
++      payload_offset = ((u8*)acx_get_wlan_hdr(adev, rxbuf) - (u8*)rxbuf);
++      skb_len = RXBUF_BYTES_USED(rxbuf) - payload_offset;
++
++      /* sanity check */
++      if (unlikely(skb_len > WLAN_A4FR_MAXLEN_WEP)) {
++              printk("%s: monitor mode panic: oversized frame!\n",
++                              adev->ndev->name);
++              goto end;
++      }
++
++      if (adev->ndev->type == ARPHRD_IEEE80211_PRISM)
++              skb_len += sizeof(*msg);
++
++      /* allocate skb */
++      skb = dev_alloc_skb(skb_len);
++      if (unlikely(!skb)) {
++              printk("%s: no memory for skb (%u bytes)\n",
++                              adev->ndev->name, skb_len);
++              goto end;
++      }
++
++      skb_put(skb, skb_len);
++
++      if (adev->ndev->type == ARPHRD_IEEE80211) {
++              /* when in raw 802.11 mode, just copy frame as-is */
++              datap = skb->data;
++      } else if (adev->ndev->type == ARPHRD_IEEE80211_PRISM) {
++              /* emulate prism header */
++              msg = (wlansniffrm_t*)skb->data;
++              datap = msg + 1;
++
++              msg->msgcode = WLANSNIFFFRM;
++              msg->msglen = sizeof(*msg);
++              strncpy(msg->devname, adev->ndev->name, sizeof(msg->devname)-1);
++              msg->devname[sizeof(msg->devname)-1] = '\0';
++
++              msg->hosttime.did = WLANSNIFFFRM_hosttime;
++              msg->hosttime.status = WLANITEM_STATUS_data_ok;
++              msg->hosttime.len = 4;
++              msg->hosttime.data = jiffies;
++
++              msg->mactime.did = WLANSNIFFFRM_mactime;
++              msg->mactime.status = WLANITEM_STATUS_data_ok;
++              msg->mactime.len = 4;
++              msg->mactime.data = rxbuf->time;
++
++              msg->channel.did = WLANSNIFFFRM_channel;
++              msg->channel.status = WLANITEM_STATUS_data_ok;
++              msg->channel.len = 4;
++              msg->channel.data = adev->channel;
++
++              msg->rssi.did = WLANSNIFFFRM_rssi;
++              msg->rssi.status = WLANITEM_STATUS_no_value;
++              msg->rssi.len = 4;
++              msg->rssi.data = 0;
++
++              msg->sq.did = WLANSNIFFFRM_sq;
++              msg->sq.status = WLANITEM_STATUS_no_value;
++              msg->sq.len = 4;
++              msg->sq.data = 0;
++
++              msg->signal.did = WLANSNIFFFRM_signal;
++              msg->signal.status = WLANITEM_STATUS_data_ok;
++              msg->signal.len = 4;
++              msg->signal.data = rxbuf->phy_snr;
++
++              msg->noise.did = WLANSNIFFFRM_noise;
++              msg->noise.status = WLANITEM_STATUS_data_ok;
++              msg->noise.len = 4;
++              msg->noise.data = rxbuf->phy_level;
++
++              msg->rate.did = WLANSNIFFFRM_rate;
++              msg->rate.status = WLANITEM_STATUS_data_ok;
++              msg->rate.len = 4;
++              msg->rate.data = rxbuf->phy_plcp_signal / 5;
++
++              msg->istx.did = WLANSNIFFFRM_istx;
++              msg->istx.status = WLANITEM_STATUS_data_ok;
++              msg->istx.len = 4;
++              msg->istx.data = 0;     /* tx=0: it's not a tx packet */
++
++              skb_len -= sizeof(*msg);
++
++              msg->frmlen.did = WLANSNIFFFRM_signal;
++              msg->frmlen.status = WLANITEM_STATUS_data_ok;
++              msg->frmlen.len = 4;
++              msg->frmlen.data = skb_len;
++      } else {
++              printk("acx: unsupported netdev type %d!\n", adev->ndev->type);
++              dev_kfree_skb(skb);
++              return;
++      }
++
++      /* sanity check (keep it here) */
++      if (unlikely((int)skb_len < 0)) {
++              printk("acx: skb_len=%d. Driver bug, please report\n", (int)skb_len);
++              dev_kfree_skb(skb);
++              return;
++      }
++      memcpy(datap, ((unsigned char*)rxbuf)+payload_offset, skb_len);
++
++      skb->dev = adev->ndev;
++      skb->dev->last_rx = jiffies;
++
++      skb_reset_mac_header(skb);
++      skb->ip_summed = CHECKSUM_NONE;
++      skb->pkt_type = PACKET_OTHERHOST;
++      skb->protocol = htons(ETH_P_80211_RAW);
++      netif_rx(skb);
++
++      adev->stats.rx_packets++;
++      adev->stats.rx_bytes += skb->len;
++
++end:
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++** acx_l_rx_ieee802_11_frame
++**
++** Called from IRQ context only
++*/
++
++/* All these contortions are for saner dup logging
++**
++** We want: (a) to know about excessive dups
++** (b) to not spam kernel log about occasional dups
++**
++** 1/64 threshold was chosen by running "ping -A"
++** It gave "rx: 59 DUPs in 2878 packets" only with 4 parallel
++** "ping -A" streams running. */
++/* 2005-10-11: bumped up to 1/8
++** subtract a $smallint from dup_count in order to
++** avoid "2 DUPs in 19 packets" messages */
++static inline int
++acx_l_handle_dup(acx_device_t *adev, u16 seq)
++{
++      if (adev->dup_count) {
++              adev->nondup_count++;
++              if (time_after(jiffies, adev->dup_msg_expiry)) {
++                      /* Log only if more than 1 dup in 64 packets */
++                      if (adev->nondup_count/8 < adev->dup_count-5) {
++                              printk(KERN_INFO "%s: rx: %d DUPs in "
++                                      "%d packets received in 10 secs\n",
++                                      adev->ndev->name,
++                                      adev->dup_count,
++                                      adev->nondup_count);
++                      }
++                      adev->dup_count = 0;
++                      adev->nondup_count = 0;
++              }
++      }
++      if (unlikely(seq == adev->last_seq_ctrl)) {
++              if (!adev->dup_count++)
++                      adev->dup_msg_expiry = jiffies + 10*HZ;
++              adev->stats.rx_errors++;
++              return 1; /* a dup */
++      }
++      adev->last_seq_ctrl = seq;
++      return 0;
++}
++
++static int
++acx_l_rx_ieee802_11_frame(acx_device_t *adev, rxbuffer_t *rxbuf)
++{
++      unsigned int ftype, fstype;
++      const wlan_hdr_t *hdr;
++      int result = NOT_OK;
++
++      FN_ENTER;
++
++      hdr = acx_get_wlan_hdr(adev, rxbuf);
++
++      /* see IEEE 802.11-1999.pdf chapter 7 "MAC frame formats" */
++      if (unlikely((hdr->fc & WF_FC_PVERi) != 0)) {
++              printk_ratelimited(KERN_INFO "rx: unsupported 802.11 protocol\n");
++              goto end;
++      }
++
++      ftype = hdr->fc & WF_FC_FTYPEi;
++      fstype = hdr->fc & WF_FC_FSTYPEi;
++
++      switch (ftype) {
++      /* check data frames first, for speed */
++      case WF_FTYPE_DATAi:
++              switch (fstype) {
++              case WF_FSTYPE_DATAONLYi:
++                      if (acx_l_handle_dup(adev, hdr->seq))
++                              break; /* a dup, simply discard it */
++
++                      /* TODO:
++                      if (WF_FC_FROMTODSi == (hdr->fc & WF_FC_FROMTODSi)) {
++                              result = acx_l_process_data_frame_wds(adev, rxbuf);
++                              break;
++                      }
++                      */
++
++                      switch (adev->mode) {
++                      case ACX_MODE_3_AP:
++                              result = acx_l_process_data_frame_master(adev, rxbuf);
++                              break;
++                      case ACX_MODE_0_ADHOC:
++                      case ACX_MODE_2_STA:
++                              result = acx_l_process_data_frame_client(adev, rxbuf);
++                              break;
++                      }
++              case WF_FSTYPE_DATA_CFACKi:
++              case WF_FSTYPE_DATA_CFPOLLi:
++              case WF_FSTYPE_DATA_CFACK_CFPOLLi:
++              case WF_FSTYPE_CFPOLLi:
++              case WF_FSTYPE_CFACK_CFPOLLi:
++              /*   see above.
++                      acx_process_class_frame(adev, rxbuf, 3); */
++                      break;
++              case WF_FSTYPE_NULLi:
++                      /* acx_l_process_NULL_frame(adev, rxbuf, 3); */
++                      break;
++              /* FIXME: same here, see above */
++              case WF_FSTYPE_CFACKi:
++              default:
++                      break;
++              }
++              break;
++      case WF_FTYPE_MGMTi:
++              result = acx_l_process_mgmt_frame(adev, rxbuf);
++              break;
++      case WF_FTYPE_CTLi:
++              if (fstype == WF_FSTYPE_PSPOLLi)
++                      result = OK;
++              /*   this call is irrelevant, since
++               *   acx_process_class_frame is a stub, so return
++               *   immediately instead.
++               * return acx_process_class_frame(adev, rxbuf, 3); */
++              break;
++      default:
++              break;
++      }
++end:
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/***********************************************************************
++** acx_l_process_rxbuf
++**
++** NB: used by USB code also
++*/
++void
++acx_l_process_rxbuf(acx_device_t *adev, rxbuffer_t *rxbuf)
++{
++      struct wlan_hdr *hdr;
++      unsigned int qual;
++      int buf_len;
++      u16 fc;
++
++      hdr = acx_get_wlan_hdr(adev, rxbuf);
++      fc = le16_to_cpu(hdr->fc);
++      /* length of frame from control field to first byte of FCS */
++      buf_len = RXBUF_BYTES_RCVD(adev, rxbuf);
++
++      if ( ((WF_FC_FSTYPE & fc) != WF_FSTYPE_BEACON)
++        || (acx_debug & L_XFER_BEACON)
++      ) {
++              log(L_XFER|L_DATA, "rx: %s "
++                      "time:%u len:%u signal:%u SNR:%u macstat:%02X "
++                      "phystat:%02X phyrate:%u status:%u\n",
++                      acx_get_packet_type_string(fc),
++                      le32_to_cpu(rxbuf->time),
++                      buf_len,
++                      acx_signal_to_winlevel(rxbuf->phy_level),
++                      acx_signal_to_winlevel(rxbuf->phy_snr),
++                      rxbuf->mac_status,
++                      rxbuf->phy_stat_baseband,
++                      rxbuf->phy_plcp_signal,
++                      adev->status);
++      }
++
++      if (unlikely(acx_debug & L_DATA)) {
++              printk("rx: 802.11 buf[%u]: ", buf_len);
++              acx_dump_bytes(hdr, buf_len);
++      }
++
++      /* FIXME: should check for Rx errors (rxbuf->mac_status?
++       * discard broken packets - but NOT for monitor!)
++       * and update Rx packet statistics here */
++
++      if (unlikely(adev->mode == ACX_MODE_MONITOR)) {
++              acx_l_rxmonitor(adev, rxbuf);
++      } else if (likely(buf_len >= WLAN_HDR_A3_LEN)) {
++              acx_l_rx_ieee802_11_frame(adev, rxbuf);
++      } else {
++              log(L_DEBUG|L_XFER|L_DATA,
++                     "rx: NOT receiving packet (%s): "
++                     "size too small (%u)\n",
++                     acx_get_packet_type_string(fc),
++                     buf_len);
++      }
++
++      /* Now check Rx quality level, AFTER processing packet.
++       * I tried to figure out how to map these levels to dBm
++       * values, but for the life of me I really didn't
++       * manage to get it. Either these values are not meant to
++       * be expressed in dBm, or it's some pretty complicated
++       * calculation. */
++
++#ifdef FROM_SCAN_SOURCE_ONLY
++      /* only consider packets originating from the MAC
++       * address of the device that's managing our BSSID.
++       * Disable it for now, since it removes information (levels
++       * from different peers) and slows the Rx path. */
++      if (adev->ap_client
++       && mac_is_equal(hdr->a2, adev->ap_client->address)) {
++#endif
++              adev->wstats.qual.level = acx_signal_to_winlevel(rxbuf->phy_level);
++              adev->wstats.qual.noise = acx_signal_to_winlevel(rxbuf->phy_snr);
++#ifndef OLD_QUALITY
++              qual = acx_signal_determine_quality(adev->wstats.qual.level,
++                              adev->wstats.qual.noise);
++#else
++              qual = (adev->wstats.qual.noise <= 100) ?
++                              100 - adev->wstats.qual.noise : 0;
++#endif
++              adev->wstats.qual.qual = qual;
++              adev->wstats.qual.updated = 7; /* all 3 indicators updated */
++#ifdef FROM_SCAN_SOURCE_ONLY
++      }
++#endif
++}
++
++
++/***********************************************************************
++** acx_l_handle_txrate_auto
++**
++** Theory of operation:
++** client->rate_cap is a bitmask of rates client is capable of.
++** client->rate_cfg is a bitmask of allowed (configured) rates.
++** It is set as a result of iwconfig rate N [auto]
++** or iwpriv set_rates "N,N,N N,N,N" commands.
++** It can be fixed (e.g. 0x0080 == 18Mbit only),
++** auto (0x00ff == 18Mbit or any lower value),
++** and code handles any bitmask (0x1081 == try 54Mbit,18Mbit,1Mbit _only_).
++**
++** client->rate_cur is a value for rate111 field in tx descriptor.
++** It is always set to txrate_cfg sans zero or more most significant
++** bits. This routine handles selection of new rate_cur value depending on
++** outcome of last tx event.
++**
++** client->rate_100 is a precalculated rate value for acx100
++** (we can do without it, but will need to calculate it on each tx).
++**
++** You cannot configure mixed usage of 5.5 and/or 11Mbit rate
++** with PBCC and CCK modulation. Either both at CCK or both at PBCC.
++** In theory you can implement it, but so far it is considered not worth doing.
++**
++** 22Mbit, of course, is PBCC always. */
++
++/* maps acx100 tx descr rate field to acx111 one */
++static u16
++rate100to111(u8 r)
++{
++      switch (r) {
++      case RATE100_1: return RATE111_1;
++      case RATE100_2: return RATE111_2;
++      case RATE100_5:
++      case (RATE100_5 | RATE100_PBCC511):     return RATE111_5;
++      case RATE100_11:
++      case (RATE100_11 | RATE100_PBCC511):    return RATE111_11;
++      case RATE100_22:        return RATE111_22;
++      default:
++              printk("acx: unexpected acx100 txrate: %u! "
++                      "Please report\n", r);
++              return RATE111_1;
++      }
++}
++
++
++void
++acx_l_handle_txrate_auto(acx_device_t *adev, struct client *txc,
++                      u16 cur, u8 rate100, u16 rate111,
++                      u8 error, int pkts_to_ignore)
++{
++      u16 sent_rate;
++      int slower_rate_was_used;
++
++      /* vda: hmm. current code will do this:
++      ** 1. send packets at 11 Mbit, stepup++
++      ** 2. will try to send at 22Mbit. hardware will see no ACK,
++      **    retries at 11Mbit, success. code notes that used rate
++      **    is lower. stepup = 0, fallback++
++      ** 3. repeat step 2 fallback_count times. Fall back to
++      **    11Mbit. go to step 1.
++      ** If stepup_count is large (say, 16) and fallback_count
++      ** is small (3), this wouldn't be too bad wrt throughput */
++
++      if (unlikely(!cur)) {
++              printk("acx: BUG! ratemask is empty\n");
++              return; /* or else we may lock up the box */
++      }
++
++      /* do some preparations, i.e. calculate the one rate that was
++       * used to send this packet */
++      if (IS_ACX111(adev)) {
++              sent_rate = 1 << highest_bit(rate111 & RATE111_ALL);
++      } else {
++              sent_rate = rate100to111(rate100);
++      }
++      /* sent_rate has only one bit set now, corresponding to tx rate
++       * which was used by hardware to tx this particular packet */
++
++      /* now do the actual auto rate management */
++      log(L_XFER, "tx: %sclient=%p/"MACSTR" used=%04X cur=%04X cfg=%04X "
++              "__=%u/%u ^^=%u/%u\n",
++              (txc->ignore_count > 0) ? "[IGN] " : "",
++              txc, MAC(txc->address), sent_rate, cur, txc->rate_cfg,
++              txc->fallback_count, adev->fallback_threshold,
++              txc->stepup_count, adev->stepup_threshold
++      );
++
++      /* we need to ignore old packets already in the tx queue since
++       * they use older rate bytes configured before our last rate change,
++       * otherwise our mechanism will get confused by interpreting old data.
++       * Do it after logging above */
++      if (txc->ignore_count) {
++              txc->ignore_count--;
++              return;
++      }
++
++      /* true only if the only nonzero bit in sent_rate is
++      ** less significant than highest nonzero bit in cur */
++      slower_rate_was_used = ( cur > ((sent_rate<<1)-1) );
++
++      if (slower_rate_was_used || error) {
++              txc->stepup_count = 0;
++              if (++txc->fallback_count <= adev->fallback_threshold)
++                      return;
++              txc->fallback_count = 0;
++
++              /* clear highest 1 bit in cur */
++              sent_rate = RATE111_54;
++              while (!(cur & sent_rate)) sent_rate >>= 1;
++              CLEAR_BIT(cur, sent_rate);
++              if (!cur) /* we can't disable all rates! */
++                      cur = sent_rate;
++              log(L_XFER, "tx: falling back to ratemask %04X\n", cur);
++
++      } else { /* there was neither lower rate nor error */
++              txc->fallback_count = 0;
++              if (++txc->stepup_count <= adev->stepup_threshold)
++                      return;
++              txc->stepup_count = 0;
++
++              /* Sanitize. Sort of not needed, but I dont trust hw that much...
++              ** what if it can report bogus tx rates sometimes? */
++              while (!(cur & sent_rate)) sent_rate >>= 1;
++
++              /* try to find a higher sent_rate that isn't yet in our
++               * current set, but is an allowed cfg */
++              while (1) {
++                      sent_rate <<= 1;
++                      if (sent_rate > txc->rate_cfg)
++                              /* no higher rates allowed by config */
++                              return;
++                      if (!(cur & sent_rate) && (txc->rate_cfg & sent_rate))
++                              /* found */
++                              break;
++                      /* not found, try higher one */
++              }
++              SET_BIT(cur, sent_rate);
++              log(L_XFER, "tx: stepping up to ratemask %04X\n", cur);
++      }
++
++      txc->rate_cur = cur;
++      txc->ignore_count = pkts_to_ignore;
++      /* calculate acx100 style rate byte if needed */
++      if (IS_ACX100(adev)) {
++              txc->rate_100 = acx_bitpos2rate100[highest_bit(cur)];
++      }
++}
++
++
++/***********************************************************************
++** acx_i_start_xmit
++**
++** Called by network core. Can be called outside of process context.
++*/
++int
++acx_i_start_xmit(struct sk_buff *skb, struct net_device *ndev)
++{
++      acx_device_t *adev = ndev2adev(ndev);
++      tx_t *tx;
++      void *txbuf;
++      unsigned long flags;
++      int txresult = NOT_OK;
++      int len;
++
++      FN_ENTER;
++
++      if (unlikely(!skb)) {
++              /* indicate success */
++              txresult = OK;
++              goto end_no_unlock;
++      }
++      if (unlikely(!adev)) {
++              goto end_no_unlock;
++      }
++
++      acx_lock(adev, flags);
++
++      if (unlikely(!(adev->dev_state_mask & ACX_STATE_IFACE_UP))) {
++              goto end;
++      }
++      if (unlikely(adev->mode == ACX_MODE_OFF)) {
++              goto end;
++      }
++      if (unlikely(acx_queue_stopped(ndev))) {
++              log(L_DEBUG, "%s: called when queue stopped\n", __func__);
++              goto end;
++      }
++      if (unlikely(ACX_STATUS_4_ASSOCIATED != adev->status)) {
++              log(L_XFER, "trying to xmit, but not associated yet: "
++                      "aborting...\n");
++              /* silently drop the packet, since we're not connected yet */
++              txresult = OK;
++              /* ...but indicate an error nevertheless */
++              adev->stats.tx_errors++;
++              goto end;
++      }
++
++      tx = acx_l_alloc_tx(adev);
++      if (unlikely(!tx)) {
++#ifndef ACX_MEM
++        /*
++         * generic slave interface has to make do with the tiny amount, around
++         * 7k, of transmit buffer space on the ACX itself.  It is likely this will
++         * frequently be full.
++         */
++              printk_ratelimited("%s: start_xmit: txdesc ring is full, "
++                      "dropping tx\n", ndev->name);
++#endif
++              txresult = NOT_OK;
++              goto end;
++      }
++
++      txbuf = acx_l_get_txbuf(adev, tx);
++      if (unlikely(!txbuf)) {
++              /* Card was removed */
++              txresult = NOT_OK;
++              acx_l_dealloc_tx(adev, tx);
++              goto end;
++      }
++      len = acx_ether_to_txbuf(adev, txbuf, skb);
++      if (unlikely(len < 0)) {
++              /* Error in packet conversion */
++              txresult = NOT_OK;
++              acx_l_dealloc_tx(adev, tx);
++              goto end;
++      }
++      acx_l_tx_data(adev, tx, len);
++      ndev->trans_start = jiffies;
++
++      txresult = OK;
++      adev->stats.tx_packets++;
++      adev->stats.tx_bytes += skb->len;
++
++end:
++      acx_unlock(adev, flags);
++
++end_no_unlock:
++      if ((txresult == OK) && skb)
++              dev_kfree_skb_any(skb);
++
++      FN_EXIT1(txresult);
++      return txresult;
++}
++
++
++/***********************************************************************
++** acx_l_update_ratevector
++**
++** Updates adev->rate_supported[_len] according to rate_{basic,oper}
++*/
++const u8
++acx_bitpos2ratebyte[] = {
++      DOT11RATEBYTE_1,
++      DOT11RATEBYTE_2,
++      DOT11RATEBYTE_5_5,
++      DOT11RATEBYTE_6_G,
++      DOT11RATEBYTE_9_G,
++      DOT11RATEBYTE_11,
++      DOT11RATEBYTE_12_G,
++      DOT11RATEBYTE_18_G,
++      DOT11RATEBYTE_22,
++      DOT11RATEBYTE_24_G,
++      DOT11RATEBYTE_36_G,
++      DOT11RATEBYTE_48_G,
++      DOT11RATEBYTE_54_G,
++};
++
++void
++acx_l_update_ratevector(acx_device_t *adev)
++{
++      u16 bcfg = adev->rate_basic;
++      u16 ocfg = adev->rate_oper;
++      u8 *supp = adev->rate_supported;
++      const u8 *dot11 = acx_bitpos2ratebyte;
++
++      FN_ENTER;
++
++      while (ocfg) {
++              if (ocfg & 1) {
++                      *supp = *dot11;
++                      if (bcfg & 1) {
++                              *supp |= 0x80;
++                      }
++                      supp++;
++              }
++              dot11++;
++              ocfg >>= 1;
++              bcfg >>= 1;
++      }
++      adev->rate_supported_len = supp - adev->rate_supported;
++      if (acx_debug & L_ASSOC) {
++              printk("new ratevector: ");
++              acx_dump_bytes(adev->rate_supported, adev->rate_supported_len);
++      }
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++** acx_l_sta_list_init
++*/
++static void
++acx_l_sta_list_init(acx_device_t *adev)
++{
++      FN_ENTER;
++      memset(adev->sta_hash_tab, 0, sizeof(adev->sta_hash_tab));
++      memset(adev->sta_list, 0, sizeof(adev->sta_list));
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++** acx_l_sta_list_get_from_hash
++*/
++static inline client_t*
++acx_l_sta_list_get_from_hash(acx_device_t *adev, const u8 *address)
++{
++      return adev->sta_hash_tab[address[5] % VEC_SIZE(adev->sta_hash_tab)];
++}
++
++
++/***********************************************************************
++** acx_l_sta_list_get
++*/
++client_t*
++acx_l_sta_list_get(acx_device_t *adev, const u8 *address)
++{
++      client_t *client;
++      FN_ENTER;
++      client = acx_l_sta_list_get_from_hash(adev, address);
++      while (client) {
++              if (mac_is_equal(address, client->address)) {
++                      client->mtime = jiffies;
++                      break;
++              }
++              client = client->next;
++      }
++      FN_EXIT0;
++      return client;
++}
++
++
++/***********************************************************************
++** acx_l_sta_list_del
++*/
++void
++acx_l_sta_list_del(acx_device_t *adev, client_t *victim)
++{
++      client_t *client, *next;
++
++      client = acx_l_sta_list_get_from_hash(adev, victim->address);
++      next = client;
++      /* tricky. next = client on first iteration only,
++      ** on all other iters next = client->next */
++      while (next) {
++              if (next == victim) {
++                      client->next = victim->next;
++                      /* Overkill */
++                      memset(victim, 0, sizeof(*victim));
++                      break;
++              }
++              client = next;
++              next = client->next;
++      }
++}
++
++
++/***********************************************************************
++** acx_l_sta_list_alloc
++**
++** Never fails - will evict oldest client if needed
++*/
++static client_t*
++acx_l_sta_list_alloc(acx_device_t *adev)
++{
++      int i;
++      unsigned long age, oldest_age;
++      client_t *client, *oldest;
++
++      FN_ENTER;
++
++      oldest = &adev->sta_list[0];
++      oldest_age = 0;
++      for (i = 0; i < VEC_SIZE(adev->sta_list); i++) {
++              client = &adev->sta_list[i];
++
++              if (!client->used) {
++                      goto found;
++              } else {
++                      age = jiffies - client->mtime;
++                      if (oldest_age < age) {
++                              oldest_age = age;
++                              oldest = client;
++                      }
++              }
++      }
++      acx_l_sta_list_del(adev, oldest);
++      client = oldest;
++found:
++      memset(client, 0, sizeof(*client));
++      FN_EXIT0;
++      return client;
++}
++
++
++/***********************************************************************
++** acx_l_sta_list_add
++**
++** Never fails - will evict oldest client if needed
++*/
++/* In case we will reimplement it differently... */
++#define STA_LIST_ADD_CAN_FAIL 0
++
++static client_t*
++acx_l_sta_list_add(acx_device_t *adev, const u8 *address)
++{
++      client_t *client;
++      int index;
++
++      FN_ENTER;
++
++      client = acx_l_sta_list_alloc(adev);
++
++      client->mtime = jiffies;
++      MAC_COPY(client->address, address);
++      client->used = CLIENT_EXIST_1;
++      client->auth_alg = WLAN_AUTH_ALG_SHAREDKEY;
++      client->auth_step = 1;
++      /* give some tentative peer rate values
++      ** (needed because peer may do auth without probing us first,
++      ** thus we'll have no idea of peer's ratevector yet).
++      ** Will be overwritten by scanning or assoc code */
++      client->rate_cap = adev->rate_basic;
++      client->rate_cfg = adev->rate_basic;
++      client->rate_cur = 1 << lowest_bit(adev->rate_basic);
++
++      index = address[5] % VEC_SIZE(adev->sta_hash_tab);
++      client->next = adev->sta_hash_tab[index];
++      adev->sta_hash_tab[index] = client;
++
++      acxlog_mac(L_ASSOC, "sta_list_add: sta=", address, "\n");
++
++      FN_EXIT0;
++      return client;
++}
++
++
++/***********************************************************************
++** acx_l_sta_list_get_or_add
++**
++** Never fails - will evict oldest client if needed
++*/
++static client_t*
++acx_l_sta_list_get_or_add(acx_device_t *adev, const u8 *address)
++{
++      client_t *client = acx_l_sta_list_get(adev, address);
++      if (!client)
++              client = acx_l_sta_list_add(adev, address);
++      return client;
++}
++
++
++/***********************************************************************
++** acx_set_status
++**
++** This function is called in many atomic regions, must not sleep
++**
++** This function does not need locking UNLESS you call it
++** as acx_set_status(ACX_STATUS_4_ASSOCIATED), bacause this can
++** wake queue. This can race with stop_queue elsewhere.
++** See acx_stop_queue comment. */
++void
++acx_set_status(acx_device_t *adev, u16 new_status)
++{
++#define QUEUE_OPEN_AFTER_ASSOC 1 /* this really seems to be needed now */
++      u16 old_status = adev->status;
++
++      FN_ENTER;
++
++      log(L_ASSOC, "%s(%d):%s\n",
++             __func__, new_status, acx_get_status_name(new_status));
++
++      /* wireless_send_event never sleeps */
++      if (ACX_STATUS_4_ASSOCIATED == new_status) {
++              union iwreq_data wrqu;
++
++              wrqu.data.length = 0;
++              wrqu.data.flags = 0;
++              wireless_send_event(adev->ndev, SIOCGIWSCAN, &wrqu, NULL);
++
++              wrqu.data.length = 0;
++              wrqu.data.flags = 0;
++              MAC_COPY(wrqu.ap_addr.sa_data, adev->bssid);
++              wrqu.ap_addr.sa_family = ARPHRD_ETHER;
++              wireless_send_event(adev->ndev, SIOCGIWAP, &wrqu, NULL);
++      } else {
++              union iwreq_data wrqu;
++
++              /* send event with empty BSSID to indicate we're not associated */
++              MAC_ZERO(wrqu.ap_addr.sa_data);
++              wrqu.ap_addr.sa_family = ARPHRD_ETHER;
++              wireless_send_event(adev->ndev, SIOCGIWAP, &wrqu, NULL);
++      }
++
++      adev->status = new_status;
++
++      switch (new_status) {
++      case ACX_STATUS_1_SCANNING:
++              adev->scan_retries = 0;
++              /* 1.0 s initial scan time */
++              acx_set_timer(adev, 1000000);
++              break;
++      case ACX_STATUS_2_WAIT_AUTH:
++      case ACX_STATUS_3_AUTHENTICATED:
++              adev->auth_or_assoc_retries = 0;
++              acx_set_timer(adev, 1500000); /* 1.5 s */
++              break;
++      }
++
++#if QUEUE_OPEN_AFTER_ASSOC
++      if (new_status == ACX_STATUS_4_ASSOCIATED)      {
++              if (old_status < ACX_STATUS_4_ASSOCIATED) {
++                      /* ah, we're newly associated now,
++                       * so let's indicate carrier */
++                      acx_carrier_on(adev->ndev, "after association");
++                      acx_wake_queue(adev->ndev, "after association");
++              }
++      } else {
++              /* not associated any more, so let's kill carrier */
++              if (old_status >= ACX_STATUS_4_ASSOCIATED) {
++                      acx_carrier_off(adev->ndev, "after losing association");
++                      acx_stop_queue(adev->ndev, "after losing association");
++              }
++      }
++#endif
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++** acx_i_timer
++**
++** Fires up periodically. Used to kick scan/auth/assoc if something goes wrong
++*/
++void
++acx_i_timer(unsigned long address)
++{
++      unsigned long flags;
++      acx_device_t *adev = (acx_device_t*)address;
++
++      FN_ENTER;
++
++      acx_lock(adev, flags);
++
++      log(L_DEBUG|L_ASSOC, "%s: adev->status=%d (%s)\n",
++              __func__, adev->status, acx_get_status_name(adev->status));
++
++      switch (adev->status) {
++      case ACX_STATUS_1_SCANNING:
++              /* was set to 0 by set_status() */
++              if (++adev->scan_retries < 7) {
++                      acx_set_timer(adev, 1000000);
++                      /* used to interrogate for scan status.
++                      ** We rely on SCAN_COMPLETE IRQ instead */
++                      log(L_ASSOC, "continuing scan (%d sec)\n",
++                                      adev->scan_retries);
++              } else {
++                      log(L_ASSOC, "stopping scan\n");
++                      /* send stop_scan cmd when we leave the interrupt context,
++                       * and make a decision what to do next (COMPLETE_SCAN) */
++                      acx_schedule_task(adev,
++                              ACX_AFTER_IRQ_CMD_STOP_SCAN + ACX_AFTER_IRQ_COMPLETE_SCAN);
++              }
++              break;
++      case ACX_STATUS_2_WAIT_AUTH:
++              /* was set to 0 by set_status() */
++              if (++adev->auth_or_assoc_retries < 10) {
++                      log(L_ASSOC, "resend authen1 request (attempt %d)\n",
++                                      adev->auth_or_assoc_retries + 1);
++                      acx_l_transmit_authen1(adev);
++              } else {
++                      /* time exceeded: fall back to scanning mode */
++                      log(L_ASSOC,
++                             "authen1 request reply timeout, giving up\n");
++                      /* we are a STA, need to find AP anyhow */
++                      acx_set_status(adev, ACX_STATUS_1_SCANNING);
++                      acx_schedule_task(adev, ACX_AFTER_IRQ_RESTART_SCAN);
++              }
++              /* used to be 1500000, but some other driver uses 2.5s */
++              acx_set_timer(adev, 2500000);
++              break;
++      case ACX_STATUS_3_AUTHENTICATED:
++              /* was set to 0 by set_status() */
++              if (++adev->auth_or_assoc_retries < 10) {
++                      log(L_ASSOC, "resend assoc request (attempt %d)\n",
++                                      adev->auth_or_assoc_retries + 1);
++                      acx_l_transmit_assoc_req(adev);
++              } else {
++                      /* time exceeded: give up */
++                      log(L_ASSOC,
++                              "association request reply timeout, giving up\n");
++                      /* we are a STA, need to find AP anyhow */
++                      acx_set_status(adev, ACX_STATUS_1_SCANNING);
++                      acx_schedule_task(adev, ACX_AFTER_IRQ_RESTART_SCAN);
++              }
++              acx_set_timer(adev, 2500000); /* see above */
++              break;
++      case ACX_STATUS_4_ASSOCIATED:
++      default:
++              break;
++      }
++
++      acx_unlock(adev, flags);
++
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++** acx_set_timer
++**
++** Sets the 802.11 state management timer's timeout.
++*/
++void
++acx_set_timer(acx_device_t *adev, int timeout_us)
++{
++      FN_ENTER;
++
++      log(L_DEBUG|L_IRQ, "%s(%u ms)\n", __func__, timeout_us/1000);
++      if (!(adev->dev_state_mask & ACX_STATE_IFACE_UP)) {
++              printk("attempt to set the timer "
++                      "when the card interface is not up!\n");
++              goto end;
++      }
++
++      /* first check if the timer was already initialized, THEN modify it */
++      if (adev->mgmt_timer.function) {
++              mod_timer(&adev->mgmt_timer,
++                              jiffies + (timeout_us * HZ / 1000000));
++      }
++end:
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++** acx_l_transmit_assocresp
++**
++** We are an AP here
++*/
++static const u8
++dot11ratebyte[] = {
++      DOT11RATEBYTE_1,
++      DOT11RATEBYTE_2,
++      DOT11RATEBYTE_5_5,
++      DOT11RATEBYTE_6_G,
++      DOT11RATEBYTE_9_G,
++      DOT11RATEBYTE_11,
++      DOT11RATEBYTE_12_G,
++      DOT11RATEBYTE_18_G,
++      DOT11RATEBYTE_22,
++      DOT11RATEBYTE_24_G,
++      DOT11RATEBYTE_36_G,
++      DOT11RATEBYTE_48_G,
++      DOT11RATEBYTE_54_G,
++};
++
++static inline int
++find_pos(const u8 *p, int size, u8 v)
++{
++      int i;
++      for (i = 0; i < size; i++)
++              if (p[i] == v)
++                      return i;
++      /* printk a message about strange byte? */
++      return 0;
++}
++
++static void
++add_bits_to_ratemasks(u8* ratevec, int len, u16* brate, u16* orate)
++{
++      while (len--) {
++              int n = 1 << find_pos(dot11ratebyte,
++                              sizeof(dot11ratebyte), *ratevec & 0x7f);
++              if (*ratevec & 0x80)
++                      *brate |= n;
++              *orate |= n;
++              ratevec++;
++      }
++}
++
++static int
++acx_l_transmit_assocresp(acx_device_t *adev, const wlan_fr_assocreq_t *req)
++{
++      struct tx *tx;
++      struct wlan_hdr_mgmt *head;
++      struct assocresp_frame_body *body;
++      u8 *p;
++      const u8 *da;
++      /* const u8 *sa; */
++      const u8 *bssid;
++      client_t *clt;
++
++      FN_ENTER;
++
++      /* sa = req->hdr->a1; */
++      da = req->hdr->a2;
++      bssid = req->hdr->a3;
++
++      clt = acx_l_sta_list_get(adev, da);
++      if (!clt)
++              goto ok;
++
++      /* Assoc without auth is a big no-no */
++      /* Let's be liberal: if already assoc'ed STA sends assoc req again,
++      ** we won't be rude */
++      if (clt->used != CLIENT_AUTHENTICATED_2
++       && clt->used != CLIENT_ASSOCIATED_3) {
++              acx_l_transmit_deauthen(adev, da, WLAN_MGMT_REASON_CLASS2_NONAUTH);
++              goto bad;
++      }
++
++      clt->used = CLIENT_ASSOCIATED_3;
++
++      if (clt->aid == 0)
++              clt->aid = ++adev->aid;
++      clt->cap_info = ieee2host16(*(req->cap_info));
++
++      /* We cheat here a bit. We don't really care which rates are flagged
++      ** as basic by the client, so we stuff them in single ratemask */
++      clt->rate_cap = 0;
++      if (req->supp_rates)
++              add_bits_to_ratemasks(req->supp_rates->rates,
++                      req->supp_rates->len, &clt->rate_cap, &clt->rate_cap);
++      if (req->ext_rates)
++              add_bits_to_ratemasks(req->ext_rates->rates,
++                      req->ext_rates->len, &clt->rate_cap, &clt->rate_cap);
++      /* We can check that client supports all basic rates,
++      ** and deny assoc if not. But let's be liberal, right? ;) */
++      clt->rate_cfg = clt->rate_cap & adev->rate_oper;
++      if (!clt->rate_cfg) clt->rate_cfg = 1 << lowest_bit(adev->rate_oper);
++      clt->rate_cur = 1 << lowest_bit(clt->rate_cfg);
++      if (IS_ACX100(adev))
++              clt->rate_100 = acx_bitpos2rate100[lowest_bit(clt->rate_cfg)];
++      clt->fallback_count = clt->stepup_count = 0;
++      clt->ignore_count = 16;
++
++      tx = acx_l_alloc_tx(adev);
++      if (!tx)
++              goto bad;
++      head = acx_l_get_txbuf(adev, tx);
++      if (!head) {
++              acx_l_dealloc_tx(adev, tx);
++              goto bad;
++      }
++      body = (void*)(head + 1);
++
++      head->fc = WF_FSTYPE_ASSOCRESPi;
++      head->dur = req->hdr->dur;
++      MAC_COPY(head->da, da);
++      MAC_COPY(head->sa, adev->dev_addr);
++      MAC_COPY(head->bssid, bssid);
++      head->seq = req->hdr->seq;
++
++      body->cap_info = host2ieee16(adev->capabilities);
++      body->status = host2ieee16(0);
++      body->aid = host2ieee16(clt->aid);
++      p = wlan_fill_ie_rates((u8*)&body->rates, adev->rate_supported_len,
++                                                      adev->rate_supported);
++      p = wlan_fill_ie_rates_ext(p, adev->rate_supported_len,
++                                                      adev->rate_supported);
++
++      acx_l_tx_data(adev, tx, p - (u8*)head);
++ok:
++      FN_EXIT1(OK);
++      return OK;
++bad:
++      FN_EXIT1(NOT_OK);
++      return NOT_OK;
++}
++
++
++/***********************************************************************
++* acx_l_transmit_reassocresp
++
++You may be wondering, just like me, what the hell ReAuth is.
++In practice it was seen sent by STA when STA feels like losing connection.
++
++[802.11]
++
++5.4.2.3 Reassociation
++
++Association is sufficient for no-transition message delivery between
++IEEE 802.11 stations. Additional functionality is needed to support
++BSS-transition mobility. The additional required functionality
++is provided by the reassociation service. Reassociation is a DSS.
++The reassociation service is invoked to 'move' a current association
++from one AP to another. This keeps the DS informed of the current
++mapping between AP and STA as the station moves from BSS to BSS within
++an ESS. Reassociation also enables changing association attributes
++of an established association while the STA remains associated with
++the same AP. Reassociation is always initiated by the mobile STA.
++
++5.4.3.1 Authentication
++...
++A STA may be authenticated with many other STAs at any given instant.
++
++5.4.3.1.1 Preauthentication
++
++Because the authentication process could be time-consuming (depending
++on the authentication protocol in use), the authentication service can
++be invoked independently of the association service. Preauthentication
++is typically done by a STA while it is already associated with an AP
++(with which it previously authenticated). IEEE 802.11 does not require
++that STAs preauthenticate with APs. However, authentication is required
++before an association can be established. If the authentication is left
++until reassociation time, this may impact the speed with which a STA can
++reassociate between APs, limiting BSS-transition mobility performance.
++The use of preauthentication takes the authentication service overhead
++out of the time-critical reassociation process.
++
++5.7.3 Reassociation
++
++For a STA to reassociate, the reassociation service causes the following
++message to occur:
++
++  Reassociation request
++
++* Message type: Management
++* Message subtype: Reassociation request
++* Information items:
++  - IEEE address of the STA
++  - IEEE address of the AP with which the STA will reassociate
++  - IEEE address of the AP with which the STA is currently associated
++  - ESSID
++* Direction of message: From STA to 'new' AP
++
++The address of the current AP is included for efficiency. The inclusion
++of the current AP address facilitates MAC reassociation to be independent
++of the DS implementation.
++
++  Reassociation response
++* Message type: Management
++* Message subtype: Reassociation response
++* Information items:
++  - Result of the requested reassociation. (success/failure)
++  - If the reassociation is successful, the response shall include the AID.
++* Direction of message: From AP to STA
++
++7.2.3.6 Reassociation Request frame format
++
++The frame body of a management frame of subtype Reassociation Request
++contains the information shown in Table 9.
++
++Table 9 Reassociation Request frame body
++Order Information
++1 Capability information
++2 Listen interval
++3 Current AP address
++4 SSID
++5 Supported rates
++
++7.2.3.7 Reassociation Response frame format
++
++The frame body of a management frame of subtype Reassociation Response
++contains the information shown in Table 10.
++
++Table 10 Reassociation Response frame body
++Order Information
++1 Capability information
++2 Status code
++3 Association ID (AID)
++4 Supported rates
++
++*/
++static int
++acx_l_transmit_reassocresp(acx_device_t *adev, const wlan_fr_reassocreq_t *req)
++{
++      struct tx *tx;
++      struct wlan_hdr_mgmt *head;
++      struct reassocresp_frame_body *body;
++      u8 *p;
++      const u8 *da;
++      /* const u8 *sa; */
++      const u8 *bssid;
++      client_t *clt;
++
++      FN_ENTER;
++
++      /* sa = req->hdr->a1; */
++      da = req->hdr->a2;
++      bssid = req->hdr->a3;
++
++      /* Must be already authenticated, so it must be in the list */
++      clt = acx_l_sta_list_get(adev, da);
++      if (!clt)
++              goto ok;
++
++      /* Assoc without auth is a big no-no */
++      /* Already assoc'ed STAs sending ReAssoc req are ok per 802.11 */
++      if (clt->used != CLIENT_AUTHENTICATED_2
++       && clt->used != CLIENT_ASSOCIATED_3) {
++              acx_l_transmit_deauthen(adev, da, WLAN_MGMT_REASON_CLASS2_NONAUTH);
++              goto bad;
++      }
++
++      clt->used = CLIENT_ASSOCIATED_3;
++      if (clt->aid == 0) {
++              clt->aid = ++adev->aid;
++      }
++      if (req->cap_info)
++              clt->cap_info = ieee2host16(*(req->cap_info));
++
++      /* We cheat here a bit. We don't really care which rates are flagged
++      ** as basic by the client, so we stuff them in single ratemask */
++      clt->rate_cap = 0;
++      if (req->supp_rates)
++              add_bits_to_ratemasks(req->supp_rates->rates,
++                      req->supp_rates->len, &clt->rate_cap, &clt->rate_cap);
++      if (req->ext_rates)
++              add_bits_to_ratemasks(req->ext_rates->rates,
++                      req->ext_rates->len, &clt->rate_cap, &clt->rate_cap);
++      /* We can check that client supports all basic rates,
++      ** and deny assoc if not. But let's be liberal, right? ;) */
++      clt->rate_cfg = clt->rate_cap & adev->rate_oper;
++      if (!clt->rate_cfg) clt->rate_cfg = 1 << lowest_bit(adev->rate_oper);
++      clt->rate_cur = 1 << lowest_bit(clt->rate_cfg);
++      if (IS_ACX100(adev))
++              clt->rate_100 = acx_bitpos2rate100[lowest_bit(clt->rate_cfg)];
++
++      clt->fallback_count = clt->stepup_count = 0;
++      clt->ignore_count = 16;
++
++      tx = acx_l_alloc_tx(adev);
++      if (!tx)
++              goto ok;
++      head = acx_l_get_txbuf(adev, tx);
++      if (!head) {
++              acx_l_dealloc_tx(adev, tx);
++              goto ok;
++      }
++      body = (void*)(head + 1);
++
++      head->fc = WF_FSTYPE_REASSOCRESPi;
++      head->dur = req->hdr->dur;
++      MAC_COPY(head->da, da);
++      MAC_COPY(head->sa, adev->dev_addr);
++      MAC_COPY(head->bssid, bssid);
++      head->seq = req->hdr->seq;
++
++      /* IEs: 1. caps */
++      body->cap_info = host2ieee16(adev->capabilities);
++      /* 2. status code */
++      body->status = host2ieee16(0);
++      /* 3. AID */
++      body->aid = host2ieee16(clt->aid);
++      /* 4. supp rates */
++      p = wlan_fill_ie_rates((u8*)&body->rates, adev->rate_supported_len,
++                                                      adev->rate_supported);
++      /* 5. ext supp rates */
++      p = wlan_fill_ie_rates_ext(p, adev->rate_supported_len,
++                                                      adev->rate_supported);
++
++      acx_l_tx_data(adev, tx, p - (u8*)head);
++ok:
++      FN_EXIT1(OK);
++      return OK;
++bad:
++      FN_EXIT1(NOT_OK);
++      return NOT_OK;
++}
++
++
++/***********************************************************************
++** acx_l_process_disassoc_from_sta
++*/
++static void
++acx_l_process_disassoc_from_sta(acx_device_t *adev, const wlan_fr_disassoc_t *req)
++{
++      const u8 *ta;
++      client_t *clt;
++
++      FN_ENTER;
++
++      ta = req->hdr->a2;
++      clt = acx_l_sta_list_get(adev, ta);
++      if (!clt)
++              goto end;
++
++      if (clt->used != CLIENT_ASSOCIATED_3
++       && clt->used != CLIENT_AUTHENTICATED_2) {
++              /* it's disassociating, but it's
++              ** not even authenticated! Let it know that */
++              acxlog_mac(L_ASSOC|L_XFER, "peer ", ta, "has sent disassoc "
++                      "req but it is not even auth'ed! sending deauth\n");
++              acx_l_transmit_deauthen(adev, ta,
++                      WLAN_MGMT_REASON_CLASS2_NONAUTH);
++              clt->used = CLIENT_EXIST_1;
++      } else {
++              /* mark it as auth'ed only */
++              clt->used = CLIENT_AUTHENTICATED_2;
++      }
++end:
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++** acx_l_process_deauthen_from_sta
++*/
++static void
++acx_l_process_deauth_from_sta(acx_device_t *adev, const wlan_fr_deauthen_t *req)
++{
++      const wlan_hdr_t *hdr;
++      client_t *client;
++
++      FN_ENTER;
++
++      hdr = req->hdr;
++
++      if (acx_debug & L_ASSOC) {
++              acx_print_mac("got deauth from sta:", hdr->a2, " ");
++              acx_print_mac("a1:", hdr->a1, " ");
++              acx_print_mac("a3:", hdr->a3, " ");
++              acx_print_mac("adev->addr:", adev->dev_addr, " ");
++              acx_print_mac("adev->bssid:", adev->bssid, "\n");
++      }
++
++      if (!mac_is_equal(adev->dev_addr, hdr->a1)) {
++              goto end;
++      }
++
++      client = acx_l_sta_list_get(adev, hdr->a2);
++      if (!client) {
++              goto end;
++      }
++      client->used = CLIENT_EXIST_1;
++end:
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++** acx_l_process_disassoc_from_ap
++*/
++static void
++acx_l_process_disassoc_from_ap(acx_device_t *adev, const wlan_fr_disassoc_t *req)
++{
++      FN_ENTER;
++
++      if (!adev->ap_client) {
++              /* Hrm, we aren't assoc'ed yet anyhow... */
++              goto end;
++      }
++
++      printk("%s: got disassoc frame with reason %d (%s)\n",
++              adev->ndev->name, *req->reason,
++              acx_wlan_reason_str(*req->reason));
++
++      if (mac_is_equal(adev->dev_addr, req->hdr->a1)) {
++              acx_l_transmit_deauthen(adev, adev->bssid,
++                              WLAN_MGMT_REASON_DEAUTH_LEAVING);
++              SET_BIT(adev->set_mask, GETSET_RESCAN);
++              acx_schedule_task(adev, ACX_AFTER_IRQ_UPDATE_CARD_CFG);
++      }
++end:
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++** acx_l_process_deauth_from_ap
++*/
++static void
++acx_l_process_deauth_from_ap(acx_device_t *adev, const wlan_fr_deauthen_t *req)
++{
++      FN_ENTER;
++
++      if (!adev->ap_client) {
++              /* Hrm, we aren't assoc'ed yet anyhow... */
++              goto end;
++      }
++
++      printk("%s: got deauth frame with reason %d (%s)\n",
++              adev->ndev->name, *req->reason,
++              acx_wlan_reason_str(*req->reason));
++
++      /* Chk: is ta verified to be from our AP? */
++      if (mac_is_equal(adev->dev_addr, req->hdr->a1)) {
++              log(L_DEBUG, "AP sent us deauth packet\n");
++              SET_BIT(adev->set_mask, GETSET_RESCAN);
++              acx_schedule_task(adev, ACX_AFTER_IRQ_UPDATE_CARD_CFG);
++      }
++end:
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++** acx_l_rx
++**
++** The end of the Rx path. Pulls data from a rxhostdesc into a socket
++** buffer and feeds it to the network stack via netif_rx().
++*/
++static void
++acx_l_rx(acx_device_t *adev, rxbuffer_t *rxbuf)
++{
++      FN_ENTER;
++      if (likely(adev->dev_state_mask & ACX_STATE_IFACE_UP)) {
++              struct sk_buff *skb;
++              skb = acx_rxbuf_to_ether(adev, rxbuf);
++              if (likely(skb)) {
++                      netif_rx(skb);
++                      adev->ndev->last_rx = jiffies;
++                      adev->stats.rx_packets++;
++                      adev->stats.rx_bytes += skb->len;
++              }
++      }
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++** acx_l_process_data_frame_master
++*/
++static int
++acx_l_process_data_frame_master(acx_device_t *adev, rxbuffer_t *rxbuf)
++{
++      struct wlan_hdr *hdr;
++      struct tx *tx;
++      void *txbuf;
++      int len;
++      int result = NOT_OK;
++
++      FN_ENTER;
++
++      hdr = acx_get_wlan_hdr(adev, rxbuf);
++
++      switch (WF_FC_FROMTODSi & hdr->fc) {
++      case 0:
++      case WF_FC_FROMDSi:
++              log(L_DEBUG, "ap->sta or adhoc->adhoc data frame ignored\n");
++              goto done;
++      case WF_FC_TODSi:
++              break;
++      default: /* WF_FC_FROMTODSi */
++              log(L_DEBUG, "wds data frame ignored (TODO)\n");
++              goto done;
++      }
++
++      /* check if it is our BSSID, if not, leave */
++      if (!mac_is_equal(adev->bssid, hdr->a1)) {
++              goto done;
++      }
++
++      if (mac_is_equal(adev->dev_addr, hdr->a3)) {
++              /* this one is for us */
++              acx_l_rx(adev, rxbuf);
++      } else {
++              if (mac_is_bcast(hdr->a3)) {
++                      /* this one is bcast, rx it too */
++                      acx_l_rx(adev, rxbuf);
++              }
++              tx = acx_l_alloc_tx(adev);
++              if (!tx) {
++                      goto fail;
++              }
++              /* repackage, tx, and hope it someday reaches its destination */
++              /* order is important, we do it in-place */
++              MAC_COPY(hdr->a1, hdr->a3);
++              MAC_COPY(hdr->a3, hdr->a2);
++              MAC_COPY(hdr->a2, adev->bssid);
++              /* To_DS = 0, From_DS = 1 */
++              hdr->fc = WF_FC_FROMDSi + WF_FTYPE_DATAi;
++
++              txbuf = acx_l_get_txbuf(adev, tx);
++              if (txbuf) {
++                      len = RXBUF_BYTES_RCVD(adev, rxbuf);
++                      memcpy(txbuf, hdr, len);
++                      acx_l_tx_data(adev, tx, len);
++              } else {
++                      acx_l_dealloc_tx(adev, tx);
++              }
++      }
++done:
++      result = OK;
++fail:
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/***********************************************************************
++** acx_l_process_data_frame_client
++*/
++static int
++acx_l_process_data_frame_client(acx_device_t *adev, rxbuffer_t *rxbuf)
++{
++      const u8 *da, *bssid;
++      const wlan_hdr_t *hdr;
++      struct net_device *ndev = adev->ndev;
++      int result = NOT_OK;
++
++      FN_ENTER;
++
++      if (ACX_STATUS_4_ASSOCIATED != adev->status)
++              goto drop;
++
++      hdr = acx_get_wlan_hdr(adev, rxbuf);
++
++      switch (WF_FC_FROMTODSi & hdr->fc) {
++      case 0:
++              if (adev->mode != ACX_MODE_0_ADHOC) {
++                      log(L_DEBUG, "adhoc->adhoc data frame ignored\n");
++                      goto drop;
++              }
++              bssid = hdr->a3;
++              break;
++      case WF_FC_FROMDSi:
++              if (adev->mode != ACX_MODE_2_STA) {
++                      log(L_DEBUG, "ap->sta data frame ignored\n");
++                      goto drop;
++              }
++              bssid = hdr->a2;
++              break;
++      case WF_FC_TODSi:
++              log(L_DEBUG, "sta->ap data frame ignored\n");
++              goto drop;
++      default: /* WF_FC_FROMTODSi: wds->wds */
++              log(L_DEBUG, "wds data frame ignored (todo)\n");
++              goto drop;
++      }
++
++      da = hdr->a1;
++
++      if (unlikely(acx_debug & L_DEBUG)) {
++              acx_print_mac("rx: da=", da, "");
++              acx_print_mac(" bssid=", bssid, "");
++              acx_print_mac(" adev->bssid=", adev->bssid, "");
++              acx_print_mac(" adev->addr=", adev->dev_addr, "\n");
++      }
++
++      /* promiscuous mode --> receive all packets */
++      if (unlikely(ndev->flags & IFF_PROMISC))
++              goto process;
++
++      /* FIRST, check if it is our BSSID */
++      if (!mac_is_equal(adev->bssid, bssid)) {
++              /* is not our BSSID, so bail out */
++              goto drop;
++      }
++
++      /* then, check if it is our address */
++      if (mac_is_equal(adev->dev_addr, da)) {
++              goto process;
++      }
++
++      /* then, check if it is broadcast */
++      if (mac_is_bcast(da)) {
++              goto process;
++      }
++
++      if (mac_is_mcast(da)) {
++              /* unconditionally receive all multicasts */
++              if (ndev->flags & IFF_ALLMULTI)
++                      goto process;
++
++              /* FIXME: need to check against the list of
++               * multicast addresses that are configured
++               * for the interface (ifconfig) */
++              log(L_XFER, "FIXME: multicast packet, need to check "
++                      "against a list of multicast addresses "
++                      "(to be created!); accepting packet for now\n");
++              /* for now, just accept it here */
++              goto process;
++      }
++
++      log(L_DEBUG, "rx: foreign packet, dropping\n");
++      goto drop;
++process:
++      /* receive packet */
++      acx_l_rx(adev, rxbuf);
++
++      result = OK;
++drop:
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/***********************************************************************
++** acx_l_process_mgmt_frame
++**
++** Theory of operation: mgmt packet gets parsed (to make it easy
++** to access variable-sized IEs), results stored in 'parsed'.
++** Then we react to the packet.
++*/
++typedef union parsed_mgmt_req {
++      wlan_fr_mgmt_t mgmt;
++      wlan_fr_assocreq_t assocreq;
++      wlan_fr_reassocreq_t reassocreq;
++      wlan_fr_assocresp_t assocresp;
++      wlan_fr_reassocresp_t reassocresp;
++      wlan_fr_beacon_t beacon;
++      wlan_fr_disassoc_t disassoc;
++      wlan_fr_authen_t authen;
++      wlan_fr_deauthen_t deauthen;
++      wlan_fr_proberesp_t proberesp;
++} parsed_mgmt_req_t;
++
++void BUG_excessive_stack_usage(void);
++
++static int
++acx_l_process_mgmt_frame(acx_device_t *adev, rxbuffer_t *rxbuf)
++{
++      parsed_mgmt_req_t parsed;       /* takes ~100 bytes of stack */
++      wlan_hdr_t *hdr;
++      int adhoc, sta_scan, sta, ap;
++      int len;
++
++      if (sizeof(parsed) > 256)
++              BUG_excessive_stack_usage();
++
++      FN_ENTER;
++
++      hdr = acx_get_wlan_hdr(adev, rxbuf);
++
++      /* Management frames never have these set */
++      if (WF_FC_FROMTODSi & hdr->fc) {
++              FN_EXIT1(NOT_OK);
++              return NOT_OK;
++      }
++
++      len = RXBUF_BYTES_RCVD(adev, rxbuf);
++      if (WF_FC_ISWEPi & hdr->fc)
++              len -= 0x10;
++
++      adhoc = (adev->mode == ACX_MODE_0_ADHOC);
++      sta_scan = ((adev->mode == ACX_MODE_2_STA)
++               && (adev->status != ACX_STATUS_4_ASSOCIATED));
++      sta = ((adev->mode == ACX_MODE_2_STA)
++          && (adev->status == ACX_STATUS_4_ASSOCIATED));
++      ap = (adev->mode == ACX_MODE_3_AP);
++
++      switch (WF_FC_FSTYPEi & hdr->fc) {
++      /* beacons first, for speed */
++      case WF_FSTYPE_BEACONi:
++              memset(&parsed.beacon, 0, sizeof(parsed.beacon));
++              parsed.beacon.hdr = hdr;
++              parsed.beacon.len = len;
++              if (acx_debug & L_DATA) {
++                      printk("beacon len:%d fc:%04X dur:%04X seq:%04X",
++                             len, hdr->fc, hdr->dur, hdr->seq);
++                      acx_print_mac(" a1:", hdr->a1, "");
++                      acx_print_mac(" a2:", hdr->a2, "");
++                      acx_print_mac(" a3:", hdr->a3, "\n");
++              }
++              wlan_mgmt_decode_beacon(&parsed.beacon);
++              /* beacon and probe response are very similar, so... */
++              acx_l_process_probe_response(adev, &parsed.beacon, rxbuf);
++              break;
++      case WF_FSTYPE_ASSOCREQi:
++              if (!ap)
++                      break;
++              memset(&parsed.assocreq, 0, sizeof(parsed.assocreq));
++              parsed.assocreq.hdr = hdr;
++              parsed.assocreq.len = len;
++              wlan_mgmt_decode_assocreq(&parsed.assocreq);
++              if (mac_is_equal(hdr->a1, adev->bssid)
++               && mac_is_equal(hdr->a3, adev->bssid)) {
++                      acx_l_transmit_assocresp(adev, &parsed.assocreq);
++              }
++              break;
++      case WF_FSTYPE_REASSOCREQi:
++              if (!ap)
++                      break;
++              memset(&parsed.assocreq, 0, sizeof(parsed.assocreq));
++              parsed.assocreq.hdr = hdr;
++              parsed.assocreq.len = len;
++              wlan_mgmt_decode_assocreq(&parsed.assocreq);
++              /* reassocreq and assocreq are equivalent */
++              acx_l_transmit_reassocresp(adev, &parsed.reassocreq);
++              break;
++      case WF_FSTYPE_ASSOCRESPi:
++              if (!sta_scan)
++                      break;
++              memset(&parsed.assocresp, 0, sizeof(parsed.assocresp));
++              parsed.assocresp.hdr = hdr;
++              parsed.assocresp.len = len;
++              wlan_mgmt_decode_assocresp(&parsed.assocresp);
++              acx_l_process_assocresp(adev, &parsed.assocresp);
++              break;
++      case WF_FSTYPE_REASSOCRESPi:
++              if (!sta_scan)
++                      break;
++              memset(&parsed.assocresp, 0, sizeof(parsed.assocresp));
++              parsed.assocresp.hdr = hdr;
++              parsed.assocresp.len = len;
++              wlan_mgmt_decode_assocresp(&parsed.assocresp);
++              acx_l_process_reassocresp(adev, &parsed.reassocresp);
++              break;
++      case WF_FSTYPE_PROBEREQi:
++              if (ap || adhoc) {
++                      /* FIXME: since we're supposed to be an AP,
++                      ** we need to return a Probe Response packet.
++                      ** Currently firmware is doing it for us,
++                      ** but firmware is buggy! See comment elsewhere --vda */
++              }
++              break;
++      case WF_FSTYPE_PROBERESPi:
++              memset(&parsed.proberesp, 0, sizeof(parsed.proberesp));
++              parsed.proberesp.hdr = hdr;
++              parsed.proberesp.len = len;
++              wlan_mgmt_decode_proberesp(&parsed.proberesp);
++              acx_l_process_probe_response(adev, &parsed.proberesp, rxbuf);
++              break;
++      case 6:
++      case 7:
++              /* exit */
++              break;
++      case WF_FSTYPE_ATIMi:
++              /* exit */
++              break;
++      case WF_FSTYPE_DISASSOCi:
++              if (!sta && !ap)
++                      break;
++              memset(&parsed.disassoc, 0, sizeof(parsed.disassoc));
++              parsed.disassoc.hdr = hdr;
++              parsed.disassoc.len = len;
++              wlan_mgmt_decode_disassoc(&parsed.disassoc);
++              if (sta)
++                      acx_l_process_disassoc_from_ap(adev, &parsed.disassoc);
++              else
++                      acx_l_process_disassoc_from_sta(adev, &parsed.disassoc);
++              break;
++      case WF_FSTYPE_AUTHENi:
++              if (!sta_scan && !ap)
++                      break;
++              memset(&parsed.authen, 0, sizeof(parsed.authen));
++              parsed.authen.hdr = hdr;
++              parsed.authen.len = len;
++              wlan_mgmt_decode_authen(&parsed.authen);
++              acx_l_process_authen(adev, &parsed.authen);
++              break;
++      case WF_FSTYPE_DEAUTHENi:
++              if (!sta && !ap)
++                      break;
++              memset(&parsed.deauthen, 0, sizeof(parsed.deauthen));
++              parsed.deauthen.hdr = hdr;
++              parsed.deauthen.len = len;
++              wlan_mgmt_decode_deauthen(&parsed.deauthen);
++              if (sta)
++                      acx_l_process_deauth_from_ap(adev, &parsed.deauthen);
++              else
++                      acx_l_process_deauth_from_sta(adev, &parsed.deauthen);
++              break;
++      }
++
++      FN_EXIT1(OK);
++      return OK;
++}
++
++
++#ifdef UNUSED
++/***********************************************************************
++** acx_process_class_frame
++**
++** Called from IRQ context only
++*/
++static int
++acx_process_class_frame(acx_device_t *adev, rxbuffer_t *rxbuf, int vala)
++{
++      return OK;
++}
++#endif
++
++
++/***********************************************************************
++** acx_l_process_NULL_frame
++*/
++#ifdef BOGUS_ITS_NOT_A_NULL_FRAME_HANDLER_AT_ALL
++static int
++acx_l_process_NULL_frame(acx_device_t *adev, rxbuffer_t *rxbuf, int vala)
++{
++      const signed char *esi;
++      const u8 *ebx;
++      const wlan_hdr_t *hdr;
++      const client_t *client;
++      int result = NOT_OK;
++
++      hdr = acx_get_wlan_hdr(adev, rxbuf);
++
++      switch (WF_FC_FROMTODSi & hdr->fc) {
++      case 0:
++              esi = hdr->a1;
++              ebx = hdr->a2;
++              break;
++      case WF_FC_FROMDSi:
++              esi = hdr->a1;
++              ebx = hdr->a3;
++              break;
++      case WF_FC_TODSi:
++              esi = hdr->a1;
++              ebx = hdr->a2;
++              break;
++      default: /* WF_FC_FROMTODSi */
++              esi = hdr->a1; /* added by me! --vda */
++              ebx = hdr->a2;
++      }
++
++      if (esi[0x0] < 0) {
++              result = OK;
++              goto done;
++      }
++
++      client = acx_l_sta_list_get(adev, ebx);
++      if (client)
++              result = NOT_OK;
++      else {
++#ifdef IS_IT_BROKEN
++              log(L_DEBUG|L_XFER, "<transmit_deauth 7>\n");
++              acx_l_transmit_deauthen(adev, ebx,
++                      WLAN_MGMT_REASON_CLASS2_NONAUTH);
++#else
++              log(L_DEBUG, "received NULL frame from unknown client! "
++                      "We really shouldn't send deauthen here, right?\n");
++#endif
++              result = OK;
++      }
++done:
++      return result;
++}
++#endif
++
++
++/***********************************************************************
++** acx_l_process_probe_response
++*/
++static int
++acx_l_process_probe_response(acx_device_t *adev, wlan_fr_proberesp_t *req,
++                      const rxbuffer_t *rxbuf)
++{
++      struct client *bss;
++      wlan_hdr_t *hdr;
++
++      FN_ENTER;
++
++      hdr = req->hdr;
++
++      if (mac_is_equal(hdr->a3, adev->dev_addr)) {
++              log(L_ASSOC, "huh, scan found our own MAC!?\n");
++              goto ok; /* just skip this one silently */
++      }
++
++      bss = acx_l_sta_list_get_or_add(adev, hdr->a2);
++
++      /* NB: be careful modifying bss data! It may be one
++      ** of the already known clients (like our AP if we are a STA)
++      ** Thus do not blindly modify e.g. current ratemask! */
++
++      if (STA_LIST_ADD_CAN_FAIL && !bss) {
++              /* uh oh, we found more sites/stations than we can handle with
++               * our current setup: pull the emergency brake and stop scanning! */
++              acx_schedule_task(adev, ACX_AFTER_IRQ_CMD_STOP_SCAN);
++              /* TODO: a nice comment what below call achieves --vda */
++              acx_set_status(adev, ACX_STATUS_2_WAIT_AUTH);
++              goto ok;
++      }
++      /* NB: get_or_add already filled bss->address = hdr->a2 */
++      MAC_COPY(bss->bssid, hdr->a3);
++
++      /* copy the ESSID element */
++      if (req->ssid && req->ssid->len <= IW_ESSID_MAX_SIZE) {
++              bss->essid_len = req->ssid->len;
++              memcpy(bss->essid, req->ssid->ssid, req->ssid->len);
++              bss->essid[req->ssid->len] = '\0';
++      } else {
++              /* Either no ESSID IE or oversized one */
++              printk("%s: received packet has bogus ESSID\n",
++                                                  adev->ndev->name);
++      }
++
++      if (req->ds_parms)
++              bss->channel = req->ds_parms->curr_ch;
++      if (req->cap_info)
++              bss->cap_info = ieee2host16(*req->cap_info);
++
++      bss->sir = acx_signal_to_winlevel(rxbuf->phy_level);
++      bss->snr = acx_signal_to_winlevel(rxbuf->phy_snr);
++
++      bss->rate_cap = 0;      /* operational mask */
++      bss->rate_bas = 0;      /* basic mask */
++      if (req->supp_rates)
++              add_bits_to_ratemasks(req->supp_rates->rates,
++                      req->supp_rates->len, &bss->rate_bas, &bss->rate_cap);
++      if (req->ext_rates)
++              add_bits_to_ratemasks(req->ext_rates->rates,
++                      req->ext_rates->len, &bss->rate_bas, &bss->rate_cap);
++      /* Fix up any possible bogosity - code elsewhere
++       * is not expecting empty masks */
++      if (!bss->rate_cap)
++              bss->rate_cap = adev->rate_basic;
++      if (!bss->rate_bas)
++              bss->rate_bas = 1 << lowest_bit(bss->rate_cap);
++      if (!bss->rate_cur)
++              bss->rate_cur = 1 << lowest_bit(bss->rate_bas);
++
++      /* People moan about this being too noisy at L_ASSOC */
++      log(L_DEBUG,
++              "found %s: ESSID=\"%s\" ch=%d "
++              "BSSID="MACSTR" caps=0x%04X SIR=%d SNR=%d\n",
++              (bss->cap_info & WF_MGMT_CAP_IBSS) ? "Ad-Hoc peer" : "AP",
++              bss->essid, bss->channel, MAC(bss->bssid), bss->cap_info,
++              bss->sir, bss->snr);
++ok:
++      FN_EXIT0;
++      return OK;
++}
++
++
++/***********************************************************************
++** acx_l_process_assocresp
++*/
++static int
++acx_l_process_assocresp(acx_device_t *adev, const wlan_fr_assocresp_t *req)
++{
++      const wlan_hdr_t *hdr;
++      int res = OK;
++
++      FN_ENTER;
++
++      hdr = req->hdr;
++
++      if ((ACX_MODE_2_STA == adev->mode)
++       && mac_is_equal(adev->dev_addr, hdr->a1)) {
++              u16 st = ieee2host16(*(req->status));
++              if (WLAN_MGMT_STATUS_SUCCESS == st) {
++                      adev->aid = ieee2host16(*(req->aid));
++                      /* tell the card we are associated when
++                      ** we are out of interrupt context */
++                      acx_schedule_task(adev, ACX_AFTER_IRQ_CMD_ASSOCIATE);
++              } else {
++
++                      /* TODO: we shall delete peer from sta_list, and try
++                      ** other candidates... */
++
++                      printk("%s: association FAILED: peer sent "
++                              "Status Code %d (%s)\n",
++                              adev->ndev->name, st, get_status_string(st));
++                      res = NOT_OK;
++              }
++      }
++
++      FN_EXIT1(res);
++      return res;
++}
++
++
++/***********************************************************************
++** acx_l_process_reassocresp
++*/
++static int
++acx_l_process_reassocresp(acx_device_t *adev, const wlan_fr_reassocresp_t *req)
++{
++      const wlan_hdr_t *hdr;
++      int result = NOT_OK;
++      u16 st;
++
++      FN_ENTER;
++
++      hdr = req->hdr;
++
++      if (!mac_is_equal(adev->dev_addr, hdr->a1)) {
++              goto end;
++      }
++      st = ieee2host16(*(req->status));
++      if (st == WLAN_MGMT_STATUS_SUCCESS) {
++              acx_set_status(adev, ACX_STATUS_4_ASSOCIATED);
++              result = OK;
++      } else {
++              printk("%s: reassociation FAILED: peer sent "
++                      "response code %d (%s)\n",
++                      adev->ndev->name, st, get_status_string(st));
++      }
++end:
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/***********************************************************************
++** acx_l_process_authen
++**
++** Called only in STA_SCAN or AP mode
++*/
++static int
++acx_l_process_authen(acx_device_t *adev, const wlan_fr_authen_t *req)
++{
++      const wlan_hdr_t *hdr;
++      client_t *clt;
++      wlan_ie_challenge_t *chal;
++      u16 alg, seq, status;
++      int ap, result;
++
++      FN_ENTER;
++
++      hdr = req->hdr;
++
++      if (acx_debug & L_ASSOC) {
++              acx_print_mac("AUTHEN adev->addr=", adev->dev_addr, " ");
++              acx_print_mac("a1=", hdr->a1, " ");
++              acx_print_mac("a2=", hdr->a2, " ");
++              acx_print_mac("a3=", hdr->a3, " ");
++              acx_print_mac("adev->bssid=", adev->bssid, "\n");
++      }
++
++      if (!mac_is_equal(adev->dev_addr, hdr->a1)
++       || !mac_is_equal(adev->bssid, hdr->a3)) {
++              result = OK;
++              goto end;
++      }
++
++      alg = ieee2host16(*(req->auth_alg));
++      seq = ieee2host16(*(req->auth_seq));
++      status = ieee2host16(*(req->status));
++
++      log(L_ASSOC, "auth algorithm %d, auth sequence %d, status %d\n", alg, seq, status);
++
++      ap = (adev->mode == ACX_MODE_3_AP);
++
++      if (adev->auth_alg <= 1) {
++              if (adev->auth_alg != alg) {
++                      log(L_ASSOC, "auth algorithm mismatch: "
++                              "our:%d peer:%d\n", adev->auth_alg, alg);
++                      result = NOT_OK;
++                      goto end;
++              }
++      }
++      if (ap) {
++              clt = acx_l_sta_list_get_or_add(adev, hdr->a2);
++              if (STA_LIST_ADD_CAN_FAIL && !clt) {
++                      log(L_ASSOC, "could not allocate room for client\n");
++                      result = NOT_OK;
++                      goto end;
++              }
++      } else {
++              clt = adev->ap_client;
++              if (!mac_is_equal(clt->address, hdr->a2)) {
++                      printk("%s: malformed auth frame from AP?!\n",
++                                      adev->ndev->name);
++                      result = NOT_OK;
++                      goto end;
++              }
++      }
++
++      /* now check which step in the authentication sequence we are
++       * currently in, and act accordingly */
++      switch (seq) {
++      case 1:
++              if (!ap)
++                      break;
++              acx_l_transmit_authen2(adev, req, clt);
++              break;
++      case 2:
++              if (ap)
++                      break;
++              if (status == WLAN_MGMT_STATUS_SUCCESS) {
++                      if (alg == WLAN_AUTH_ALG_OPENSYSTEM) {
++                              acx_set_status(adev, ACX_STATUS_3_AUTHENTICATED);
++                              acx_l_transmit_assoc_req(adev);
++                      } else
++                      if (alg == WLAN_AUTH_ALG_SHAREDKEY) {
++                              acx_l_transmit_authen3(adev, req);
++                      }
++              } else {
++                      printk("%s: auth FAILED: peer sent "
++                              "response code %d (%s), "
++                              "still waiting for authentication\n",
++                              adev->ndev->name,
++                              status, get_status_string(status));
++                      acx_set_status(adev, ACX_STATUS_2_WAIT_AUTH);
++              }
++              break;
++      case 3:
++              if (!ap)
++                      break;
++              if ((clt->auth_alg != WLAN_AUTH_ALG_SHAREDKEY)
++               || (alg != WLAN_AUTH_ALG_SHAREDKEY)
++               || (clt->auth_step != 2))
++                      break;
++              chal = req->challenge;
++              if (!chal
++               || memcmp(chal->challenge, clt->challenge_text, WLAN_CHALLENGE_LEN)
++               || (chal->eid != WLAN_EID_CHALLENGE)
++               || (chal->len != WLAN_CHALLENGE_LEN)
++              )
++                      break;
++              acx_l_transmit_authen4(adev, req);
++              MAC_COPY(clt->address, hdr->a2);
++              clt->used = CLIENT_AUTHENTICATED_2;
++              clt->auth_step = 4;
++              clt->seq = ieee2host16(hdr->seq);
++              break;
++      case 4:
++              if (ap)
++                      break;
++              /* ok, we're through: we're authenticated. Woohoo!! */
++              acx_set_status(adev, ACX_STATUS_3_AUTHENTICATED);
++              log(L_ASSOC, "Authenticated!\n");
++              /* now that we're authenticated, request association */
++              acx_l_transmit_assoc_req(adev);
++              break;
++      }
++      result = OK;
++end:
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/***********************************************************************
++** acx_gen_challenge
++*/
++static inline void
++acx_gen_challenge(wlan_ie_challenge_t* d)
++{
++      FN_ENTER;
++      d->eid = WLAN_EID_CHALLENGE;
++      d->len = WLAN_CHALLENGE_LEN;
++      get_random_bytes(d->challenge, WLAN_CHALLENGE_LEN);
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++** acx_l_transmit_deauthen
++*/
++static int
++acx_l_transmit_deauthen(acx_device_t *adev, const u8 *addr, u16 reason)
++{
++      struct tx *tx;
++      struct wlan_hdr_mgmt *head;
++      struct deauthen_frame_body *body;
++
++      FN_ENTER;
++
++      tx = acx_l_alloc_tx(adev);
++      if (!tx)
++              goto bad;
++      head = acx_l_get_txbuf(adev, tx);
++      if (!head) {
++              acx_l_dealloc_tx(adev, tx);
++              goto bad;
++      }
++      body = (void*)(head + 1);
++
++      head->fc = (WF_FTYPE_MGMTi | WF_FSTYPE_DEAUTHENi);
++      head->dur = 0;
++      MAC_COPY(head->da, addr);
++      MAC_COPY(head->sa, adev->dev_addr);
++      MAC_COPY(head->bssid, adev->bssid);
++      head->seq = 0;
++
++      log(L_DEBUG|L_ASSOC|L_XFER,
++              "sending deauthen to "MACSTR" for %d\n",
++              MAC(addr), reason);
++
++      body->reason = host2ieee16(reason);
++
++      /* body is fixed size here, but beware of cutting-and-pasting this -
++      ** do not use sizeof(*body) for variable sized mgmt packets! */
++      acx_l_tx_data(adev, tx, WLAN_HDR_A3_LEN + sizeof(*body));
++
++      FN_EXIT1(OK);
++      return OK;
++bad:
++      FN_EXIT1(NOT_OK);
++      return NOT_OK;
++}
++
++
++/***********************************************************************
++** acx_l_transmit_authen1
++*/
++static int
++acx_l_transmit_authen1(acx_device_t *adev)
++{
++      struct tx *tx;
++      struct wlan_hdr_mgmt *head;
++      struct auth_frame_body *body;
++
++      FN_ENTER;
++
++      log(L_ASSOC, "sending authentication1 request (auth algo %d), "
++              "awaiting response\n", adev->auth_alg);
++
++      tx = acx_l_alloc_tx(adev);
++      if (!tx)
++              goto bad;
++      head = acx_l_get_txbuf(adev, tx);
++      if (!head) {
++              acx_l_dealloc_tx(adev, tx);
++              goto bad;
++      }
++      body = (void*)(head + 1);
++
++      head->fc = WF_FSTYPE_AUTHENi;
++      /* duration should be 0 instead of 0x8000 to have
++       * the firmware calculate the value, right? */
++      head->dur = 0;
++      MAC_COPY(head->da, adev->bssid);
++      MAC_COPY(head->sa, adev->dev_addr);
++      MAC_COPY(head->bssid, adev->bssid);
++      head->seq = 0;
++
++      body->auth_alg = host2ieee16(adev->auth_alg);
++      body->auth_seq = host2ieee16(1);
++      body->status = host2ieee16(0);
++
++      acx_l_tx_data(adev, tx, WLAN_HDR_A3_LEN + 2 + 2 + 2);
++
++      FN_EXIT1(OK);
++      return OK;
++bad:
++      FN_EXIT1(NOT_OK);
++      return NOT_OK;
++}
++
++
++/***********************************************************************
++** acx_l_transmit_authen2
++*/
++static int
++acx_l_transmit_authen2(acx_device_t *adev, const wlan_fr_authen_t *req,
++                    client_t *clt)
++{
++      struct tx *tx;
++      struct wlan_hdr_mgmt *head;
++      struct auth_frame_body *body;
++      unsigned int packet_len;
++
++      FN_ENTER;
++
++      if (!clt)
++              goto ok;
++
++      MAC_COPY(clt->address, req->hdr->a2);
++#ifdef UNUSED
++      clt->ps = ((WF_FC_PWRMGTi & req->hdr->fc) != 0);
++#endif
++      clt->auth_alg = ieee2host16(*(req->auth_alg));
++      clt->auth_step = 2;
++      clt->seq = ieee2host16(req->hdr->seq);
++
++      tx = acx_l_alloc_tx(adev);
++      if (!tx)
++              goto bad;
++      head = acx_l_get_txbuf(adev, tx);
++      if (!head) {
++              acx_l_dealloc_tx(adev, tx);
++              goto bad;
++      }
++      body = (void*)(head + 1);
++
++      head->fc = WF_FSTYPE_AUTHENi;
++      head->dur = 0 /* req->hdr->dur */;
++      MAC_COPY(head->da, req->hdr->a2);
++      MAC_COPY(head->sa, adev->dev_addr);
++      MAC_COPY(head->bssid, req->hdr->a3);
++      head->seq = 0 /* req->hdr->seq */;
++
++      /* already in IEEE format, no endianness conversion */
++      body->auth_alg = *(req->auth_alg);
++      body->auth_seq = host2ieee16(2);
++      body->status = host2ieee16(0);
++
++      packet_len = WLAN_HDR_A3_LEN + 2 + 2 + 2;
++      if (ieee2host16(*(req->auth_alg)) == WLAN_AUTH_ALG_OPENSYSTEM) {
++              clt->used = CLIENT_AUTHENTICATED_2;
++      } else {        /* shared key */
++              acx_gen_challenge(&body->challenge);
++              memcpy(&clt->challenge_text, body->challenge.challenge, WLAN_CHALLENGE_LEN);
++              packet_len += 2 + 2 + 2 + 1+1+WLAN_CHALLENGE_LEN;
++      }
++
++      acxlog_mac(L_ASSOC|L_XFER,
++              "transmit_auth2: BSSID=", head->bssid, "\n");
++
++      acx_l_tx_data(adev, tx, packet_len);
++ok:
++      FN_EXIT1(OK);
++      return OK;
++bad:
++      FN_EXIT1(NOT_OK);
++      return NOT_OK;
++}
++
++
++/***********************************************************************
++** acx_l_transmit_authen3
++*/
++static int
++acx_l_transmit_authen3(acx_device_t *adev, const wlan_fr_authen_t *req)
++{
++      struct tx *tx;
++      struct wlan_hdr_mgmt *head;
++      struct auth_frame_body *body;
++      unsigned int packet_len;
++
++      FN_ENTER;
++
++      tx = acx_l_alloc_tx(adev);
++      if (!tx)
++              goto ok;
++      head = acx_l_get_txbuf(adev, tx);
++      if (!head) {
++              acx_l_dealloc_tx(adev, tx);
++              goto ok;
++      }
++      body = (void*)(head + 1);
++
++      /* add WF_FC_ISWEPi: auth step 3 needs to be encrypted */
++      head->fc = WF_FC_ISWEPi + WF_FSTYPE_AUTHENi;
++      /* FIXME: is this needed?? authen4 does it...
++       * I think it's even wrong since we shouldn't re-use old
++       * values but instead let the firmware calculate proper ones
++      head->dur = req->hdr->dur;
++      head->seq = req->hdr->seq;
++      */
++      MAC_COPY(head->da, adev->bssid);
++      MAC_COPY(head->sa, adev->dev_addr);
++      MAC_COPY(head->bssid, adev->bssid);
++
++      /* already in IEEE format, no endianness conversion */
++      body->auth_alg = *(req->auth_alg);
++      body->auth_seq = host2ieee16(3);
++      body->status = host2ieee16(0);
++      memcpy(&body->challenge, req->challenge, req->challenge->len + 2);
++      packet_len = WLAN_HDR_A3_LEN + 8 + req->challenge->len;
++
++      log(L_ASSOC|L_XFER, "transmit_authen3!\n");
++
++      acx_l_tx_data(adev, tx, packet_len);
++ok:
++      FN_EXIT1(OK);
++      return OK;
++}
++
++
++/***********************************************************************
++** acx_l_transmit_authen4
++*/
++static int
++acx_l_transmit_authen4(acx_device_t *adev, const wlan_fr_authen_t *req)
++{
++      struct tx *tx;
++      struct wlan_hdr_mgmt *head;
++      struct auth_frame_body *body;
++
++      FN_ENTER;
++
++      tx = acx_l_alloc_tx(adev);
++      if (!tx)
++              goto ok;
++      head = acx_l_get_txbuf(adev, tx);
++      if (!head) {
++              acx_l_dealloc_tx(adev, tx);
++              goto ok;
++      }
++      body = (void*)(head + 1);
++
++      head->fc = WF_FSTYPE_AUTHENi; /* 0xb0 */
++      head->dur = 0 /* req->hdr->dur */;
++      MAC_COPY(head->da, req->hdr->a2);
++      MAC_COPY(head->sa, adev->dev_addr);
++      MAC_COPY(head->bssid, req->hdr->a3);
++      head->seq = 0 /* req->hdr->seq  */;
++
++      /* already in IEEE format, no endianness conversion */
++      body->auth_alg = *(req->auth_alg);
++      body->auth_seq = host2ieee16(4);
++      body->status = host2ieee16(0);
++
++      acx_l_tx_data(adev, tx, WLAN_HDR_A3_LEN + 2 + 2 + 2);
++ok:
++      FN_EXIT1(OK);
++      return OK;
++}
++
++
++/***********************************************************************
++** acx_l_transmit_assoc_req
++**
++** adev->ap_client is a current candidate AP here
++*/
++static int
++acx_l_transmit_assoc_req(acx_device_t *adev)
++{
++      struct tx *tx;
++      struct wlan_hdr_mgmt *head;
++      u8 *body, *p, *prate;
++      unsigned int packet_len;
++      u16 cap;
++
++      FN_ENTER;
++
++      log(L_ASSOC, "sending association request, "
++                      "awaiting response. NOT ASSOCIATED YET\n");
++      tx = acx_l_alloc_tx(adev);
++      if (!tx)
++              goto bad;
++      head = acx_l_get_txbuf(adev, tx);
++      if (!head) {
++              acx_l_dealloc_tx(adev, tx);
++              goto bad;
++      }
++      body = (void*)(head + 1);
++
++      head->fc = WF_FSTYPE_ASSOCREQi;
++      head->dur = host2ieee16(0x8000);
++      MAC_COPY(head->da, adev->bssid);
++      MAC_COPY(head->sa, adev->dev_addr);
++      MAC_COPY(head->bssid, adev->bssid);
++      head->seq = 0;
++
++      p = body;
++      /* now start filling the AssocReq frame body */
++
++      /* since this assoc request will most likely only get
++       * sent in the STA to AP case (and not when Ad-Hoc IBSS),
++       * the cap combination indicated here will thus be
++       * WF_MGMT_CAP_ESSi *always* (no IBSS ever)
++       * The specs are more than non-obvious on all that:
++       *
++       * 802.11 7.3.1.4 Capability Information field
++      ** APs set the ESS subfield to 1 and the IBSS subfield to 0 within
++      ** Beacon or Probe Response management frames. STAs within an IBSS
++      ** set the ESS subfield to 0 and the IBSS subfield to 1 in transmitted
++      ** Beacon or Probe Response management frames
++      **
++      ** APs set the Privacy subfield to 1 within transmitted Beacon,
++      ** Probe Response, Association Response, and Reassociation Response
++      ** if WEP is required for all data type frames within the BSS.
++      ** STAs within an IBSS set the Privacy subfield to 1 in Beacon
++      ** or Probe Response management frames if WEP is required
++      ** for all data type frames within the IBSS */
++
++      /* note that returning 0 will be refused by several APs...
++       * (so this indicates that you're probably supposed to
++       * "confirm" the ESS mode) */
++      cap = WF_MGMT_CAP_ESSi;
++
++      /* this one used to be a check on wep_restricted,
++       * but more likely it's wep_enabled instead */
++      if (adev->wep_enabled)
++              SET_BIT(cap, WF_MGMT_CAP_PRIVACYi);
++
++      /* Probably we can just set these always, because our hw is
++      ** capable of shortpre and PBCC --vda */
++      /* only ask for short preamble if the peer station supports it */
++      if (adev->ap_client->cap_info & WF_MGMT_CAP_SHORT)
++              SET_BIT(cap, WF_MGMT_CAP_SHORTi);
++      /* only ask for PBCC support if the peer station supports it */
++      if (adev->ap_client->cap_info & WF_MGMT_CAP_PBCC)
++              SET_BIT(cap, WF_MGMT_CAP_PBCCi);
++
++      /* IEs: 1. caps */
++      *(u16*)p = cap; p += 2;
++      /* 2. listen interval */
++      *(u16*)p = host2ieee16(adev->listen_interval); p += 2;
++      /* 3. ESSID */
++      p = wlan_fill_ie_ssid(p,
++                      strlen(adev->essid_for_assoc), adev->essid_for_assoc);
++      /* 4. supp rates */
++      prate = p;
++      p = wlan_fill_ie_rates(p,
++                      adev->rate_supported_len, adev->rate_supported);
++      /* 5. ext supp rates */
++      p = wlan_fill_ie_rates_ext(p,
++                      adev->rate_supported_len, adev->rate_supported);
++
++      if (acx_debug & L_DEBUG) {
++              printk("association: rates element\n");
++              acx_dump_bytes(prate, p - prate);
++      }
++
++      /* calculate lengths */
++      packet_len = WLAN_HDR_A3_LEN + (p - body);
++
++      log(L_ASSOC, "association: requesting caps 0x%04X, ESSID \"%s\"\n",
++              cap, adev->essid_for_assoc);
++
++      acx_l_tx_data(adev, tx, packet_len);
++      FN_EXIT1(OK);
++      return OK;
++bad:
++      FN_EXIT1(NOT_OK);
++      return NOT_OK;
++}
++
++
++/***********************************************************************
++** acx_l_transmit_disassoc
++**
++** FIXME: looks like incomplete implementation of a helper:
++** acx_l_transmit_disassoc(adev, clt) - kick this client (we're an AP)
++** acx_l_transmit_disassoc(adev, NULL) - leave BSSID (we're a STA)
++*/
++#ifdef BROKEN
++int
++acx_l_transmit_disassoc(acx_device_t *adev, client_t *clt)
++{
++      struct tx *tx;
++      struct wlan_hdr_mgmt *head;
++      struct disassoc_frame_body *body;
++
++      FN_ENTER;
++/*    if (clt != NULL) { */
++              tx = acx_l_alloc_tx(adev);
++              if (!tx)
++                      goto bad;
++              head = acx_l_get_txbuf(adev, tx);
++              if (!head) {
++                      acx_l_dealloc_tx(adev, tx);
++                      goto bad;
++              }
++              body = (void*)(head + 1);
++
++/*            clt->used = CLIENT_AUTHENTICATED_2; - not (yet?) associated */
++
++              head->fc = WF_FSTYPE_DISASSOCi;
++              head->dur = 0;
++              /* huh? It muchly depends on whether we're STA or AP...
++              ** sta->ap: da=bssid, sa=own, bssid=bssid
++              ** ap->sta: da=sta, sa=bssid, bssid=bssid. FIXME! */
++              MAC_COPY(head->da, adev->bssid);
++              MAC_COPY(head->sa, adev->dev_addr);
++              MAC_COPY(head->bssid, adev->dev_addr);
++              head->seq = 0;
++
++              /* "Class 3 frame received from nonassociated station." */
++              body->reason = host2ieee16(7);
++
++              /* fixed size struct, ok to sizeof */
++              acx_l_tx_data(adev, tx, WLAN_HDR_A3_LEN + sizeof(*body));
++/*    } */
++      FN_EXIT1(OK);
++      return OK;
++bad:
++      FN_EXIT1(NOT_OK);
++      return NOT_OK;
++}
++#endif
++
++
++/***********************************************************************
++** acx_s_complete_scan
++**
++** Called either from after_interrupt_task() if:
++** 1) there was Scan_Complete IRQ, or
++** 2) scanning expired in timer()
++** We need to decide which ESS or IBSS to join.
++** Iterates thru adev->sta_list:
++**    if adev->ap is not bcast, will join only specified
++**    ESS or IBSS with this bssid
++**    checks peers' caps for ESS/IBSS bit
++**    checks peers' SSID, allows exact match or hidden SSID
++** If station to join is chosen:
++**    points adev->ap_client to the chosen struct client
++**    sets adev->essid_for_assoc for future assoc attempt
++** Auth/assoc is not yet performed
++** Returns OK if there is no need to restart scan
++*/
++int
++acx_s_complete_scan(acx_device_t *adev)
++{
++      struct client *bss;
++      unsigned long flags;
++      u16 needed_cap;
++      int i;
++      int idx_found = -1;
++      int result = OK;
++
++      FN_ENTER;
++
++      switch (adev->mode) {
++      case ACX_MODE_0_ADHOC:
++              needed_cap = WF_MGMT_CAP_IBSS; /* 2, we require Ad-Hoc */
++              break;
++      case ACX_MODE_2_STA:
++              needed_cap = WF_MGMT_CAP_ESS; /* 1, we require Managed */
++              break;
++      default:
++              printk("acx: driver bug: mode=%d in complete_scan()\n", adev->mode);
++              dump_stack();
++              goto end;
++      }
++
++      acx_lock(adev, flags);
++
++      /* TODO: sta_iterator hiding implementation would be nice here... */
++
++      for (i = 0; i < VEC_SIZE(adev->sta_list); i++) {
++              bss = &adev->sta_list[i];
++              if (!bss->used) continue;
++
++
++              log(L_ASSOC, "scan table: SSID=\"%s\" CH=%d SIR=%d SNR=%d\n",
++                      bss->essid, bss->channel, bss->sir, bss->snr);
++
++              if (!mac_is_bcast(adev->ap))
++                      if (!mac_is_equal(bss->bssid, adev->ap))
++                              continue; /* keep looking */
++
++              /* broken peer with no mode flags set? */
++              if (unlikely(!(bss->cap_info & (WF_MGMT_CAP_ESS | WF_MGMT_CAP_IBSS)))) {
++                      printk("%s: strange peer "MACSTR" found with "
++                              "neither ESS (AP) nor IBSS (Ad-Hoc) "
++                              "capability - skipped\n",
++                              adev->ndev->name, MAC(bss->address));
++                      continue;
++              }
++              log(L_ASSOC, "peer_cap 0x%04X, needed_cap 0x%04X\n",
++                     bss->cap_info, needed_cap);
++
++              /* does peer station support what we need? */
++              if ((bss->cap_info & needed_cap) != needed_cap)
++                      continue; /* keep looking */
++
++              /* strange peer with NO basic rates?! */
++              if (unlikely(!bss->rate_bas)) {
++                      printk("%s: strange peer "MACSTR" with empty rate set "
++                              "- skipped\n",
++                              adev->ndev->name, MAC(bss->address));
++                      continue;
++              }
++
++              /* do we support all basic rates of this peer? */
++              if ((bss->rate_bas & adev->rate_oper) != bss->rate_bas) {
++/* we probably need to have all rates as operational rates,
++   even in case of an 11M-only configuration */
++#ifdef THIS_IS_TROUBLESOME
++                      printk("%s: peer "MACSTR": incompatible basic rates "
++                              "(AP requests 0x%04X, we have 0x%04X) "
++                              "- skipped\n",
++                              adev->ndev->name, MAC(bss->address),
++                              bss->rate_bas, adev->rate_oper);
++                      continue;
++#else
++                      printk("%s: peer "MACSTR": incompatible basic rates "
++                              "(AP requests 0x%04X, we have 0x%04X). "
++                              "Considering anyway...\n",
++                              adev->ndev->name, MAC(bss->address),
++                              bss->rate_bas, adev->rate_oper);
++#endif
++              }
++
++              if ( !(adev->reg_dom_chanmask & (1<<(bss->channel-1))) ) {
++                      printk("%s: warning: peer "MACSTR" is on channel %d "
++                              "outside of channel range of current "
++                              "regulatory domain - couldn't join "
++                              "even if other settings match. "
++                              "You might want to adapt your config\n",
++                              adev->ndev->name, MAC(bss->address),
++                              bss->channel);
++                      continue; /* keep looking */
++              }
++
++              if (!adev->essid_active || !strcmp(bss->essid, adev->essid)) {
++                      log(L_ASSOC,
++                             "found station with matching ESSID! ('%s' "
++                             "station, '%s' config)\n",
++                             bss->essid,
++                             (adev->essid_active) ? adev->essid : "[any]");
++                      /* TODO: continue looking for peer with better SNR */
++                      bss->used = CLIENT_JOIN_CANDIDATE;
++                      idx_found = i;
++
++                      /* stop searching if this station is
++                       * on the current channel, otherwise
++                       * keep looking for an even better match */
++                      if (bss->channel == adev->channel)
++                              break;
++              } else
++              if (is_hidden_essid(bss->essid)) {
++                      /* hmm, station with empty or single-space SSID:
++                       * using hidden SSID broadcast?
++                       */
++                      /* This behaviour is broken: which AP from zillion
++                      ** of APs with hidden SSID you'd try?
++                      ** We should use Probe requests to get Probe responses
++                      ** and check for real SSID (are those never hidden?) */
++                      bss->used = CLIENT_JOIN_CANDIDATE;
++                      if (idx_found == -1)
++                              idx_found = i;
++                      log(L_ASSOC, "found station with empty or "
++                              "single-space (hidden) SSID, considering "
++                              "for assoc attempt\n");
++                      /* ...and keep looking for better matches */
++              } else {
++                      log(L_ASSOC, "ESSID doesn't match! ('%s' "
++                              "station, '%s' config)\n",
++                              bss->essid,
++                              (adev->essid_active) ? adev->essid : "[any]");
++              }
++      }
++
++      /* TODO: iterate thru join candidates instead */
++      /* TODO: rescan if not associated within some timeout */
++      if (idx_found != -1) {
++              char *essid_src;
++              size_t essid_len;
++
++              bss = &adev->sta_list[idx_found];
++              adev->ap_client = bss;
++
++              if (is_hidden_essid(bss->essid)) {
++                      /* if the ESSID of the station we found is empty
++                       * (no broadcast), then use user-configured ESSID
++                       * instead */
++                      essid_src = adev->essid;
++                      essid_len = adev->essid_len;
++              } else {
++                      essid_src = bss->essid;
++                      essid_len = strlen(bss->essid);
++              }
++
++              acx_update_capabilities(adev);
++
++              memcpy(adev->essid_for_assoc, essid_src, essid_len);
++              adev->essid_for_assoc[essid_len] = '\0';
++              adev->channel = bss->channel;
++              MAC_COPY(adev->bssid, bss->bssid);
++
++              bss->rate_cfg = (bss->rate_cap & adev->rate_oper);
++              bss->rate_cur = 1 << lowest_bit(bss->rate_cfg);
++              bss->rate_100 = acx_rate111to100(bss->rate_cur);
++
++              acxlog_mac(L_ASSOC,
++                      "matching station found: ", adev->bssid, ", joining\n");
++
++              /* TODO: do we need to switch to the peer's channel first? */
++
++              if (ACX_MODE_0_ADHOC == adev->mode) {
++                      acx_set_status(adev, ACX_STATUS_4_ASSOCIATED);
++              } else {
++                      acx_l_transmit_authen1(adev);
++                      acx_set_status(adev, ACX_STATUS_2_WAIT_AUTH);
++              }
++      } else { /* idx_found == -1 */
++              /* uh oh, no station found in range */
++              if (ACX_MODE_0_ADHOC == adev->mode) {
++                      printk("%s: no matching station found in range, "
++                              "generating our own IBSS instead\n",
++                              adev->ndev->name);
++                      /* we do it the HostAP way: */
++                      MAC_COPY(adev->bssid, adev->dev_addr);
++                      adev->bssid[0] |= 0x02; /* 'local assigned addr' bit */
++                      /* add IBSS bit to our caps... */
++                      acx_update_capabilities(adev);
++                      acx_set_status(adev, ACX_STATUS_4_ASSOCIATED);
++                      /* In order to cmd_join be called below */
++                      idx_found = 0;
++              } else {
++                      /* we shall scan again, AP can be
++                      ** just temporarily powered off */
++                      log(L_ASSOC,
++                              "no matching station found in range yet\n");
++                      acx_set_status(adev, ACX_STATUS_1_SCANNING);
++                      result = NOT_OK;
++              }
++      }
++
++      acx_unlock(adev, flags);
++
++      if (idx_found != -1) {
++              if (ACX_MODE_0_ADHOC == adev->mode) {
++                      /* need to update channel in beacon template */
++                      SET_BIT(adev->set_mask, SET_TEMPLATES);
++                      if (ACX_STATE_IFACE_UP & adev->dev_state_mask)
++                              acx_s_update_card_settings(adev);
++              }
++              /* Inform firmware on our decision to start or join BSS */
++              acx_s_cmd_join_bssid(adev, adev->bssid);
++      }
++
++end:
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/***********************************************************************
++** acx_s_read_fw
++**
++** Loads a firmware image
++**
++** Returns:
++**  0                         unable to load file
++**  pointer to firmware               success
++*/
++firmware_image_t*
++acx_s_read_fw(struct device *dev, const char *file, u32 *size)
++{
++      firmware_image_t *res;
++      const struct firmware *fw_entry;
++
++      res = NULL;
++      log(L_INIT, "requesting firmware image '%s'\n", file);
++      if (!request_firmware(&fw_entry, file, dev)) {
++              *size = 8;
++              if (fw_entry->size >= 8)
++                      *size = 8 + le32_to_cpu(*(u32 *)(fw_entry->data + 4));
++              if (fw_entry->size != *size) {
++                      printk("acx: firmware size does not match "
++                              "firmware header: %d != %d, "
++                              "aborting fw upload\n",
++                              (int) fw_entry->size, (int) *size);
++                      goto release_ret;
++              }
++              res = vmalloc(*size);
++              if (!res) {
++                      printk("acx: no memory for firmware "
++                              "(%u bytes)\n", *size);
++                      goto release_ret;
++              }
++              memcpy(res, fw_entry->data, fw_entry->size);
++release_ret:
++              release_firmware(fw_entry);
++              return res;
++      }
++      printk("acx: firmware image '%s' was not provided. "
++              "Check your hotplug scripts\n", file);
++
++      /* checksum will be verified in write_fw, so don't bother here */
++      return res;
++}
++
++
++/***********************************************************************
++** acx_s_set_wepkey
++*/
++static void
++acx100_s_set_wepkey(acx_device_t *adev)
++{
++      ie_dot11WEPDefaultKey_t dk;
++      int i;
++
++      for (i = 0; i < DOT11_MAX_DEFAULT_WEP_KEYS; i++) {
++              if (adev->wep_keys[i].size != 0) {
++                      log(L_INIT, "setting WEP key: %d with "
++                              "total size: %d\n", i, (int) adev->wep_keys[i].size);
++                      dk.action = 1;
++                      dk.keySize = adev->wep_keys[i].size;
++                      dk.defaultKeyNum = i;
++                      memcpy(dk.key, adev->wep_keys[i].key, dk.keySize);
++                      acx_s_configure(adev, &dk, ACX100_IE_DOT11_WEP_DEFAULT_KEY_WRITE);
++              }
++      }
++}
++
++static void
++acx111_s_set_wepkey(acx_device_t *adev)
++{
++      acx111WEPDefaultKey_t dk;
++      int i;
++
++      for (i = 0; i < DOT11_MAX_DEFAULT_WEP_KEYS; i++) {
++              if (adev->wep_keys[i].size != 0) {
++                      log(L_INIT, "setting WEP key: %d with "
++                              "total size: %d\n", i, (int) adev->wep_keys[i].size);
++                      memset(&dk, 0, sizeof(dk));
++                      dk.action = cpu_to_le16(1); /* "add key"; yes, that's a 16bit value */
++                      dk.keySize = adev->wep_keys[i].size;
++
++                      /* are these two lines necessary? */
++                      dk.type = 0;              /* default WEP key */
++                      dk.index = 0;             /* ignored when setting default key */
++
++                      dk.defaultKeyNum = i;
++                      memcpy(dk.key, adev->wep_keys[i].key, dk.keySize);
++                      acx_s_issue_cmd(adev, ACX1xx_CMD_WEP_MGMT, &dk, sizeof(dk));
++              }
++      }
++}
++
++static void
++acx_s_set_wepkey(acx_device_t *adev)
++{
++      if (IS_ACX111(adev))
++              acx111_s_set_wepkey(adev);
++      else
++              acx100_s_set_wepkey(adev);
++}
++
++
++/***********************************************************************
++** acx100_s_init_wep
++**
++** FIXME: this should probably be moved into the new card settings
++** management, but since we're also modifying the memory map layout here
++** due to the WEP key space we want, we should take care...
++*/
++static int
++acx100_s_init_wep(acx_device_t *adev)
++{
++      acx100_ie_wep_options_t options;
++      ie_dot11WEPDefaultKeyID_t dk;
++      acx_ie_memmap_t pt;
++      int res = NOT_OK;
++
++      FN_ENTER;
++
++      if (OK != acx_s_interrogate(adev, &pt, ACX1xx_IE_MEMORY_MAP)) {
++              goto fail;
++      }
++
++      log(L_DEBUG, "CodeEnd:%X\n", pt.CodeEnd);
++
++      pt.WEPCacheStart = cpu_to_le32(le32_to_cpu(pt.CodeEnd) + 0x4);
++      pt.WEPCacheEnd   = cpu_to_le32(le32_to_cpu(pt.CodeEnd) + 0x4);
++
++      if (OK != acx_s_configure(adev, &pt, ACX1xx_IE_MEMORY_MAP)) {
++              goto fail;
++      }
++
++      /* let's choose maximum setting: 4 default keys, plus 10 other keys: */
++      options.NumKeys = cpu_to_le16(DOT11_MAX_DEFAULT_WEP_KEYS + 10);
++      options.WEPOption = 0x00;
++
++      log(L_ASSOC, "%s: writing WEP options\n", __func__);
++      acx_s_configure(adev, &options, ACX100_IE_WEP_OPTIONS);
++
++      acx100_s_set_wepkey(adev);
++
++      if (adev->wep_keys[adev->wep_current_index].size != 0) {
++              log(L_ASSOC, "setting active default WEP key number: %d\n",
++                              adev->wep_current_index);
++              dk.KeyID = adev->wep_current_index;
++              acx_s_configure(adev, &dk, ACX1xx_IE_DOT11_WEP_DEFAULT_KEY_SET); /* 0x1010 */
++      }
++      /* FIXME!!! wep_key_struct is filled nowhere! But adev
++       * is initialized to 0, and we don't REALLY need those keys either */
++/*            for (i = 0; i < 10; i++) {
++              if (adev->wep_key_struct[i].len != 0) {
++                      MAC_COPY(wep_mgmt.MacAddr, adev->wep_key_struct[i].addr);
++                      wep_mgmt.KeySize = cpu_to_le16(adev->wep_key_struct[i].len);
++                      memcpy(&wep_mgmt.Key, adev->wep_key_struct[i].key, le16_to_cpu(wep_mgmt.KeySize));
++                      wep_mgmt.Action = cpu_to_le16(1);
++                      log(L_ASSOC, "writing WEP key %d (len %d)\n", i, le16_to_cpu(wep_mgmt.KeySize));
++                      if (OK == acx_s_issue_cmd(adev, ACX1xx_CMD_WEP_MGMT, &wep_mgmt, sizeof(wep_mgmt))) {
++                              adev->wep_key_struct[i].index = i;
++                      }
++              }
++      }
++*/
++
++      /* now retrieve the updated WEPCacheEnd pointer... */
++      if (OK != acx_s_interrogate(adev, &pt, ACX1xx_IE_MEMORY_MAP)) {
++              printk("%s: ACX1xx_IE_MEMORY_MAP read #2 FAILED\n",
++                              adev->ndev->name);
++              goto fail;
++      }
++      /* ...and tell it to start allocating templates at that location */
++      /* (no endianness conversion needed) */
++      pt.PacketTemplateStart = pt.WEPCacheEnd;
++
++      if (OK != acx_s_configure(adev, &pt, ACX1xx_IE_MEMORY_MAP)) {
++              printk("%s: ACX1xx_IE_MEMORY_MAP write #2 FAILED\n",
++                              adev->ndev->name);
++              goto fail;
++      }
++      res = OK;
++
++fail:
++      FN_EXIT1(res);
++      return res;
++}
++
++
++static int
++acx_s_init_max_template_generic(acx_device_t *adev, unsigned int len, unsigned int cmd)
++{
++      int res;
++      union {
++              acx_template_nullframe_t null;
++              acx_template_beacon_t b;
++              acx_template_tim_t tim;
++              acx_template_probereq_t preq;
++              acx_template_proberesp_t presp;
++      } templ;
++
++      memset(&templ, 0, len);
++      templ.null.size = cpu_to_le16(len - 2);
++      res = acx_s_issue_cmd(adev, cmd, &templ, len);
++      return res;
++}
++
++static inline int
++acx_s_init_max_null_data_template(acx_device_t *adev)
++{
++      return acx_s_init_max_template_generic(
++              adev, sizeof(acx_template_nullframe_t), ACX1xx_CMD_CONFIG_NULL_DATA
++      );
++}
++
++static inline int
++acx_s_init_max_beacon_template(acx_device_t *adev)
++{
++      return acx_s_init_max_template_generic(
++              adev, sizeof(acx_template_beacon_t), ACX1xx_CMD_CONFIG_BEACON
++      );
++}
++
++static inline int
++acx_s_init_max_tim_template(acx_device_t *adev)
++{
++      return acx_s_init_max_template_generic(
++              adev, sizeof(acx_template_tim_t), ACX1xx_CMD_CONFIG_TIM
++      );
++}
++
++static inline int
++acx_s_init_max_probe_response_template(acx_device_t *adev)
++{
++      return acx_s_init_max_template_generic(
++              adev, sizeof(acx_template_proberesp_t), ACX1xx_CMD_CONFIG_PROBE_RESPONSE
++      );
++}
++
++static inline int
++acx_s_init_max_probe_request_template(acx_device_t *adev)
++{
++      return acx_s_init_max_template_generic(
++              adev, sizeof(acx_template_probereq_t), ACX1xx_CMD_CONFIG_PROBE_REQUEST
++      );
++}
++
++/***********************************************************************
++** acx_s_set_tim_template
++**
++** FIXME: In full blown driver we will regularly update partial virtual bitmap
++** by calling this function
++** (it can be done by irq handler on each DTIM irq or by timer...)
++
++[802.11 7.3.2.6] TIM information element:
++- 1 EID
++- 1 Length
++1 1 DTIM Count
++    indicates how many beacons (including this) appear before next DTIM
++    (0=this one is a DTIM)
++2 1 DTIM Period
++    number of beacons between successive DTIMs
++    (0=reserved, 1=all TIMs are DTIMs, 2=every other, etc)
++3 1 Bitmap Control
++    bit0: Traffic Indicator bit associated with Assoc ID 0 (Bcast AID?)
++    set to 1 in TIM elements with a value of 0 in the DTIM Count field
++    when one or more broadcast or multicast frames are buffered at the AP.
++    bit1-7: Bitmap Offset (logically Bitmap_Offset = Bitmap_Control & 0xFE).
++4 n Partial Virtual Bitmap
++    Visible part of traffic-indication bitmap.
++    Full bitmap consists of 2008 bits (251 octets) such that bit number N
++    (0<=N<=2007) in the bitmap corresponds to bit number (N mod 8)
++    in octet number N/8 where the low-order bit of each octet is bit0,
++    and the high order bit is bit7.
++    Each set bit in virtual bitmap corresponds to traffic buffered by AP
++    for a specific station (with corresponding AID?).
++    Partial Virtual Bitmap shows a part of bitmap which has non-zero.
++    Bitmap Offset is a number of skipped zero octets (see above).
++    'Missing' octets at the tail are also assumed to be zero.
++    Example: Length=6, Bitmap_Offset=2, Partial_Virtual_Bitmap=55 55 55
++    This means that traffic-indication bitmap is:
++    00000000 00000000 01010101 01010101 01010101 00000000 00000000...
++    (is bit0 in the map is always 0 and real value is in Bitmap Control bit0?)
++*/
++static int
++acx_s_set_tim_template(acx_device_t *adev)
++{
++/* For now, configure smallish test bitmap, all zero ("no pending data") */
++      enum { bitmap_size = 5 };
++
++      acx_template_tim_t t;
++      int result;
++
++      FN_ENTER;
++
++      memset(&t, 0, sizeof(t));
++      t.size = 5 + bitmap_size; /* eid+len+count+period+bmap_ctrl + bmap */
++      t.tim_eid = WLAN_EID_TIM;
++      t.len = 3 + bitmap_size; /* count+period+bmap_ctrl + bmap */
++      result = acx_s_issue_cmd(adev, ACX1xx_CMD_CONFIG_TIM, &t, sizeof(t));
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/***********************************************************************
++** acx_fill_beacon_or_proberesp_template
++**
++** For frame format info, please see 802.11-1999.pdf item 7.2.3.9 and below!!
++**
++** NB: we use the fact that
++** struct acx_template_proberesp and struct acx_template_beacon are the same
++** (well, almost...)
++**
++** [802.11] Beacon's body consist of these IEs:
++** 1 Timestamp
++** 2 Beacon interval
++** 3 Capability information
++** 4 SSID
++** 5 Supported rates (up to 8 rates)
++** 6 FH Parameter Set (frequency-hopping PHYs only)
++** 7 DS Parameter Set (direct sequence PHYs only)
++** 8 CF Parameter Set (only if PCF is supported)
++** 9 IBSS Parameter Set (ad-hoc only)
++**
++** Beacon only:
++** 10 TIM (AP only) (see 802.11 7.3.2.6)
++** 11 Country Information (802.11d)
++** 12 FH Parameters (802.11d)
++** 13 FH Pattern Table (802.11d)
++** ... (?!! did not yet find relevant PDF file... --vda)
++** 19 ERP Information (extended rate PHYs)
++** 20 Extended Supported Rates (if more than 8 rates)
++**
++** Proberesp only:
++** 10 Country information (802.11d)
++** 11 FH Parameters (802.11d)
++** 12 FH Pattern Table (802.11d)
++** 13-n Requested information elements (802.11d)
++** ????
++** 18 ERP Information (extended rate PHYs)
++** 19 Extended Supported Rates (if more than 8 rates)
++*/
++static int
++acx_fill_beacon_or_proberesp_template(acx_device_t *adev,
++                                      struct acx_template_beacon *templ,
++                                      u16 fc /* in host order! */)
++{
++      int len;
++      u8 *p;
++
++      FN_ENTER;
++
++      memset(templ, 0, sizeof(*templ));
++      MAC_BCAST(templ->da);
++      MAC_COPY(templ->sa, adev->dev_addr);
++      MAC_COPY(templ->bssid, adev->bssid);
++
++      templ->beacon_interval = cpu_to_le16(adev->beacon_interval);
++      acx_update_capabilities(adev);
++      templ->cap = cpu_to_le16(adev->capabilities);
++
++      p = templ->variable;
++      p = wlan_fill_ie_ssid(p, adev->essid_len, adev->essid);
++      p = wlan_fill_ie_rates(p, adev->rate_supported_len, adev->rate_supported);
++      p = wlan_fill_ie_ds_parms(p, adev->channel);
++      /* NB: should go AFTER tim, but acx seem to keep tim last always */
++      p = wlan_fill_ie_rates_ext(p, adev->rate_supported_len, adev->rate_supported);
++
++      switch (adev->mode) {
++      case ACX_MODE_0_ADHOC:
++              /* ATIM window */
++              p = wlan_fill_ie_ibss_parms(p, 0); break;
++      case ACX_MODE_3_AP:
++              /* TIM IE is set up as separate template */
++              break;
++      }
++
++      len = p - (u8*)templ;
++      templ->fc = cpu_to_le16(WF_FTYPE_MGMT | fc);
++      /* - 2: do not count 'u16 size' field */
++      templ->size = cpu_to_le16(len - 2);
++
++      FN_EXIT1(len);
++      return len;
++}
++
++
++#if POWER_SAVE_80211
++/***********************************************************************
++** acx_s_set_null_data_template
++*/
++static int
++acx_s_set_null_data_template(acx_device_t *adev)
++{
++      struct acx_template_nullframe b;
++      int result;
++
++      FN_ENTER;
++
++      /* memset(&b, 0, sizeof(b)); not needed, setting all members */
++
++      b.size = cpu_to_le16(sizeof(b) - 2);
++      b.hdr.fc = WF_FTYPE_MGMTi | WF_FSTYPE_NULLi;
++      b.hdr.dur = 0;
++      MAC_BCAST(b.hdr.a1);
++      MAC_COPY(b.hdr.a2, adev->dev_addr);
++      MAC_COPY(b.hdr.a3, adev->bssid);
++      b.hdr.seq = 0;
++
++      result = acx_s_issue_cmd(adev, ACX1xx_CMD_CONFIG_NULL_DATA, &b, sizeof(b));
++
++      FN_EXIT1(result);
++      return result;
++}
++#endif
++
++
++/***********************************************************************
++** acx_s_set_beacon_template
++*/
++static int
++acx_s_set_beacon_template(acx_device_t *adev)
++{
++      struct acx_template_beacon bcn;
++      int len, result;
++
++      FN_ENTER;
++
++      len = acx_fill_beacon_or_proberesp_template(adev, &bcn, WF_FSTYPE_BEACON);
++      result = acx_s_issue_cmd(adev, ACX1xx_CMD_CONFIG_BEACON, &bcn, len);
++
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/***********************************************************************
++** acx_s_set_probe_response_template
++*/
++static int
++acx_s_set_probe_response_template(acx_device_t *adev)
++{
++      struct acx_template_proberesp pr;
++      int len, result;
++
++      FN_ENTER;
++
++      len = acx_fill_beacon_or_proberesp_template(adev, &pr, WF_FSTYPE_PROBERESP);
++      result = acx_s_issue_cmd(adev, ACX1xx_CMD_CONFIG_PROBE_RESPONSE, &pr, len);
++
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/***********************************************************************
++** acx_s_init_packet_templates()
++**
++** NOTE: order is very important here, to have a correct memory layout!
++** init templates: max Probe Request (station mode), max NULL data,
++** max Beacon, max TIM, max Probe Response.
++*/
++static int
++acx_s_init_packet_templates(acx_device_t *adev)
++{
++      acx_ie_memmap_t mm; /* ACX100 only */
++      int result = NOT_OK;
++
++      FN_ENTER;
++
++      log(L_DEBUG|L_INIT, "initializing max packet templates\n");
++
++      if (OK != acx_s_init_max_probe_request_template(adev))
++              goto failed;
++
++      if (OK != acx_s_init_max_null_data_template(adev))
++              goto failed;
++
++      if (OK != acx_s_init_max_beacon_template(adev))
++              goto failed;
++
++      if (OK != acx_s_init_max_tim_template(adev))
++              goto failed;
++
++      if (OK != acx_s_init_max_probe_response_template(adev))
++              goto failed;
++
++      if (IS_ACX111(adev)) {
++              /* ACX111 doesn't need the memory map magic below,
++               * and the other templates will be set later (acx_start) */
++              result = OK;
++              goto success;
++      }
++
++      /* ACX100 will have its TIM template set,
++       * and we also need to update the memory map */
++
++      if (OK != acx_s_set_tim_template(adev))
++              goto failed_acx100;
++
++      log(L_DEBUG, "sizeof(memmap)=%d bytes\n", (int)sizeof(mm));
++
++      if (OK != acx_s_interrogate(adev, &mm, ACX1xx_IE_MEMORY_MAP))
++              goto failed_acx100;
++
++      mm.QueueStart = cpu_to_le32(le32_to_cpu(mm.PacketTemplateEnd) + 4);
++      if (OK != acx_s_configure(adev, &mm, ACX1xx_IE_MEMORY_MAP))
++              goto failed_acx100;
++
++      result = OK;
++      goto success;
++
++failed_acx100:
++      log(L_DEBUG|L_INIT,
++              /* "cb=0x%X\n" */
++              "ACXMemoryMap:\n"
++              ".CodeStart=0x%X\n"
++              ".CodeEnd=0x%X\n"
++              ".WEPCacheStart=0x%X\n"
++              ".WEPCacheEnd=0x%X\n"
++              ".PacketTemplateStart=0x%X\n"
++              ".PacketTemplateEnd=0x%X\n",
++              /* len, */
++              le32_to_cpu(mm.CodeStart),
++              le32_to_cpu(mm.CodeEnd),
++              le32_to_cpu(mm.WEPCacheStart),
++              le32_to_cpu(mm.WEPCacheEnd),
++              le32_to_cpu(mm.PacketTemplateStart),
++              le32_to_cpu(mm.PacketTemplateEnd));
++
++failed:
++      printk("%s: %s() FAILED\n", adev->ndev->name, __func__);
++
++success:
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/***********************************************************************
++*/
++static int
++acx_s_set_probe_request_template(acx_device_t *adev)
++{
++      struct acx_template_probereq probereq;
++      char *p;
++      int res;
++      int frame_len;
++
++      FN_ENTER;
++
++      memset(&probereq, 0, sizeof(probereq));
++
++      probereq.fc = WF_FTYPE_MGMTi | WF_FSTYPE_PROBEREQi;
++      MAC_BCAST(probereq.da);
++      MAC_COPY(probereq.sa, adev->dev_addr);
++      MAC_BCAST(probereq.bssid);
++
++      p = probereq.variable;
++      p = wlan_fill_ie_ssid(p, adev->essid_len, adev->essid);
++      p = wlan_fill_ie_rates(p, adev->rate_supported_len, adev->rate_supported);
++      p = wlan_fill_ie_rates_ext(p, adev->rate_supported_len, adev->rate_supported);
++      frame_len = p - (char*)&probereq;
++      probereq.size = cpu_to_le16(frame_len - 2);
++
++      res = acx_s_issue_cmd(adev, ACX1xx_CMD_CONFIG_PROBE_REQUEST, &probereq, frame_len);
++      FN_EXIT0;
++      return res;
++}
++
++
++/***********************************************************************
++** acx_s_init_mac
++*/
++int
++acx_s_init_mac(acx_device_t *adev)
++{
++      int result = NOT_OK;
++
++      FN_ENTER;
++
++      if (IS_ACX111(adev)) {
++              adev->ie_len = acx111_ie_len;
++              adev->ie_len_dot11 = acx111_ie_len_dot11;
++      } else {
++              adev->ie_len = acx100_ie_len;
++              adev->ie_len_dot11 = acx100_ie_len_dot11;
++      }
++
++#if defined (ACX_MEM)
++              adev->memblocksize = 256; /* 256 is default */
++              /* try to load radio for both ACX100 and ACX111, since both
++               * chips have at least some firmware versions making use of an
++               * external radio module */
++              acxmem_s_upload_radio(adev);
++#else
++      if (IS_PCI(adev)) {
++              adev->memblocksize = 256; /* 256 is default */
++              /* try to load radio for both ACX100 and ACX111, since both
++               * chips have at least some firmware versions making use of an
++               * external radio module */
++              acxpci_s_upload_radio(adev);
++      } else {
++              adev->memblocksize = 128;
++      }
++#endif
++
++      if (IS_ACX111(adev)) {
++              /* for ACX111, the order is different from ACX100
++                 1. init packet templates
++                 2. create station context and create dma regions
++                 3. init wep default keys
++              */
++              if (OK != acx_s_init_packet_templates(adev))
++                      goto fail;
++              if (OK != acx111_s_create_dma_regions(adev)) {
++                      printk("%s: acx111_create_dma_regions FAILED\n",
++                                              adev->ndev->name);
++                      goto fail;
++              }
++      } else {
++              if (OK != acx100_s_init_wep(adev))
++                      goto fail;
++              if (OK != acx_s_init_packet_templates(adev))
++                      goto fail;
++              if (OK != acx100_s_create_dma_regions(adev)) {
++                      printk("%s: acx100_create_dma_regions FAILED\n",
++                                              adev->ndev->name);
++                      goto fail;
++              }
++      }
++
++      MAC_COPY(adev->ndev->dev_addr, adev->dev_addr);
++      result = OK;
++
++fail:
++      if (result)
++              printk("acx: init_mac() FAILED\n");
++      FN_EXIT1(result);
++      return result;
++}
++
++
++void
++acx_s_set_sane_reg_domain(acx_device_t *adev, int do_set)
++{
++      unsigned mask;
++
++      unsigned int i;
++
++      for (i = 0; i < sizeof(acx_reg_domain_ids); i++)
++              if (acx_reg_domain_ids[i] == adev->reg_dom_id)
++                      break;
++
++      if (sizeof(acx_reg_domain_ids) == i) {
++              log(L_INIT, "Invalid or unsupported regulatory domain"
++                             " 0x%02X specified, falling back to FCC (USA)!"
++                             " Please report if this sounds fishy!\n",
++                              adev->reg_dom_id);
++              i = 0;
++              adev->reg_dom_id = acx_reg_domain_ids[i];
++
++              /* since there was a mismatch, we need to force updating */
++              do_set = 1;
++      }
++
++      if (do_set) {
++              acx_ie_generic_t dom;
++              dom.m.bytes[0] = adev->reg_dom_id;
++              acx_s_configure(adev, &dom, ACX1xx_IE_DOT11_CURRENT_REG_DOMAIN);
++      }
++
++      adev->reg_dom_chanmask = reg_domain_channel_masks[i];
++
++      mask = (1 << (adev->channel - 1));
++      if (!(adev->reg_dom_chanmask & mask)) {
++      /* hmm, need to adjust our channel to reside within domain */
++              mask = 1;
++              for (i = 1; i <= 14; i++) {
++                      if (adev->reg_dom_chanmask & mask) {
++                              printk("%s: adjusting selected channel from %d "
++                                      "to %d due to new regulatory domain\n",
++                                      adev->ndev->name, adev->channel, i);
++                              adev->channel = i;
++                              break;
++                      }
++                      mask <<= 1;
++              }
++      }
++}
++
++
++#if POWER_SAVE_80211
++static void
++acx_s_update_80211_powersave_mode(acx_device_t *adev)
++{
++      /* merge both structs in a union to be able to have common code */
++      union {
++              acx111_ie_powersave_t acx111;
++              acx100_ie_powersave_t acx100;
++      } pm;
++
++      /* change 802.11 power save mode settings */
++      log(L_INIT, "updating 802.11 power save mode settings: "
++              "wakeup_cfg 0x%02X, listen interval %u, "
++              "options 0x%02X, hangover period %u, "
++              "enhanced_ps_transition_time %u\n",
++              adev->ps_wakeup_cfg, adev->ps_listen_interval,
++              adev->ps_options, adev->ps_hangover_period,
++              adev->ps_enhanced_transition_time);
++      acx_s_interrogate(adev, &pm, ACX1xx_IE_POWER_MGMT);
++      log(L_INIT, "Previous PS mode settings: wakeup_cfg 0x%02X, "
++              "listen interval %u, options 0x%02X, "
++              "hangover period %u, "
++              "enhanced_ps_transition_time %u, beacon_rx_time %u\n",
++              pm.acx111.wakeup_cfg,
++              pm.acx111.listen_interval,
++              pm.acx111.options,
++              pm.acx111.hangover_period,
++              IS_ACX111(adev) ?
++                      pm.acx111.enhanced_ps_transition_time
++                    : pm.acx100.enhanced_ps_transition_time,
++              IS_ACX111(adev) ?
++                      pm.acx111.beacon_rx_time
++                    : (u32)-1
++              );
++      pm.acx111.wakeup_cfg = adev->ps_wakeup_cfg;
++      pm.acx111.listen_interval = adev->ps_listen_interval;
++      pm.acx111.options = adev->ps_options;
++      pm.acx111.hangover_period = adev->ps_hangover_period;
++      if (IS_ACX111(adev)) {
++              pm.acx111.beacon_rx_time = cpu_to_le32(adev->ps_beacon_rx_time);
++              pm.acx111.enhanced_ps_transition_time = cpu_to_le32(adev->ps_enhanced_transition_time);
++      } else {
++              pm.acx100.enhanced_ps_transition_time = cpu_to_le16(adev->ps_enhanced_transition_time);
++      }
++      acx_s_configure(adev, &pm, ACX1xx_IE_POWER_MGMT);
++      acx_s_interrogate(adev, &pm, ACX1xx_IE_POWER_MGMT);
++      log(L_INIT, "wakeup_cfg: 0x%02X\n", pm.acx111.wakeup_cfg);
++      acx_s_msleep(40);
++      acx_s_interrogate(adev, &pm, ACX1xx_IE_POWER_MGMT);
++      log(L_INIT, "wakeup_cfg: 0x%02X\n", pm.acx111.wakeup_cfg);
++      log(L_INIT, "power save mode change %s\n",
++              (pm.acx111.wakeup_cfg & PS_CFG_PENDING) ? "FAILED" : "was successful");
++      /* FIXME: maybe verify via PS_CFG_PENDING bit here
++       * that power save mode change was successful. */
++      /* FIXME: we shouldn't trigger a scan immediately after
++       * fiddling with power save mode (since the firmware is sending
++       * a NULL frame then). */
++}
++#endif
++
++
++/***********************************************************************
++** acx_s_update_card_settings
++**
++** Applies accumulated changes in various adev->xxxx members
++** Called by ioctl commit handler, acx_start, acx_set_defaults,
++** acx_s_after_interrupt_task (if IRQ_CMD_UPDATE_CARD_CFG),
++*/
++static void
++acx111_s_sens_radio_16_17(acx_device_t *adev)
++{
++      u32 feature1, feature2;
++
++      if ((adev->sensitivity < 1) || (adev->sensitivity > 3)) {
++              printk("%s: invalid sensitivity setting (1..3), "
++                      "setting to 1\n", adev->ndev->name);
++              adev->sensitivity = 1;
++      }
++      acx111_s_get_feature_config(adev, &feature1, &feature2);
++      CLEAR_BIT(feature1, FEATURE1_LOW_RX|FEATURE1_EXTRA_LOW_RX);
++      if (adev->sensitivity > 1)
++              SET_BIT(feature1, FEATURE1_LOW_RX);
++      if (adev->sensitivity > 2)
++              SET_BIT(feature1, FEATURE1_EXTRA_LOW_RX);
++      acx111_s_feature_set(adev, feature1, feature2);
++}
++
++
++void
++acx_s_update_card_settings(acx_device_t *adev)
++{
++      unsigned long flags;
++      unsigned int start_scan = 0;
++      int i;
++
++      FN_ENTER;
++
++      log(L_INIT, "get_mask 0x%08X, set_mask 0x%08X\n",
++                      adev->get_mask, adev->set_mask);
++
++      /* Track dependencies betweed various settings */
++
++      if (adev->set_mask & (GETSET_MODE|GETSET_RESCAN|GETSET_WEP)) {
++              log(L_INIT, "important setting has been changed. "
++                      "Need to update packet templates, too\n");
++              SET_BIT(adev->set_mask, SET_TEMPLATES);
++      }
++      if (adev->set_mask & GETSET_CHANNEL) {
++              /* This will actually tune RX/TX to the channel */
++              SET_BIT(adev->set_mask, GETSET_RX|GETSET_TX);
++              switch (adev->mode) {
++              case ACX_MODE_0_ADHOC:
++              case ACX_MODE_3_AP:
++                      /* Beacons contain channel# - update them */
++                      SET_BIT(adev->set_mask, SET_TEMPLATES);
++              }
++              switch (adev->mode) {
++              case ACX_MODE_0_ADHOC:
++              case ACX_MODE_2_STA:
++                      start_scan = 1;
++              }
++      }
++
++      /* Apply settings */
++
++#ifdef WHY_SHOULD_WE_BOTHER /* imagine we were just powered off */
++      /* send a disassoc request in case it's required */
++      if (adev->set_mask & (GETSET_MODE|GETSET_RESCAN|GETSET_CHANNEL|GETSET_WEP)) {
++              if (ACX_MODE_2_STA == adev->mode) {
++                      if (ACX_STATUS_4_ASSOCIATED == adev->status) {
++                              log(L_ASSOC, "we were ASSOCIATED - "
++                                      "sending disassoc request\n");
++                              acx_lock(adev, flags);
++                              acx_l_transmit_disassoc(adev, NULL);
++                              /* FIXME: deauth? */
++                              acx_unlock(adev, flags);
++                      }
++                      /* need to reset some other stuff as well */
++                      log(L_DEBUG, "resetting bssid\n");
++                      MAC_ZERO(adev->bssid);
++                      SET_BIT(adev->set_mask, SET_TEMPLATES|SET_STA_LIST);
++                      start_scan = 1;
++              }
++      }
++#endif
++
++      if (adev->get_mask & GETSET_STATION_ID) {
++              u8 stationID[4 + ACX1xx_IE_DOT11_STATION_ID_LEN];
++              const u8 *paddr;
++
++              acx_s_interrogate(adev, &stationID, ACX1xx_IE_DOT11_STATION_ID);
++              paddr = &stationID[4];
++              for (i = 0; i < ETH_ALEN; i++) {
++                      /* we copy the MAC address (reversed in
++                       * the card) to the netdevice's MAC
++                       * address, and on ifup it will be
++                       * copied into iwadev->dev_addr */
++                      adev->ndev->dev_addr[ETH_ALEN - 1 - i] = paddr[i];
++              }
++              CLEAR_BIT(adev->get_mask, GETSET_STATION_ID);
++      }
++
++      if (adev->get_mask & GETSET_SENSITIVITY) {
++              if ((RADIO_RFMD_11 == adev->radio_type)
++              || (RADIO_MAXIM_0D == adev->radio_type)
++              || (RADIO_RALINK_15 == adev->radio_type)) {
++                      acx_s_read_phy_reg(adev, 0x30, &adev->sensitivity);
++              } else {
++                      log(L_INIT, "don't know how to get sensitivity "
++                              "for radio type 0x%02X\n", adev->radio_type);
++                      adev->sensitivity = 0;
++              }
++              log(L_INIT, "got sensitivity value %u\n", adev->sensitivity);
++
++              CLEAR_BIT(adev->get_mask, GETSET_SENSITIVITY);
++      }
++
++      if (adev->get_mask & GETSET_ANTENNA) {
++              u8 antenna[4 + ACX1xx_IE_DOT11_CURRENT_ANTENNA_LEN];
++
++              memset(antenna, 0, sizeof(antenna));
++              acx_s_interrogate(adev, antenna, ACX1xx_IE_DOT11_CURRENT_ANTENNA);
++              adev->antenna = antenna[4];
++              log(L_INIT, "got antenna value 0x%02X\n", adev->antenna);
++              CLEAR_BIT(adev->get_mask, GETSET_ANTENNA);
++      }
++
++      if (adev->get_mask & GETSET_ED_THRESH) {
++              if (IS_ACX100(adev))    {
++                      u8 ed_threshold[4 + ACX100_IE_DOT11_ED_THRESHOLD_LEN];
++
++                      memset(ed_threshold, 0, sizeof(ed_threshold));
++                      acx_s_interrogate(adev, ed_threshold, ACX100_IE_DOT11_ED_THRESHOLD);
++                      adev->ed_threshold = ed_threshold[4];
++              } else {
++                      log(L_INIT, "acx111 doesn't support ED\n");
++                      adev->ed_threshold = 0;
++              }
++              log(L_INIT, "got Energy Detect (ED) threshold %u\n", adev->ed_threshold);
++              CLEAR_BIT(adev->get_mask, GETSET_ED_THRESH);
++      }
++
++      if (adev->get_mask & GETSET_CCA) {
++              if (IS_ACX100(adev))    {
++                      u8 cca[4 + ACX1xx_IE_DOT11_CURRENT_CCA_MODE_LEN];
++
++                      memset(cca, 0, sizeof(adev->cca));
++                      acx_s_interrogate(adev, cca, ACX1xx_IE_DOT11_CURRENT_CCA_MODE);
++                      adev->cca = cca[4];
++              } else {
++                      log(L_INIT, "acx111 doesn't support CCA\n");
++                      adev->cca = 0;
++              }
++              log(L_INIT, "got Channel Clear Assessment (CCA) value %u\n", adev->cca);
++              CLEAR_BIT(adev->get_mask, GETSET_CCA);
++      }
++
++      if (adev->get_mask & GETSET_REG_DOMAIN) {
++              acx_ie_generic_t dom;
++
++              acx_s_interrogate(adev, &dom, ACX1xx_IE_DOT11_CURRENT_REG_DOMAIN);
++              adev->reg_dom_id = dom.m.bytes[0];
++              acx_s_set_sane_reg_domain(adev, 0);
++              log(L_INIT, "got regulatory domain 0x%02X\n", adev->reg_dom_id);
++              CLEAR_BIT(adev->get_mask, GETSET_REG_DOMAIN);
++      }
++
++      if (adev->set_mask & GETSET_STATION_ID) {
++              u8 stationID[4 + ACX1xx_IE_DOT11_STATION_ID_LEN];
++              u8 *paddr;
++
++              paddr = &stationID[4];
++              memcpy(adev->dev_addr, adev->ndev->dev_addr, ETH_ALEN);
++              for (i = 0; i < ETH_ALEN; i++) {
++                      /* copy the MAC address we obtained when we noticed
++                       * that the ethernet iface's MAC changed
++                       * to the card (reversed in
++                       * the card!) */
++                      paddr[i] = adev->dev_addr[ETH_ALEN - 1 - i];
++              }
++              acx_s_configure(adev, &stationID, ACX1xx_IE_DOT11_STATION_ID);
++              CLEAR_BIT(adev->set_mask, GETSET_STATION_ID);
++      }
++
++      if (adev->set_mask & SET_TEMPLATES) {
++              log(L_INIT, "updating packet templates\n");
++              switch (adev->mode) {
++              case ACX_MODE_2_STA:
++                      acx_s_set_probe_request_template(adev);
++#if POWER_SAVE_80211
++                      acx_s_set_null_data_template(adev);
++#endif
++                      break;
++              case ACX_MODE_0_ADHOC:
++                      acx_s_set_probe_request_template(adev);
++#if POWER_SAVE_80211
++                      /* maybe power save functionality is somehow possible
++                       * for Ad-Hoc mode, too... FIXME: verify it somehow? firmware debug fields? */
++                      acx_s_set_null_data_template(adev);
++#endif
++                      /* fall through */
++              case ACX_MODE_3_AP:
++                      acx_s_set_beacon_template(adev);
++                      acx_s_set_tim_template(adev);
++                      /* BTW acx111 firmware would not send probe responses
++                      ** if probe request does not have all basic rates flagged
++                      ** by 0x80! Thus firmware does not conform to 802.11,
++                      ** it should ignore 0x80 bit in ratevector from STA.
++                      ** We can 'fix' it by not using this template and
++                      ** sending probe responses by hand. TODO --vda */
++                      acx_s_set_probe_response_template(adev);
++              }
++              /* Needed if generated frames are to be emitted at different tx rate now */
++              log(L_IRQ, "redoing cmd_join_bssid() after template cfg\n");
++              acx_s_cmd_join_bssid(adev, adev->bssid);
++              CLEAR_BIT(adev->set_mask, SET_TEMPLATES);
++      }
++      if (adev->set_mask & SET_STA_LIST) {
++              acx_lock(adev, flags);
++              acx_l_sta_list_init(adev);
++              CLEAR_BIT(adev->set_mask, SET_STA_LIST);
++              acx_unlock(adev, flags);
++      }
++      if (adev->set_mask & SET_RATE_FALLBACK) {
++              u8 rate[4 + ACX1xx_IE_RATE_FALLBACK_LEN];
++
++              /* configure to not do fallbacks when not in auto rate mode */
++              rate[4] = (adev->rate_auto) ? /* adev->txrate_fallback_retries */ 1 : 0;
++              log(L_INIT, "updating Tx fallback to %u retries\n", rate[4]);
++              acx_s_configure(adev, &rate, ACX1xx_IE_RATE_FALLBACK);
++              CLEAR_BIT(adev->set_mask, SET_RATE_FALLBACK);
++      }
++      if (adev->set_mask & GETSET_TXPOWER) {
++              log(L_INIT, "updating transmit power: %u dBm\n",
++                                      adev->tx_level_dbm);
++              acx_s_set_tx_level(adev, adev->tx_level_dbm);
++              CLEAR_BIT(adev->set_mask, GETSET_TXPOWER);
++      }
++
++      if (adev->set_mask & GETSET_SENSITIVITY) {
++              log(L_INIT, "updating sensitivity value: %u\n",
++                                      adev->sensitivity);
++              switch (adev->radio_type) {
++              case RADIO_RFMD_11:
++              case RADIO_MAXIM_0D:
++              case RADIO_RALINK_15:
++                      acx_s_write_phy_reg(adev, 0x30, adev->sensitivity);
++                      break;
++              case RADIO_RADIA_16:
++              case RADIO_UNKNOWN_17:
++                      acx111_s_sens_radio_16_17(adev);
++                      break;
++              default:
++                      log(L_INIT, "don't know how to modify sensitivity "
++                              "for radio type 0x%02X\n", adev->radio_type);
++              }
++              CLEAR_BIT(adev->set_mask, GETSET_SENSITIVITY);
++      }
++
++      if (adev->set_mask & GETSET_ANTENNA) {
++              /* antenna */
++              u8 antenna[4 + ACX1xx_IE_DOT11_CURRENT_ANTENNA_LEN];
++
++              memset(antenna, 0, sizeof(antenna));
++              antenna[4] = adev->antenna;
++              log(L_INIT, "updating antenna value: 0x%02X\n",
++                                      adev->antenna);
++              acx_s_configure(adev, &antenna, ACX1xx_IE_DOT11_CURRENT_ANTENNA);
++              CLEAR_BIT(adev->set_mask, GETSET_ANTENNA);
++      }
++
++      if (adev->set_mask & GETSET_ED_THRESH) {
++              /* ed_threshold */
++              log(L_INIT, "updating Energy Detect (ED) threshold: %u\n",
++                                      adev->ed_threshold);
++              if (IS_ACX100(adev)) {
++                      u8 ed_threshold[4 + ACX100_IE_DOT11_ED_THRESHOLD_LEN];
++
++                      memset(ed_threshold, 0, sizeof(ed_threshold));
++                      ed_threshold[4] = adev->ed_threshold;
++                      acx_s_configure(adev, &ed_threshold, ACX100_IE_DOT11_ED_THRESHOLD);
++              }
++              else
++                      log(L_INIT, "acx111 doesn't support ED!\n");
++              CLEAR_BIT(adev->set_mask, GETSET_ED_THRESH);
++      }
++
++      if (adev->set_mask & GETSET_CCA) {
++              /* CCA value */
++              log(L_INIT, "updating Channel Clear Assessment "
++                              "(CCA) value: 0x%02X\n", adev->cca);
++              if (IS_ACX100(adev))    {
++                      u8 cca[4 + ACX1xx_IE_DOT11_CURRENT_CCA_MODE_LEN];
++
++                      memset(cca, 0, sizeof(cca));
++                      cca[4] = adev->cca;
++                      acx_s_configure(adev, &cca, ACX1xx_IE_DOT11_CURRENT_CCA_MODE);
++              }
++              else
++                      log(L_INIT, "acx111 doesn't support CCA!\n");
++              CLEAR_BIT(adev->set_mask, GETSET_CCA);
++      }
++
++      if (adev->set_mask & GETSET_LED_POWER) {
++              /* Enable Tx */
++              log(L_INIT, "updating power LED status: %u\n", adev->led_power);
++
++              acx_lock(adev, flags);
++#if defined (ACX_MEM)
++              acxmem_l_power_led(adev, adev->led_power);
++#else
++              if (IS_PCI(adev))
++                      acxpci_l_power_led(adev, adev->led_power);
++#endif
++              CLEAR_BIT(adev->set_mask, GETSET_LED_POWER);
++              acx_unlock(adev, flags);
++      }
++
++      if (adev->set_mask & GETSET_POWER_80211) {
++#if POWER_SAVE_80211
++              acx_s_update_80211_powersave_mode(adev);
++#endif
++              CLEAR_BIT(adev->set_mask, GETSET_POWER_80211);
++      }
++
++      if (adev->set_mask & GETSET_CHANNEL) {
++              /* channel */
++              log(L_INIT, "updating channel to: %u\n", adev->channel);
++              CLEAR_BIT(adev->set_mask, GETSET_CHANNEL);
++      }
++
++      if (adev->set_mask & GETSET_TX) {
++              /* set Tx */
++              log(L_INIT, "updating: %s Tx\n",
++                              adev->tx_disabled ? "disable" : "enable");
++              if (adev->tx_disabled)
++                      acx_s_issue_cmd(adev, ACX1xx_CMD_DISABLE_TX, NULL, 0);
++              else
++                      acx_s_issue_cmd(adev, ACX1xx_CMD_ENABLE_TX, &adev->channel, 1);
++              CLEAR_BIT(adev->set_mask, GETSET_TX);
++      }
++
++      if (adev->set_mask & GETSET_RX) {
++              /* Enable Rx */
++              log(L_INIT, "updating: enable Rx on channel: %u\n",
++                              adev->channel);
++              acx_s_issue_cmd(adev, ACX1xx_CMD_ENABLE_RX, &adev->channel, 1);
++              CLEAR_BIT(adev->set_mask, GETSET_RX);
++      }
++
++      if (adev->set_mask & GETSET_RETRY) {
++              u8 short_retry[4 + ACX1xx_IE_DOT11_SHORT_RETRY_LIMIT_LEN];
++              u8 long_retry[4 + ACX1xx_IE_DOT11_LONG_RETRY_LIMIT_LEN];
++
++              log(L_INIT, "updating short retry limit: %u, long retry limit: %u\n",
++                                      adev->short_retry, adev->long_retry);
++              short_retry[0x4] = adev->short_retry;
++              long_retry[0x4] = adev->long_retry;
++              acx_s_configure(adev, &short_retry, ACX1xx_IE_DOT11_SHORT_RETRY_LIMIT);
++              acx_s_configure(adev, &long_retry, ACX1xx_IE_DOT11_LONG_RETRY_LIMIT);
++              CLEAR_BIT(adev->set_mask, GETSET_RETRY);
++      }
++
++      if (adev->set_mask & SET_MSDU_LIFETIME) {
++              u8 xmt_msdu_lifetime[4 + ACX1xx_IE_DOT11_MAX_XMIT_MSDU_LIFETIME_LEN];
++
++              log(L_INIT, "updating tx MSDU lifetime: %u\n",
++                                      adev->msdu_lifetime);
++              *(u32 *)&xmt_msdu_lifetime[4] = cpu_to_le32((u32)adev->msdu_lifetime);
++              acx_s_configure(adev, &xmt_msdu_lifetime, ACX1xx_IE_DOT11_MAX_XMIT_MSDU_LIFETIME);
++              CLEAR_BIT(adev->set_mask, SET_MSDU_LIFETIME);
++      }
++
++      if (adev->set_mask & GETSET_REG_DOMAIN) {
++              log(L_INIT, "updating regulatory domain: 0x%02X\n",
++                                      adev->reg_dom_id);
++              acx_s_set_sane_reg_domain(adev, 1);
++              CLEAR_BIT(adev->set_mask, GETSET_REG_DOMAIN);
++      }
++
++      if (adev->set_mask & GETSET_MODE) {
++              adev->ndev->type = (adev->mode == ACX_MODE_MONITOR) ?
++                      adev->monitor_type : ARPHRD_ETHER;
++
++              switch (adev->mode) {
++              case ACX_MODE_3_AP:
++
++                      acx_lock(adev, flags);
++                      acx_l_sta_list_init(adev);
++                      adev->aid = 0;
++                      adev->ap_client = NULL;
++                      MAC_COPY(adev->bssid, adev->dev_addr);
++                      /* this basically says "we're connected" */
++                      acx_set_status(adev, ACX_STATUS_4_ASSOCIATED);
++                      acx_unlock(adev, flags);
++
++                      acx111_s_feature_off(adev, 0, FEATURE2_NO_TXCRYPT|FEATURE2_SNIFFER);
++                      /* start sending beacons */
++                      acx_s_cmd_join_bssid(adev, adev->bssid);
++                      break;
++              case ACX_MODE_MONITOR:
++                      acx111_s_feature_on(adev, 0, FEATURE2_NO_TXCRYPT|FEATURE2_SNIFFER);
++                      /* this stops beacons */
++                      acx_s_cmd_join_bssid(adev, adev->bssid);
++                      /* this basically says "we're connected" */
++                      acx_set_status(adev, ACX_STATUS_4_ASSOCIATED);
++                      SET_BIT(adev->set_mask, SET_RXCONFIG|SET_WEP_OPTIONS);
++                      break;
++              case ACX_MODE_0_ADHOC:
++              case ACX_MODE_2_STA:
++                      acx111_s_feature_off(adev, 0, FEATURE2_NO_TXCRYPT|FEATURE2_SNIFFER);
++
++                      acx_lock(adev, flags);
++                      adev->aid = 0;
++                      adev->ap_client = NULL;
++                      acx_unlock(adev, flags);
++
++                      /* we want to start looking for peer or AP */
++                      start_scan = 1;
++                      break;
++              case ACX_MODE_OFF:
++                      /* TODO: disable RX/TX, stop any scanning activity etc: */
++                      /* adev->tx_disabled = 1; */
++                      /* SET_BIT(adev->set_mask, GETSET_RX|GETSET_TX); */
++
++                      /* This stops beacons (invalid macmode...) */
++                      acx_s_cmd_join_bssid(adev, adev->bssid);
++                      acx_set_status(adev, ACX_STATUS_0_STOPPED);
++                      break;
++              }
++              CLEAR_BIT(adev->set_mask, GETSET_MODE);
++      }
++
++      if (adev->set_mask & SET_RXCONFIG) {
++              acx_s_initialize_rx_config(adev);
++              CLEAR_BIT(adev->set_mask, SET_RXCONFIG);
++      }
++
++      if (adev->set_mask & GETSET_RESCAN) {
++              switch (adev->mode) {
++              case ACX_MODE_0_ADHOC:
++              case ACX_MODE_2_STA:
++                      start_scan = 1;
++                      break;
++              }
++              CLEAR_BIT(adev->set_mask, GETSET_RESCAN);
++      }
++
++      if (adev->set_mask & GETSET_WEP) {
++              /* encode */
++
++              ie_dot11WEPDefaultKeyID_t dkey;
++#ifdef DEBUG_WEP
++              struct {
++                      u16 type;
++                      u16 len;
++                      u8  val;
++              } ACX_PACKED keyindic;
++#endif
++              log(L_INIT, "updating WEP key settings\n");
++
++              acx_s_set_wepkey(adev);
++
++              dkey.KeyID = adev->wep_current_index;
++              log(L_INIT, "setting WEP key %u as default\n", dkey.KeyID);
++              acx_s_configure(adev, &dkey, ACX1xx_IE_DOT11_WEP_DEFAULT_KEY_SET);
++#ifdef DEBUG_WEP
++              keyindic.val = 3;
++              acx_s_configure(adev, &keyindic, ACX111_IE_KEY_CHOOSE);
++#endif
++              start_scan = 1;
++              CLEAR_BIT(adev->set_mask, GETSET_WEP);
++      }
++
++      if (adev->set_mask & SET_WEP_OPTIONS) {
++              acx100_ie_wep_options_t options;
++              if (IS_ACX111(adev)) {
++                      log(L_DEBUG, "setting WEP Options for acx111 is not supported\n");
++              } else {
++                      log(L_INIT, "setting WEP Options\n");
++                      acx100_s_init_wep(adev);
++#if 0
++                      /* let's choose maximum setting: 4 default keys,
++                       * plus 10 other keys: */
++                      options.NumKeys = cpu_to_le16(DOT11_MAX_DEFAULT_WEP_KEYS + 10);
++                      /* don't decrypt default key only,
++                       * don't override decryption: */
++                      options.WEPOption = 0;
++                      if (adev->mode == ACX_MODE_MONITOR) {
++                              /* don't decrypt default key only,
++                               * override decryption mechanism: */
++                              options.WEPOption = 2;
++                      }
++
++                      acx_s_configure(adev, &options, ACX100_IE_WEP_OPTIONS);
++#endif
++              }
++              CLEAR_BIT(adev->set_mask, SET_WEP_OPTIONS);
++      }
++
++      /* Rescan was requested */
++      if (start_scan) {
++              switch (adev->mode) {
++              case ACX_MODE_0_ADHOC:
++              case ACX_MODE_2_STA:
++                      /* We can avoid clearing list if join code
++                      ** will be a bit more clever about not picking
++                      ** 'bad' AP over and over again */
++                      acx_lock(adev, flags);
++                      adev->ap_client = NULL;
++                      acx_l_sta_list_init(adev);
++                      acx_set_status(adev, ACX_STATUS_1_SCANNING);
++                      acx_unlock(adev, flags);
++
++                      acx_s_cmd_start_scan(adev);
++              }
++      }
++
++      /* debug, rate, and nick don't need any handling */
++      /* what about sniffing mode?? */
++
++      log(L_INIT, "get_mask 0x%08X, set_mask 0x%08X - after update\n",
++                      adev->get_mask, adev->set_mask);
++
++/* end: */
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++** acx_e_after_interrupt_task
++*/
++static int
++acx_s_recalib_radio(acx_device_t *adev)
++{
++      if (IS_ACX111(adev)) {
++              acx111_cmd_radiocalib_t cal;
++
++              printk("%s: recalibrating radio\n", adev->ndev->name);
++              /* automatic recalibration, choose all methods: */
++              cal.methods = cpu_to_le32(0x8000000f);
++              /* automatic recalibration every 60 seconds (value in TUs)
++               * I wonder what the firmware default here is? */
++              cal.interval = cpu_to_le32(58594);
++              return acx_s_issue_cmd_timeo(adev, ACX111_CMD_RADIOCALIB,
++                      &cal, sizeof(cal), CMD_TIMEOUT_MS(100));
++      } else {
++              /* On ACX100, we need to recalibrate the radio
++               * by issuing a GETSET_TX|GETSET_RX */
++              if (/* (OK == acx_s_issue_cmd(adev, ACX1xx_CMD_DISABLE_TX, NULL, 0)) &&
++                  (OK == acx_s_issue_cmd(adev, ACX1xx_CMD_DISABLE_RX, NULL, 0)) && */
++                  (OK == acx_s_issue_cmd(adev, ACX1xx_CMD_ENABLE_TX, &adev->channel, 1)) &&
++                  (OK == acx_s_issue_cmd(adev, ACX1xx_CMD_ENABLE_RX, &adev->channel, 1)) )
++                      return OK;
++              return NOT_OK;
++      }
++}
++
++static void
++acx_s_after_interrupt_recalib(acx_device_t *adev)
++{
++      int res;
++
++      /* this helps with ACX100 at least;
++       * hopefully ACX111 also does a
++       * recalibration here */
++
++      /* clear flag beforehand, since we want to make sure
++       * it's cleared; then only set it again on specific circumstances */
++      CLEAR_BIT(adev->after_interrupt_jobs, ACX_AFTER_IRQ_CMD_RADIO_RECALIB);
++
++      /* better wait a bit between recalibrations to
++       * prevent overheating due to torturing the card
++       * into working too long despite high temperature
++       * (just a safety measure) */
++      if (adev->recalib_time_last_success
++       && time_before(jiffies, adev->recalib_time_last_success
++                                      + RECALIB_PAUSE * 60 * HZ)) {
++              if (adev->recalib_msg_ratelimit <= 4) {
++                      printk("%s: less than " STRING(RECALIB_PAUSE)
++                              " minutes since last radio recalibration, "
++                              "not recalibrating (maybe card is too hot?)\n",
++                              adev->ndev->name);
++                      adev->recalib_msg_ratelimit++;
++                      if (adev->recalib_msg_ratelimit == 5)
++                              printk("disabling above message until next recalib\n");
++              }
++              return;
++      }
++
++      adev->recalib_msg_ratelimit = 0;
++
++      /* note that commands sometimes fail (card busy),
++       * so only clear flag if we were fully successful */
++      res = acx_s_recalib_radio(adev);
++      if (res == OK) {
++              printk("%s: successfully recalibrated radio\n",
++                                              adev->ndev->name);
++              adev->recalib_time_last_success = jiffies;
++              adev->recalib_failure_count = 0;
++      } else {
++              /* failed: resubmit, but only limited
++               * amount of times within some time range
++               * to prevent endless loop */
++
++              adev->recalib_time_last_success = 0; /* we failed */
++
++              /* if some time passed between last
++               * attempts, then reset failure retry counter
++               * to be able to do next recalib attempt */
++              if (time_after(jiffies, adev->recalib_time_last_attempt + 5*HZ))
++                      adev->recalib_failure_count = 0;
++
++              if (adev->recalib_failure_count < 5) {
++                      /* increment inside only, for speedup of outside path */
++                      adev->recalib_failure_count++;
++                      adev->recalib_time_last_attempt = jiffies;
++                      acx_schedule_task(adev, ACX_AFTER_IRQ_CMD_RADIO_RECALIB);
++              }
++      }
++}
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
++static void
++acx_e_after_interrupt_task(struct work_struct *work)
++{
++      acx_device_t *adev = container_of(work, acx_device_t, after_interrupt_task);
++#else
++  static void
++  acx_e_after_interrupt_task(void *data)
++  {
++      struct net_device *ndev = (struct net_device*)data;
++      acx_device_t *adev = ndev2adev(ndev);
++#endif
++      FN_ENTER;
++
++      acx_sem_lock(adev);
++
++      if (!adev->after_interrupt_jobs)
++              goto end; /* no jobs to do */
++
++#if TX_CLEANUP_IN_SOFTIRQ
++      /* can happen only on PCI */
++      if (adev->after_interrupt_jobs & ACX_AFTER_IRQ_TX_CLEANUP) {
++              acx_lock(adev, flags);
++              acxpci_l_clean_txdesc(adev);
++              CLEAR_BIT(adev->after_interrupt_jobs, ACX_AFTER_IRQ_TX_CLEANUP);
++              acx_unlock(adev, flags);
++      }
++#endif
++      /* we see lotsa tx errors */
++      if (adev->after_interrupt_jobs & ACX_AFTER_IRQ_CMD_RADIO_RECALIB) {
++              acx_s_after_interrupt_recalib(adev);
++      }
++
++      /* a poor interrupt code wanted to do update_card_settings() */
++      if (adev->after_interrupt_jobs & ACX_AFTER_IRQ_UPDATE_CARD_CFG) {
++              if (ACX_STATE_IFACE_UP & adev->dev_state_mask)
++                      acx_s_update_card_settings(adev);
++              CLEAR_BIT(adev->after_interrupt_jobs, ACX_AFTER_IRQ_UPDATE_CARD_CFG);
++      }
++
++      /* 1) we detected that no Scan_Complete IRQ came from fw, or
++      ** 2) we found too many STAs */
++      if (adev->after_interrupt_jobs & ACX_AFTER_IRQ_CMD_STOP_SCAN) {
++              log(L_IRQ, "sending a stop scan cmd...\n");
++              acx_s_issue_cmd(adev, ACX1xx_CMD_STOP_SCAN, NULL, 0);
++              /* HACK: set the IRQ bit, since we won't get a
++               * scan complete IRQ any more on ACX111 (works on ACX100!),
++               * since _we_, not a fw, have stopped the scan */
++              SET_BIT(adev->irq_status, HOST_INT_SCAN_COMPLETE);
++              CLEAR_BIT(adev->after_interrupt_jobs, ACX_AFTER_IRQ_CMD_STOP_SCAN);
++      }
++
++      /* either fw sent Scan_Complete or we detected that
++      ** no Scan_Complete IRQ came from fw. Finish scanning,
++      ** pick join partner if any */
++      if (adev->after_interrupt_jobs & ACX_AFTER_IRQ_COMPLETE_SCAN) {
++              if (adev->status == ACX_STATUS_1_SCANNING) {
++                      if (OK != acx_s_complete_scan(adev)) {
++                              SET_BIT(adev->after_interrupt_jobs,
++                                      ACX_AFTER_IRQ_RESTART_SCAN);
++                      }
++              } else {
++                      /* + scan kills current join status - restore it
++                      **   (do we need it for STA?) */
++                      /* + does it happen only with active scans?
++                      **   active and passive scans? ALL scans including
++                      **   background one? */
++                      /* + was not verified that everything is restored
++                      **   (but at least we start to emit beacons again) */
++                      switch (adev->mode) {
++                      case ACX_MODE_0_ADHOC:
++                      case ACX_MODE_3_AP:
++                              log(L_IRQ, "redoing cmd_join_bssid() after scan\n");
++                              acx_s_cmd_join_bssid(adev, adev->bssid);
++                      }
++              }
++              CLEAR_BIT(adev->after_interrupt_jobs, ACX_AFTER_IRQ_COMPLETE_SCAN);
++      }
++
++      /* STA auth or assoc timed out, start over again */
++      if (adev->after_interrupt_jobs & ACX_AFTER_IRQ_RESTART_SCAN) {
++              log(L_IRQ, "sending a start_scan cmd...\n");
++              acx_s_cmd_start_scan(adev);
++              CLEAR_BIT(adev->after_interrupt_jobs, ACX_AFTER_IRQ_RESTART_SCAN);
++      }
++
++      /* whee, we got positive assoc response! 8) */
++      if (adev->after_interrupt_jobs & ACX_AFTER_IRQ_CMD_ASSOCIATE) {
++              acx_ie_generic_t pdr;
++              /* tiny race window exists, checking that we still a STA */
++              switch (adev->mode) {
++              case ACX_MODE_2_STA:
++                      pdr.m.aid = cpu_to_le16(adev->aid);
++                      acx_s_configure(adev, &pdr, ACX1xx_IE_ASSOC_ID);
++                      acx_set_status(adev, ACX_STATUS_4_ASSOCIATED);
++                      log(L_ASSOC|L_DEBUG, "ASSOCIATED!\n");
++                      CLEAR_BIT(adev->after_interrupt_jobs, ACX_AFTER_IRQ_CMD_ASSOCIATE);
++              }
++      }
++end:
++      acx_sem_unlock(adev);
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++** acx_schedule_task
++**
++** Schedule the call of the after_interrupt method after leaving
++** the interrupt context.
++*/
++void
++acx_schedule_task(acx_device_t *adev, unsigned int set_flag)
++{
++      SET_BIT(adev->after_interrupt_jobs, set_flag);
++      SCHEDULE_WORK(&adev->after_interrupt_task);
++}
++
++
++/***********************************************************************
++*/
++void
++acx_init_task_scheduler(acx_device_t *adev)
++{
++      /* configure task scheduler */
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
++      INIT_WORK(&adev->after_interrupt_task, acx_e_after_interrupt_task);
++#else
++      INIT_WORK(&adev->after_interrupt_task, acx_e_after_interrupt_task,
++                      adev->ndev);
++#endif
++}
++
++
++/***********************************************************************
++** acx_s_start
++*/
++void
++acx_s_start(acx_device_t *adev)
++{
++      FN_ENTER;
++
++      /*
++       * Ok, now we do everything that can possibly be done with ioctl
++       * calls to make sure that when it was called before the card
++       * was up we get the changes asked for
++       */
++
++      SET_BIT(adev->set_mask, SET_TEMPLATES|SET_STA_LIST|GETSET_WEP
++              |GETSET_TXPOWER|GETSET_ANTENNA|GETSET_ED_THRESH|GETSET_CCA
++              |GETSET_REG_DOMAIN|GETSET_MODE|GETSET_CHANNEL
++              |GETSET_TX|GETSET_RX|GETSET_STATION_ID);
++
++      log(L_INIT, "updating initial settings on iface activation\n");
++      acx_s_update_card_settings(adev);
++
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++** acx_update_capabilities
++*/
++void
++acx_update_capabilities(acx_device_t *adev)
++{
++      u16 cap = 0;
++
++      switch (adev->mode) {
++      case ACX_MODE_3_AP:
++              SET_BIT(cap, WF_MGMT_CAP_ESS); break;
++      case ACX_MODE_0_ADHOC:
++              SET_BIT(cap, WF_MGMT_CAP_IBSS); break;
++      /* other types of stations do not emit beacons */
++      }
++
++      if (adev->wep_restricted) {
++              SET_BIT(cap, WF_MGMT_CAP_PRIVACY);
++      }
++      if (adev->cfgopt_dot11ShortPreambleOption) {
++              SET_BIT(cap, WF_MGMT_CAP_SHORT);
++      }
++      if (adev->cfgopt_dot11PBCCOption) {
++              SET_BIT(cap, WF_MGMT_CAP_PBCC);
++      }
++      if (adev->cfgopt_dot11ChannelAgility) {
++              SET_BIT(cap, WF_MGMT_CAP_AGILITY);
++      }
++      log(L_DEBUG, "caps updated from 0x%04X to 0x%04X\n",
++                              adev->capabilities, cap);
++      adev->capabilities = cap;
++}
++
++/***********************************************************************
++** Common function to parse ALL configoption struct formats
++** (ACX100 and ACX111; FIXME: how to make it work with ACX100 USB!?!?).
++** FIXME: logging should be removed here and added to a /proc file instead
++*/
++void
++acx_s_parse_configoption(acx_device_t *adev, const acx111_ie_configoption_t *pcfg)
++{
++      const u8 *pEle;
++      int i;
++      int is_acx111 = IS_ACX111(adev);
++
++      if (acx_debug & L_DEBUG) {
++              printk("configoption struct content:\n");
++              acx_dump_bytes(pcfg, sizeof(*pcfg));
++      }
++
++      if (( is_acx111 && (adev->eeprom_version == 5))
++      ||  (!is_acx111 && (adev->eeprom_version == 4))
++      ||  (!is_acx111 && (adev->eeprom_version == 5))) {
++              /* these versions are known to be supported */
++      } else {
++              printk("unknown chip and EEPROM version combination (%s, v%d), "
++                      "don't know how to parse config options yet. "
++                      "Please report\n", is_acx111 ? "ACX111" : "ACX100",
++                      adev->eeprom_version);
++              return;
++      }
++
++      /* first custom-parse the first part which has chip-specific layout */
++
++      pEle = (const u8 *) pcfg;
++
++      pEle += 4; /* skip (type,len) header */
++
++      memcpy(adev->cfgopt_NVSv, pEle, sizeof(adev->cfgopt_NVSv));
++      pEle += sizeof(adev->cfgopt_NVSv);
++
++      if (is_acx111) {
++              adev->cfgopt_NVS_vendor_offs = le16_to_cpu(*(u16 *)pEle);
++              pEle += sizeof(adev->cfgopt_NVS_vendor_offs);
++
++              adev->cfgopt_probe_delay = 200; /* good default value? */
++              pEle += 2; /* FIXME: unknown, value 0x0001 */
++      } else {
++              memcpy(adev->cfgopt_MAC, pEle, sizeof(adev->cfgopt_MAC));
++              pEle += sizeof(adev->cfgopt_MAC);
++
++              adev->cfgopt_probe_delay = le16_to_cpu(*(u16 *)pEle);
++              pEle += sizeof(adev->cfgopt_probe_delay);
++              if ((adev->cfgopt_probe_delay < 100) || (adev->cfgopt_probe_delay > 500)) {
++                      printk("strange probe_delay value %d, "
++                              "tweaking to 200\n", adev->cfgopt_probe_delay);
++                      adev->cfgopt_probe_delay = 200;
++              }
++      }
++
++      adev->cfgopt_eof_memory = le32_to_cpu(*(u32 *)pEle);
++      pEle += sizeof(adev->cfgopt_eof_memory);
++
++      printk("NVS_vendor_offs:%04X probe_delay:%d eof_memory:%d\n",
++              adev->cfgopt_NVS_vendor_offs,
++              adev->cfgopt_probe_delay,
++              adev->cfgopt_eof_memory);
++
++      adev->cfgopt_dot11CCAModes = *pEle++;
++      adev->cfgopt_dot11Diversity = *pEle++;
++      adev->cfgopt_dot11ShortPreambleOption = *pEle++;
++      adev->cfgopt_dot11PBCCOption = *pEle++;
++      adev->cfgopt_dot11ChannelAgility = *pEle++;
++      adev->cfgopt_dot11PhyType = *pEle++;
++      adev->cfgopt_dot11TempType = *pEle++;
++      printk("CCAModes:%02X Diversity:%02X ShortPreOpt:%02X "
++              "PBCC:%02X ChanAgil:%02X PHY:%02X Temp:%02X\n",
++              adev->cfgopt_dot11CCAModes,
++              adev->cfgopt_dot11Diversity,
++              adev->cfgopt_dot11ShortPreambleOption,
++              adev->cfgopt_dot11PBCCOption,
++              adev->cfgopt_dot11ChannelAgility,
++              adev->cfgopt_dot11PhyType,
++              adev->cfgopt_dot11TempType);
++
++      /* then use common parsing for next part which has common layout */
++
++      pEle++; /* skip table_count (6) */
++
++      if (IS_MEM(adev) && IS_ACX100(adev))
++      {
++      /*
++         * For iPaq hx4700 Generic Slave F/W 1.10.7.K.  I'm not sure if these
++         * 4 extra bytes are before the dot11 things above or after, so I'm just
++         * going to guess after.  If someone sees these aren't reasonable numbers,
++         * please fix this.
++       * The area from which the dot11 values above are read contains:
++       * 04 01 01 01 00 05 01 06 00 02 01 02
++       * the 8 dot11 reads above take care of 8 of them, but which 8...
++       */
++      pEle += 4;
++      }
++
++      adev->cfgopt_antennas.type = pEle[0];
++      adev->cfgopt_antennas.len = pEle[1];
++      printk("AntennaID:%02X Len:%02X Data:",
++                      adev->cfgopt_antennas.type, adev->cfgopt_antennas.len);
++      for (i = 0; i < pEle[1]; i++) {
++              adev->cfgopt_antennas.list[i] = pEle[i+2];
++              printk("%02X ", pEle[i+2]);
++      }
++      printk("\n");
++
++      pEle += pEle[1] + 2;
++      adev->cfgopt_power_levels.type = pEle[0];
++      adev->cfgopt_power_levels.len = pEle[1];
++      printk("PowerLevelID:%02X Len:%02X Data:",
++              adev->cfgopt_power_levels.type, adev->cfgopt_power_levels.len);
++      for (i = 0; i < pEle[1]; i++) {
++              adev->cfgopt_power_levels.list[i] = le16_to_cpu(*(u16 *)&pEle[i*2+2]);
++              printk("%04X ", adev->cfgopt_power_levels.list[i]);
++      }
++      printk("\n");
++
++      pEle += pEle[1]*2 + 2;
++      adev->cfgopt_data_rates.type = pEle[0];
++      adev->cfgopt_data_rates.len = pEle[1];
++      printk("DataRatesID:%02X Len:%02X Data:",
++              adev->cfgopt_data_rates.type, adev->cfgopt_data_rates.len);
++      for (i = 0; i < pEle[1]; i++) {
++              adev->cfgopt_data_rates.list[i] = pEle[i+2];
++              printk("%02X ", pEle[i+2]);
++      }
++      printk("\n");
++
++      pEle += pEle[1] + 2;
++      adev->cfgopt_domains.type = pEle[0];
++      adev->cfgopt_domains.len = pEle[1];
++      if (IS_MEM(adev) && IS_ACX100(adev))
++      {
++      /*
++         * For iPaq hx4700 Generic Slave F/W 1.10.7.K.
++       * There's an extra byte between this structure and the next
++       * that is not accounted for with this structure's length.  It's
++       * most likely a bug in the firmware, but we can fix it here
++       * by bumping the length of this field by 1.
++       */
++      adev->cfgopt_domains.len++;
++      }
++      printk("DomainID:%02X Len:%02X Data:",
++                      adev->cfgopt_domains.type, adev->cfgopt_domains.len);
++      for (i = 0; i < adev->cfgopt_domains.len; i++) {
++              adev->cfgopt_domains.list[i] = pEle[i+2];
++              printk("%02X ", pEle[i+2]);
++      }
++      printk("\n");
++
++      pEle += adev->cfgopt_domains.len + 2;
++
++      adev->cfgopt_product_id.type = pEle[0];
++      adev->cfgopt_product_id.len = pEle[1];
++      for (i = 0; i < pEle[1]; i++) {
++              adev->cfgopt_product_id.list[i] = pEle[i+2];
++      }
++      printk("ProductID:%02X Len:%02X Data:%.*s\n",
++              adev->cfgopt_product_id.type, adev->cfgopt_product_id.len,
++              adev->cfgopt_product_id.len, (char *)adev->cfgopt_product_id.list);
++
++      pEle += pEle[1] + 2;
++      adev->cfgopt_manufacturer.type = pEle[0];
++      adev->cfgopt_manufacturer.len = pEle[1];
++      for (i = 0; i < pEle[1]; i++) {
++              adev->cfgopt_manufacturer.list[i] = pEle[i+2];
++      }
++      printk("ManufacturerID:%02X Len:%02X Data:%.*s\n",
++              adev->cfgopt_manufacturer.type, adev->cfgopt_manufacturer.len,
++              adev->cfgopt_manufacturer.len, (char *)adev->cfgopt_manufacturer.list);
++/*
++      printk("EEPROM part:\n");
++      for (i=0; i<58; i++) {
++              printk("%02X =======>  0x%02X\n",
++                      i, (u8 *)adev->cfgopt_NVSv[i-2]);
++      }
++*/
++}
++
++
++/***********************************************************************
++*/
++static int __init
++acx_e_init_module(void)
++{
++      int r1,r2,r3,r4;
++
++      acx_struct_size_check();
++
++      printk("acx: this driver is still EXPERIMENTAL\n"
++              "acx: reading README file and/or Craig's HOWTO is "
++              "recommended, visit http://acx100.sf.net in case "
++              "of further questions/discussion\n");
++
++#if defined(CONFIG_ACX_PCI)
++      r1 = acxpci_e_init_module();
++#else
++      r1 = -EINVAL;
++#endif
++#if defined(CONFIG_ACX_MEM)
++      r2 = acxmem_e_init_module();
++#else
++      r2 = -EINVAL;
++#endif
++#if defined(CONFIG_ACX_USB)
++      r3 = acxusb_e_init_module();
++#else
++      r3 = -EINVAL;
++#endif
++#if defined(CONFIG_ACX_CS)
++      r4 = acx_cs_init();
++#else
++      r4 = -EINVAL;
++#endif
++      if (r2 && r1  && r3 && r4) { /* all failed! */
++        if (r3 || r1)
++              return r3 ? r3 : r1;
++        else
++          return r2;
++      }
++      /* return success if at least one succeeded */
++      return 0;
++
++}
++
++static void __exit
++acx_e_cleanup_module(void)
++{
++#if defined(CONFIG_ACX_PCI)
++      acxpci_e_cleanup_module();
++#endif
++#if defined(CONFIG_ACX_MEM)
++      acxmem_e_cleanup_module();
++#endif
++#if defined(CONFIG_ACX_USB)
++      acxusb_e_cleanup_module();
++#endif
++#if defined(CONFIG_ACX_CS)
++      acx_cs_cleanup();
++#endif
++}
++
++module_init(acx_e_init_module)
++module_exit(acx_e_cleanup_module)
+Index: linux-2.6.22/drivers/net/wireless/acx/conv.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/drivers/net/wireless/acx/conv.c       2007-08-23 18:34:19.000000000 +0200
+@@ -0,0 +1,504 @@
++/***********************************************************************
++** Copyright (C) 2003  ACX100 Open Source Project
++**
++** The contents of this file are subject to the Mozilla Public
++** License Version 1.1 (the "License"); you may not use this file
++** except in compliance with the License. You may obtain a copy of
++** the License at http://www.mozilla.org/MPL/
++**
++** Software distributed under the License is distributed on an "AS
++** IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
++** implied. See the License for the specific language governing
++** rights and limitations under the License.
++**
++** Alternatively, the contents of this file may be used under the
++** terms of the GNU Public License version 2 (the "GPL"), in which
++** case the provisions of the GPL are applicable instead of the
++** above.  If you wish to allow the use of your version of this file
++** only under the terms of the GPL and not to allow others to use
++** your version of this file under the MPL, indicate your decision
++** by deleting the provisions above and replace them with the notice
++** and other provisions required by the GPL.  If you do not delete
++** the provisions above, a recipient may use your version of this
++** file under either the MPL or the GPL.
++** ---------------------------------------------------------------------
++** Inquiries regarding the ACX100 Open Source Project can be
++** made directly to:
++**
++** acx100-users@lists.sf.net
++** http://acx100.sf.net
++** ---------------------------------------------------------------------
++*/
++
++#include <linux/version.h>
++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18)
++#include <linux/config.h>
++#endif
++#include <linux/skbuff.h>
++#include <linux/if_arp.h>
++#include <linux/etherdevice.h>
++#include <linux/wireless.h>
++#include <net/iw_handler.h>
++
++#include "acx.h"
++
++
++/***********************************************************************
++** proto_is_stt
++**
++** Searches the 802.1h Selective Translation Table for a given
++** protocol.
++**
++** prottype - protocol number (in host order) to search for.
++**
++** Returns:
++**    1 - if the table is empty or a match is found.
++**    0 - if the table is non-empty and a match is not found.
++**
++** Based largely on p80211conv.c of the linux-wlan-ng project
++*/
++static inline int
++proto_is_stt(unsigned int proto)
++{
++      /* Always return found for now.  This is the behavior used by the */
++      /* Zoom Win95 driver when 802.1h mode is selected */
++      /* TODO: If necessary, add an actual search we'll probably
++               need this to match the CMAC's way of doing things.
++               Need to do some testing to confirm.
++      */
++
++      if (proto == 0x80f3)  /* APPLETALK */
++              return 1;
++
++      return 0;
++/*    return ((prottype == ETH_P_AARP) || (prottype == ETH_P_IPX)); */
++}
++
++/* Helpers */
++
++static inline void
++store_llc_snap(struct wlan_llc *llc)
++{
++      llc->dsap = 0xaa;       /* SNAP, see IEEE 802 */
++      llc->ssap = 0xaa;
++      llc->ctl = 0x03;
++}
++static inline int
++llc_is_snap(const struct wlan_llc *llc)
++{
++      return (llc->dsap == 0xaa)
++      && (llc->ssap == 0xaa)
++      && (llc->ctl == 0x03);
++}
++static inline void
++store_oui_rfc1042(struct wlan_snap *snap)
++{
++      snap->oui[0] = 0;
++      snap->oui[1] = 0;
++      snap->oui[2] = 0;
++}
++static inline int
++oui_is_rfc1042(const struct wlan_snap *snap)
++{
++      return (snap->oui[0] == 0)
++      && (snap->oui[1] == 0)
++      && (snap->oui[2] == 0);
++}
++static inline void
++store_oui_8021h(struct wlan_snap *snap)
++{
++      snap->oui[0] = 0;
++      snap->oui[1] = 0;
++      snap->oui[2] = 0xf8;
++}
++static inline int
++oui_is_8021h(const struct wlan_snap *snap)
++{
++      return (snap->oui[0] == 0)
++      && (snap->oui[1] == 0)
++      && (snap->oui[2] == 0xf8);
++}
++
++
++/***********************************************************************
++** acx_ether_to_txbuf
++**
++** Uses the contents of the ether frame to build the elements of
++** the 802.11 frame.
++**
++** We don't actually set up the frame header here.  That's the
++** MAC's job.  We're only handling conversion of DIXII or 802.3+LLC
++** frames to something that works with 802.11.
++**
++** Based largely on p80211conv.c of the linux-wlan-ng project
++*/
++int
++acx_ether_to_txbuf(acx_device_t *adev, void *txbuf, const struct sk_buff *skb)
++{
++      struct wlan_hdr_a3 *w_hdr;
++      struct wlan_ethhdr *e_hdr;
++      struct wlan_llc *e_llc;
++      struct wlan_snap *e_snap;
++      const u8 *a1, *a3;
++      int header_len, payload_len = -1;
++      /* protocol type or data length, depending on whether
++       * DIX or 802.3 ethernet format */
++      u16 proto;
++      u16 fc;
++
++      FN_ENTER;
++
++      if (unlikely(!skb->len)) {
++              log(L_DEBUG, "zero-length skb!\n");
++              goto end;
++      }
++
++      w_hdr = (struct wlan_hdr_a3*)txbuf;
++
++      switch (adev->mode) {
++      case ACX_MODE_MONITOR:
++              /* NB: one day we might want to play with DESC_CTL2_FCS
++              ** Will need to stop doing "- WLAN_FCS_LEN" here then */
++              if (unlikely(skb->len >= WLAN_A4FR_MAXLEN_WEP_FCS - WLAN_FCS_LEN)) {
++                      printk("%s: can't tx oversized frame (%d bytes)\n",
++                              adev->ndev->name, skb->len);
++                      goto end;
++              }
++              memcpy(w_hdr, skb->data, skb->len);
++              payload_len = skb->len;
++              goto end;
++      }
++
++      /* step 1: classify ether frame, DIX or 802.3? */
++      e_hdr = (wlan_ethhdr_t *)skb->data;
++      proto = ntohs(e_hdr->type);
++      if (proto <= 1500) {
++              log(L_DEBUG, "tx: 802.3 len: %d\n", skb->len);
++              /* codes <= 1500 reserved for 802.3 lengths */
++              /* it's 802.3, pass ether payload unchanged, */
++              /* trim off ethernet header and copy payload to txdesc */
++              header_len = WLAN_HDR_A3_LEN;
++      } else {
++              /* it's DIXII, time for some conversion */
++              /* Create 802.11 packet. Header also contains llc and snap. */
++
++              log(L_DEBUG, "tx: DIXII len: %d\n", skb->len);
++
++              /* size of header is 802.11 header + llc + snap */
++              header_len = WLAN_HDR_A3_LEN + sizeof(wlan_llc_t) + sizeof(wlan_snap_t);
++              /* llc is located behind the 802.11 header */
++              e_llc = (wlan_llc_t*)(w_hdr + 1);
++              /* snap is located behind the llc */
++              e_snap = (wlan_snap_t*)(e_llc + 1);
++
++              /* setup the LLC header */
++              store_llc_snap(e_llc);
++
++              /* setup the SNAP header */
++              e_snap->type = htons(proto);
++              if (proto_is_stt(proto)) {
++                      store_oui_8021h(e_snap);
++              } else {
++                      store_oui_rfc1042(e_snap);
++              }
++      }
++      /* trim off ethernet header and copy payload to txbuf */
++      payload_len = skb->len - sizeof(wlan_ethhdr_t);
++      /* TODO: can we just let acx DMA payload from skb instead? */
++      memcpy((u8*)txbuf + header_len, skb->data + sizeof(wlan_ethhdr_t), payload_len);
++      payload_len += header_len;
++
++      /* Set up the 802.11 header */
++      switch (adev->mode) {
++      case ACX_MODE_0_ADHOC:
++              fc = (WF_FTYPE_DATAi | WF_FSTYPE_DATAONLYi);
++              a1 = e_hdr->daddr;
++              a3 = adev->bssid;
++              break;
++      case ACX_MODE_2_STA:
++              fc = (WF_FTYPE_DATAi | WF_FSTYPE_DATAONLYi | WF_FC_TODSi);
++              a1 = adev->bssid;
++              a3 = e_hdr->daddr;
++              break;
++      case ACX_MODE_3_AP:
++              fc = (WF_FTYPE_DATAi | WF_FSTYPE_DATAONLYi | WF_FC_FROMDSi);
++              a1 = e_hdr->daddr;
++              a3 = e_hdr->saddr;
++              break;
++      default:
++              printk("%s: error - converting eth to wlan in unknown mode\n",
++                              adev->ndev->name);
++              payload_len = -1;
++              goto end;
++      }
++      if (adev->wep_enabled)
++              SET_BIT(fc, WF_FC_ISWEPi);
++
++      w_hdr->fc = fc;
++      w_hdr->dur = 0;
++      MAC_COPY(w_hdr->a1, a1);
++      MAC_COPY(w_hdr->a2, adev->dev_addr);
++      MAC_COPY(w_hdr->a3, a3);
++      w_hdr->seq = 0;
++
++#ifdef DEBUG_CONVERT
++      if (acx_debug & L_DATA) {
++              printk("original eth frame [%d]: ", skb->len);
++              acx_dump_bytes(skb->data, skb->len);
++              printk("802.11 frame [%d]: ", payload_len);
++              acx_dump_bytes(w_hdr, payload_len);
++      }
++#endif
++
++end:
++      FN_EXIT1(payload_len);
++      return payload_len;
++}
++
++
++/***********************************************************************
++** acx_rxbuf_to_ether
++**
++** Uses the contents of a received 802.11 frame to build an ether
++** frame.
++**
++** This function extracts the src and dest address from the 802.11
++** frame to use in the construction of the eth frame.
++**
++** Based largely on p80211conv.c of the linux-wlan-ng project
++*/
++struct sk_buff*
++acx_rxbuf_to_ether(acx_device_t *adev, rxbuffer_t *rxbuf)
++{
++      struct wlan_hdr *w_hdr;
++      struct wlan_ethhdr *e_hdr;
++      struct wlan_llc *e_llc;
++      struct wlan_snap *e_snap;
++      struct sk_buff *skb;
++      const u8 *daddr;
++      const u8 *saddr;
++      const u8 *e_payload;
++      int buflen, payload_length;
++      unsigned int payload_offset, mtu;
++      u16 fc;
++
++      FN_ENTER;
++
++      /* This looks complex because it must handle possible
++      ** phy header in rxbuff */
++      w_hdr = acx_get_wlan_hdr(adev, rxbuf);
++      payload_offset = WLAN_HDR_A3_LEN; /* it is relative to w_hdr */
++      payload_length = RXBUF_BYTES_USED(rxbuf) /* entire rxbuff... */
++              - ((u8*)w_hdr - (u8*)rxbuf) /* minus space before 802.11 frame */
++              - WLAN_HDR_A3_LEN; /* minus 802.11 header */
++
++      /* setup some vars for convenience */
++      fc = w_hdr->fc;
++      switch (WF_FC_FROMTODSi & fc) {
++      case 0:
++              daddr = w_hdr->a1;
++              saddr = w_hdr->a2;
++              break;
++      case WF_FC_FROMDSi:
++              daddr = w_hdr->a1;
++              saddr = w_hdr->a3;
++              break;
++      case WF_FC_TODSi:
++              daddr = w_hdr->a3;
++              saddr = w_hdr->a2;
++              break;
++      default: /* WF_FC_FROMTODSi */
++              payload_offset += (WLAN_HDR_A4_LEN - WLAN_HDR_A3_LEN);
++              payload_length -= (WLAN_HDR_A4_LEN - WLAN_HDR_A3_LEN);
++              daddr = w_hdr->a3;
++              saddr = w_hdr->a4;
++      }
++
++      if ((WF_FC_ISWEPi & fc) && IS_ACX100(adev)) {
++              /* chop off the IV+ICV WEP header and footer */
++              log(L_DATA|L_DEBUG, "rx: WEP packet, "
++                      "chopping off IV and ICV\n");
++              payload_offset += WLAN_WEP_IV_LEN;
++              payload_length -= WLAN_WEP_IV_LEN + WLAN_WEP_ICV_LEN;
++      }
++
++      if (unlikely(payload_length < 0)) {
++              printk("%s: rx frame too short, ignored\n", adev->ndev->name);
++              goto ret_null;
++      }
++
++      e_hdr = (wlan_ethhdr_t*) ((u8*) w_hdr + payload_offset);
++      e_llc = (wlan_llc_t*) e_hdr;
++      e_snap = (wlan_snap_t*) (e_llc + 1);
++      mtu = adev->ndev->mtu;
++      e_payload = (u8*) (e_snap + 1);
++
++      log(L_DATA, "rx: payload_offset %d, payload_length %d\n",
++              payload_offset, payload_length);
++      log(L_XFER|L_DATA,
++              "rx: frame info: llc=%02X%02X%02X "
++              "snap.oui=%02X%02X%02X snap.type=%04X\n",
++              e_llc->dsap, e_llc->ssap, e_llc->ctl,
++              e_snap->oui[0], e_snap->oui[1], e_snap->oui[2],
++              ntohs(e_snap->type));
++
++      /* Test for the various encodings */
++      if ((payload_length >= sizeof(wlan_ethhdr_t))
++       && ((e_llc->dsap != 0xaa) || (e_llc->ssap != 0xaa))
++       && (   (mac_is_equal(daddr, e_hdr->daddr))
++           || (mac_is_equal(saddr, e_hdr->saddr))
++          )
++      ) {
++      /* 802.3 Encapsulated: */
++      /* wlan frame body contains complete eth frame (header+body) */
++              log(L_DEBUG|L_DATA, "rx: 802.3 ENCAP len=%d\n", payload_length);
++
++              if (unlikely(payload_length > (mtu + ETH_HLEN))) {
++                      printk("%s: rx: ENCAP frame too large (%d > %d)\n",
++                              adev->ndev->name,
++                              payload_length, mtu + ETH_HLEN);
++                      goto ret_null;
++              }
++
++              /* allocate space and setup host buffer */
++              buflen = payload_length;
++              /* Attempt to align IP header (14 bytes eth header + 2 = 16) */
++              skb = dev_alloc_skb(buflen + 2);
++              if (unlikely(!skb))
++                      goto no_skb;
++              skb_reserve(skb, 2);
++              skb_put(skb, buflen);           /* make room */
++
++              /* now copy the data from the 80211 frame */
++              memcpy(skb->data, e_hdr, payload_length);
++
++      } else if ( (payload_length >= sizeof(wlan_llc_t)+sizeof(wlan_snap_t))
++               && llc_is_snap(e_llc) ) {
++      /* wlan frame body contains: AA AA 03 ... (it's a SNAP) */
++
++              if ( !oui_is_rfc1042(e_snap)
++               || (proto_is_stt(ieee2host16(e_snap->type)) /* && (ethconv == WLAN_ETHCONV_8021h) */)) {
++                      log(L_DEBUG|L_DATA, "rx: SNAP+RFC1042 len=%d\n", payload_length);
++      /* wlan frame body contains: AA AA 03 !(00 00 00) ... -or- */
++      /* wlan frame body contains: AA AA 03 00 00 00 0x80f3 ... */
++      /* build eth hdr, type = len, copy AA AA 03... as eth body */
++                      /* it's a SNAP + RFC1042 frame && protocol is in STT */
++
++                      if (unlikely(payload_length > mtu)) {
++                              printk("%s: rx: SNAP frame too large (%d > %d)\n",
++                                      adev->ndev->name,
++                                      payload_length, mtu);
++                              goto ret_null;
++                      }
++
++                      /* allocate space and setup host buffer */
++                      buflen = payload_length + ETH_HLEN;
++                      skb = dev_alloc_skb(buflen + 2);
++                      if (unlikely(!skb))
++                              goto no_skb;
++                      skb_reserve(skb, 2);
++                      skb_put(skb, buflen);           /* make room */
++
++                      /* create 802.3 header */
++                      e_hdr = (wlan_ethhdr_t*) skb->data;
++                      MAC_COPY(e_hdr->daddr, daddr);
++                      MAC_COPY(e_hdr->saddr, saddr);
++                      e_hdr->type = htons(payload_length);
++
++                      /* Now copy the data from the 80211 frame.
++                         Make room in front for the eth header, and keep the
++                         llc and snap from the 802.11 payload */
++                      memcpy(skb->data + ETH_HLEN,
++                                      e_llc, payload_length);
++
++              } else {
++      /* wlan frame body contains: AA AA 03 00 00 00 [type] [tail] */
++      /* build eth hdr, type=[type], copy [tail] as eth body */
++                      log(L_DEBUG|L_DATA, "rx: 802.1h/RFC1042 len=%d\n",
++                              payload_length);
++                      /* it's an 802.1h frame (an RFC1042 && protocol is not in STT) */
++                      /* build a DIXII + RFC894 */
++
++                      payload_length -= sizeof(wlan_llc_t) + sizeof(wlan_snap_t);
++                      if (unlikely(payload_length > mtu)) {
++                              printk("%s: rx: DIXII frame too large (%d > %d)\n",
++                                      adev->ndev->name,
++                                      payload_length, mtu);
++                              goto ret_null;
++                      }
++
++                      /* allocate space and setup host buffer */
++                      buflen = payload_length + ETH_HLEN;
++                      skb = dev_alloc_skb(buflen + 2);
++                      if (unlikely(!skb))
++                              goto no_skb;
++                      skb_reserve(skb, 2);
++                      skb_put(skb, buflen);           /* make room */
++
++                      /* create 802.3 header */
++                      e_hdr = (wlan_ethhdr_t *) skb->data;
++                      MAC_COPY(e_hdr->daddr, daddr);
++                      MAC_COPY(e_hdr->saddr, saddr);
++                      e_hdr->type = e_snap->type;
++
++                      /* Now copy the data from the 80211 frame.
++                         Make room in front for the eth header, and cut off the
++                         llc and snap from the 802.11 payload */
++                      memcpy(skb->data + ETH_HLEN,
++                                      e_payload, payload_length);
++              }
++
++      } else {
++              log(L_DEBUG|L_DATA, "rx: NON-ENCAP len=%d\n", payload_length);
++      /* build eth hdr, type=len, copy wlan body as eth body */
++              /* any NON-ENCAP */
++              /* it's a generic 80211+LLC or IPX 'Raw 802.3' */
++              /* build an 802.3 frame */
++
++              if (unlikely(payload_length > mtu)) {
++                      printk("%s: rx: OTHER frame too large (%d > %d)\n",
++                              adev->ndev->name, payload_length, mtu);
++                      goto ret_null;
++              }
++
++              /* allocate space and setup host buffer */
++              buflen = payload_length + ETH_HLEN;
++              skb = dev_alloc_skb(buflen + 2);
++              if (unlikely(!skb))
++                      goto no_skb;
++              skb_reserve(skb, 2);
++              skb_put(skb, buflen);           /* make room */
++
++              /* set up the 802.3 header */
++              e_hdr = (wlan_ethhdr_t *) skb->data;
++              MAC_COPY(e_hdr->daddr, daddr);
++              MAC_COPY(e_hdr->saddr, saddr);
++              e_hdr->type = htons(payload_length);
++
++              /* now copy the data from the 80211 frame */
++              memcpy(skb->data + ETH_HLEN, e_llc, payload_length);
++      }
++
++      skb->dev = adev->ndev;
++      skb->protocol = eth_type_trans(skb, adev->ndev);
++
++#ifdef DEBUG_CONVERT
++      if (acx_debug & L_DATA) {
++              int len = RXBUF_BYTES_RCVD(adev, rxbuf);
++              printk("p802.11 frame [%d]: ", len);
++              acx_dump_bytes(w_hdr, len);
++              printk("eth frame [%d]: ", skb->len);
++              acx_dump_bytes(skb->data, skb->len);
++      }
++#endif
++
++      FN_EXIT0;
++      return skb;
++
++no_skb:
++      printk("%s: rx: no memory for skb (%d bytes)\n",
++                      adev->ndev->name, buflen + 2);
++ret_null:
++      FN_EXIT1((int)NULL);
++      return NULL;
++}
+Index: linux-2.6.22/drivers/net/wireless/acx/cs.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/drivers/net/wireless/acx/cs.c 2007-08-23 18:34:19.000000000 +0200
+@@ -0,0 +1,5703 @@
++/***********************************************************************
++** Copyright (C) 2003  ACX100 Open Source Project
++**
++** The contents of this file are subject to the Mozilla Public
++** License Version 1.1 (the "License"); you may not use this file
++** except in compliance with the License. You may obtain a copy of
++** the License at http://www.mozilla.org/MPL/
++**
++** Software distributed under the License is distributed on an "AS
++** IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
++** implied. See the License for the specific language governing
++** rights and limitations under the License.
++**
++** Alternatively, the contents of this file may be used under the
++** terms of the GNU Public License version 2 (the "GPL"), in which
++** case the provisions of the GPL are applicable instead of the
++** above.  If you wish to allow the use of your version of this file
++** only under the terms of the GPL and not to allow others to use
++** your version of this file under the MPL, indicate your decision
++** by deleting the provisions above and replace them with the notice
++** and other provisions required by the GPL.  If you do not delete
++** the provisions above, a recipient may use your version of this
++** file under either the MPL or the GPL.
++** ---------------------------------------------------------------------
++** Inquiries regarding the ACX100 Open Source Project can be
++** made directly to:
++**
++** acx100-users@lists.sf.net
++** http://acx100.sf.net
++** ---------------------------------------------------------------------
++**
++** Slave memory interface support:
++**
++** Todd Blumer - SDG Systems
++** Bill Reese - HP
++** Eric McCorkle - Shadowsun
++**
++** CF support, (c) Fabrice Crohas, Paul Sokolovsky
++*/
++#define ACX_MEM 1
++
++/*
++ * non-zero makes it dump the ACX memory to the console then
++ * panic when you cat /proc/driver/acx_wlan0_diag
++ */
++#define DUMP_MEM_DEFINED 1
++
++#define DUMP_MEM_DURING_DIAG 0
++#define DUMP_IF_SLOW 0
++
++#define PATCH_AROUND_BAD_SPOTS 1
++#define HX4700_FIRMWARE_CHECKSUM 0x0036862e
++#define HX4700_ALTERNATE_FIRMWARE_CHECKSUM 0x00368a75
++
++#include <linux/version.h>
++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18)
++#include <linux/config.h>
++#endif
++
++/* Linux 2.6.18+ uses <linux/utsrelease.h> */
++#ifndef UTS_RELEASE
++#include <linux/utsrelease.h>
++#endif
++
++#include <linux/compiler.h> /* required for Lx 2.6.8 ?? */
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/sched.h>
++#include <linux/types.h>
++#include <linux/skbuff.h>
++#include <linux/slab.h>
++#include <linux/if_arp.h>
++#include <linux/irq.h>
++#include <linux/rtnetlink.h>
++#include <linux/wireless.h>
++#include <net/iw_handler.h>
++#include <linux/netdevice.h>
++#include <linux/ioport.h>
++#include <linux/pci.h>
++#include <linux/platform_device.h>
++#include <linux/pm.h>
++#include <linux/vmalloc.h>
++#include <linux/delay.h>
++#include <linux/workqueue.h>
++#include <linux/inetdevice.h>
++
++#define PCMCIA_DEBUG 1
++
++/*
++   All the PCMCIA modules use PCMCIA_DEBUG to control debugging.  If
++   you do not define PCMCIA_DEBUG at all, all the debug code will be
++   left out.  If you compile with PCMCIA_DEBUG=0, the debug code will
++   be present but disabled -- but it can then be enabled for specific
++   modules at load time with a 'pc_debug=#' option to insmod.
++      
++*/
++#include <pcmcia/cs_types.h>
++#include <pcmcia/cs.h>
++#include <pcmcia/cistpl.h>
++#include <pcmcia/cisreg.h>
++#include <pcmcia/ds.h>
++#include "acx.h"
++#include "acx_hw.h"
++
++#ifdef PCMCIA_DEBUG
++static int pc_debug = PCMCIA_DEBUG;
++module_param(pc_debug, int, 0);
++static char *version = "$Revision: 1.10 $";
++#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args);
++#else
++#define DEBUG(n, args...)
++#endif
++
++
++static win_req_t memwin;
++
++typedef struct local_info_t {
++        dev_node_t      node;
++        struct net_device *ndev;
++} local_info_t;
++
++static struct net_device *resume_ndev;
++
++
++/***********************************************************************
++*/
++
++#define CARD_EEPROM_ID_SIZE 6
++
++#include <asm/io.h>
++
++#define REG_ACX_VENDOR_ID 0x900
++/*
++ * This is the vendor id on the HX4700, anyway
++ */
++#define ACX_VENDOR_ID 0x8400104c
++
++typedef enum {
++      ACX_SOFT_RESET = 0,
++
++      ACX_SLV_REG_ADDR,
++      ACX_SLV_REG_DATA,
++      ACX_SLV_REG_ADATA,
++
++      ACX_SLV_MEM_CP,
++      ACX_SLV_MEM_ADDR,
++      ACX_SLV_MEM_DATA,
++      ACX_SLV_MEM_CTL,
++} acxreg_t;
++
++/***********************************************************************
++*/
++static void acxmem_i_tx_timeout(struct net_device *ndev);
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
++static irqreturn_t acxmem_i_interrupt(int irq, void *dev_id);
++#else
++static irqreturn_t acxmem_i_interrupt(int irq, void *dev_id, struct pt_regs *regs);
++#endif
++static void acxmem_i_set_multicast_list(struct net_device *ndev);
++
++static int acxmem_e_open(struct net_device *ndev);
++static int acxmem_e_close(struct net_device *ndev);
++static void acxmem_s_up(struct net_device *ndev);
++static void acxmem_s_down(struct net_device *ndev);
++
++static void dump_acxmem (acx_device_t *adev, u32 start, int length);
++static int acxmem_complete_hw_reset (acx_device_t *adev);
++static void acxmem_s_delete_dma_regions(acx_device_t *adev);
++
++static int
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11)
++acxmem_e_suspend( struct net_device *ndev, pm_message_t state);
++#else
++acxmem_e_suspend( struct net_device *ndev, u32 state);
++#endif
++static void
++fw_resumer(struct work_struct *notused);
++//fw_resumer( void *data );
++
++static int acx_netdev_event(struct notifier_block *this, unsigned long event, void *ptr)
++{
++  struct net_device *ndev = ptr;
++  acx_device_t *adev = ndev2adev(ndev);
++
++  /*
++   * Upper level ioctl() handlers send a NETDEV_CHANGEADDR if the MAC address changes.
++   */
++
++  if (NETDEV_CHANGEADDR == event) {
++    /*
++     * the upper layers put the new MAC address in ndev->dev_addr; we just copy
++     * it over and update the ACX with it.
++     */
++    MAC_COPY(adev->dev_addr, adev->ndev->dev_addr);
++    adev->set_mask |= GETSET_STATION_ID;
++    acx_s_update_card_settings (adev);
++  }
++
++  return 0;
++}
++
++static struct notifier_block acx_netdev_notifier = {
++        .notifier_call = acx_netdev_event,
++};
++
++/***********************************************************************
++** Register access
++*/
++
++/* Pick one */
++/* #define INLINE_IO static */
++#define INLINE_IO static inline
++
++INLINE_IO u32
++read_id_register (acx_device_t *adev)
++{
++  writel (0x24, &adev->iobase[ACX_SLV_REG_ADDR]);
++  return readl (&adev->iobase[ACX_SLV_REG_DATA]);
++}
++
++INLINE_IO u32
++read_reg32(acx_device_t *adev, unsigned int offset)
++{
++        u32 val;
++      u32 addr;
++
++        if (offset > IO_ACX_ECPU_CTRL)
++        addr = offset;
++      else
++        addr = adev->io[offset];
++
++      if (addr < 0x20) {
++        return readl(((u8*)adev->iobase) + addr);
++      }
++
++      writel( addr, &adev->iobase[ACX_SLV_REG_ADDR] );
++      val = readl( &adev->iobase[ACX_SLV_REG_DATA] );
++
++      return val;
++}
++
++INLINE_IO u16
++read_reg16(acx_device_t *adev, unsigned int offset)
++{
++      u16 lo;
++      u32 addr;
++
++        if (offset > IO_ACX_ECPU_CTRL)
++        addr = offset;
++      else
++        addr = adev->io[offset];
++
++      if (addr < 0x20) {
++          return readw(((u8 *) adev->iobase) + addr);
++      }
++
++      writel( addr, &adev->iobase[ACX_SLV_REG_ADDR] );
++      lo = readw( (u16 *)&adev->iobase[ACX_SLV_REG_DATA] );
++
++      return lo;
++}
++
++INLINE_IO u8
++read_reg8(acx_device_t *adev, unsigned int offset)
++{
++      u8 lo;
++      u32 addr;
++
++        if (offset > IO_ACX_ECPU_CTRL)
++        addr = offset;
++      else
++        addr = adev->io[offset];
++
++      if (addr < 0x20)
++          return readb(((u8 *)adev->iobase) + addr);
++
++      writel( addr, &adev->iobase[ACX_SLV_REG_ADDR] );
++      lo = readw( (u8 *)&adev->iobase[ACX_SLV_REG_DATA] );
++
++      return (u8)lo;
++}
++
++INLINE_IO void
++write_reg32(acx_device_t *adev, unsigned int offset, u32 val)
++{
++      u32 addr;
++
++        if (offset > IO_ACX_ECPU_CTRL)
++        addr = offset;
++      else
++        addr = adev->io[offset];
++
++      if (addr < 0x20) {
++          writel(val, ((u8*)adev->iobase) + addr);
++          return;
++      }
++
++      writel( addr, &adev->iobase[ACX_SLV_REG_ADDR] );
++      writel( val, &adev->iobase[ACX_SLV_REG_DATA] );
++}
++
++INLINE_IO void
++write_reg16(acx_device_t *adev, unsigned int offset, u16 val)
++{
++      u32 addr;
++
++        if (offset > IO_ACX_ECPU_CTRL)
++        addr = offset;
++      else
++        addr = adev->io[offset];
++
++      if (addr < 0x20) {
++          writew(val, ((u8 *)adev->iobase) + addr);
++          return;
++      }
++      writel( addr, &adev->iobase[ACX_SLV_REG_ADDR] );
++      writew( val, (u16 *) &adev->iobase[ACX_SLV_REG_DATA] );
++}
++
++INLINE_IO void
++write_reg8(acx_device_t *adev, unsigned int offset, u8 val)
++{
++      u32 addr;
++
++        if (offset > IO_ACX_ECPU_CTRL)
++        addr = offset;
++      else
++        addr = adev->io[offset];
++
++      if (addr < 0x20) {
++          writeb(val, ((u8 *) adev->iobase) + addr);
++          return;
++      }
++      writel( addr, &adev->iobase[ACX_SLV_REG_ADDR] );
++      writeb( val, (u8 *)&adev->iobase[ACX_SLV_REG_DATA] );
++}
++
++/* Handle PCI posting properly:
++ * Make sure that writes reach the adapter in case they require to be executed
++ * *before* the next write, by reading a random (and safely accessible) register.
++ * This call has to be made if there is no read following (which would flush the data
++ * to the adapter), yet the written data has to reach the adapter immediately. */
++INLINE_IO void
++write_flush(acx_device_t *adev)
++{
++      /* readb(adev->iobase + adev->io[IO_ACX_INFO_MAILBOX_OFFS]); */
++      /* faster version (accesses the first register, IO_ACX_SOFT_RESET,
++       * which should also be safe): */
++      (void) readl(adev->iobase);
++}
++
++INLINE_IO void
++set_regbits (acx_device_t *adev, unsigned int offset, u32 bits) {
++  u32 tmp;
++
++  tmp = read_reg32 (adev, offset);
++  tmp = tmp | bits;
++  write_reg32 (adev, offset, tmp);
++  write_flush (adev);
++}
++
++INLINE_IO void
++clear_regbits (acx_device_t *adev, unsigned int offset, u32 bits) {
++  u32 tmp;
++
++  tmp = read_reg32 (adev, offset);
++  tmp = tmp & ~bits;
++  write_reg32 (adev, offset, tmp);
++  write_flush (adev);
++}
++
++/*
++ * Copy from PXA memory to the ACX memory.  This assumes both the PXA and ACX
++ * addresses are 32 bit aligned.  Count is in bytes.
++ */
++INLINE_IO void
++write_slavemem32 (acx_device_t *adev, u32 slave_address, u32 val)
++{
++  write_reg32 (adev, IO_ACX_SLV_MEM_CTL, 0x0);
++  write_reg32 (adev, IO_ACX_SLV_MEM_ADDR, slave_address);
++  udelay (10);
++  write_reg32 (adev, IO_ACX_SLV_MEM_DATA, val);
++}
++
++INLINE_IO u32
++read_slavemem32 (acx_device_t *adev, u32 slave_address)
++{
++  u32 val;
++
++  write_reg32 (adev, IO_ACX_SLV_MEM_CTL, 0x0);
++  write_reg32 (adev, IO_ACX_SLV_MEM_ADDR, slave_address);
++  udelay (10);
++  val = read_reg32 (adev, IO_ACX_SLV_MEM_DATA);
++
++  return val;
++}
++
++INLINE_IO void
++write_slavemem8 (acx_device_t *adev, u32 slave_address, u8 val)
++{
++  u32 data;
++  u32 base;
++  int offset;
++
++  /*
++   * Get the word containing the target address and the byte offset in that word.
++   */
++  base = slave_address & ~3;
++  offset = (slave_address & 3) * 8;
++
++  data = read_slavemem32 (adev, base);
++  data &= ~(0xff << offset);
++  data |= val << offset;
++  write_slavemem32 (adev, base, data);
++}
++
++INLINE_IO u8
++read_slavemem8 (acx_device_t *adev, u32 slave_address)
++{
++  u8 val;
++  u32 base;
++  u32 data;
++  int offset;
++
++  base = slave_address & ~3;
++  offset = (slave_address & 3) * 8;
++
++  data = read_slavemem32 (adev, base);
++ 
++  val = (data >> offset) & 0xff;
++
++  return val;
++}
++
++/*
++ * doesn't split across word boundaries
++ */
++INLINE_IO void
++write_slavemem16 (acx_device_t *adev, u32 slave_address, u16 val)
++{
++  u32 data;
++  u32 base;
++  int offset;
++
++  /*
++   * Get the word containing the target address and the byte offset in that word.
++   */
++  base = slave_address & ~3;
++  offset = (slave_address & 3) * 8;
++
++  data = read_slavemem32 (adev, base);
++  data &= ~(0xffff << offset);
++  data |= val << offset;
++  write_slavemem32 (adev, base, data);
++}
++
++/*
++ * doesn't split across word boundaries
++ */
++INLINE_IO u16
++read_slavemem16 (acx_device_t *adev, u32 slave_address)
++{
++  u16 val;
++  u32 base;
++  u32 data;
++  int offset;
++
++  base = slave_address & ~3;
++  offset = (slave_address & 3) * 8;
++
++  data = read_slavemem32 (adev, base);
++ 
++  val = (data >> offset) & 0xffff;
++
++  return val;
++}
++
++/*
++ * Copy from slave memory
++ *
++ * TODO - rewrite using address autoincrement, handle partial words
++ */
++void
++copy_from_slavemem (acx_device_t *adev, u8 *destination, u32 source, int count) {
++  u32 tmp = 0;
++  u8 *ptmp = (u8 *) &tmp;
++
++  /*
++   * Right now I'm making the assumption that the destination is aligned, but
++   * I'd better check.
++   */
++  if ((u32) destination & 3) {
++    printk ("acx copy_from_slavemem: warning!  destination not word-aligned!\n");
++  }
++
++  while (count >= 4) {
++    write_reg32 (adev, IO_ACX_SLV_MEM_ADDR, source);
++    udelay (10);
++    *((u32 *) destination) = read_reg32 (adev, IO_ACX_SLV_MEM_DATA);
++    count -= 4;
++    source += 4;
++    destination += 4;
++  }
++
++  /*
++   * If the word reads above didn't satisfy the count, read one more word
++   * and transfer a byte at a time until the request is satisfied.
++   */
++  if (count) {
++    write_reg32 (adev, IO_ACX_SLV_MEM_ADDR, source);
++    udelay (10);
++    tmp = read_reg32 (adev, IO_ACX_SLV_MEM_DATA);
++    while (count--) {
++      *destination++ = *ptmp++;
++    }
++  }
++}
++
++/*
++ * Copy to slave memory
++ *
++ * TODO - rewrite using autoincrement, handle partial words
++ */
++void
++copy_to_slavemem (acx_device_t *adev, u32 destination, u8 *source, int count)
++{
++  u32 tmp = 0;
++  u8* ptmp = (u8 *) &tmp;
++  static u8 src[512]; /* make static to avoid huge stack objects */
++
++  /*
++   * For now, make sure the source is word-aligned by copying it to a word-aligned
++   * buffer.  Someday rewrite to avoid the extra copy.
++   */
++  if (count > sizeof (src)) {
++    printk ("acx copy_to_slavemem: Warning! buffer overflow!\n");
++    count = sizeof (src);
++  }
++  memcpy (src, source, count);
++  source = src;
++
++  while (count >= 4) {
++    write_reg32 (adev, IO_ACX_SLV_MEM_ADDR, destination);
++    udelay (10);
++    write_reg32 (adev, IO_ACX_SLV_MEM_DATA, *((u32 *) source));
++    count -= 4;
++    source += 4;
++    destination += 4;
++  }
++
++  /*
++   * If there are leftovers read the next word from the acx and merge in
++   * what they want to write.
++   */
++  if (count) {
++    write_reg32 (adev, IO_ACX_SLV_MEM_ADDR, destination);
++    udelay (10);
++    tmp = read_reg32 (adev, IO_ACX_SLV_MEM_DATA);
++    while (count--) {
++      *ptmp++ = *source++;
++    }
++    /*
++     * reset address in case we're currently in auto-increment mode
++     */
++    write_reg32 (adev, IO_ACX_SLV_MEM_ADDR, destination);
++    udelay (10);
++    write_reg32 (adev, IO_ACX_SLV_MEM_DATA, tmp);
++    udelay (10);
++  }
++  
++}
++
++/*
++ * Block copy to slave buffers using memory block chain mode.  Copies to the ACX
++ * transmit buffer structure with minimal intervention on our part.
++ * Interrupts should be disabled when calling this.
++ */
++void
++chaincopy_to_slavemem (acx_device_t *adev, u32 destination, u8 *source, int count)
++{
++  u32 val;
++  u32 *data = (u32 *) source;
++  static u8 aligned_source[WLAN_A4FR_MAXLEN_WEP_FCS];
++
++  /*
++   * Warn if the pointers don't look right.  Destination must fit in [23:5] with
++   * zero elsewhere and source should be 32 bit aligned.
++   * This should never happen since we're in control of both, but I want to know about
++   * it if it does.
++   */
++  if ((destination & 0x00ffffe0) != destination) {
++    printk ("acx chaincopy: destination block 0x%04x not aligned!\n", destination);
++  }
++  if (count > sizeof aligned_source) {
++      printk( KERN_ERR "chaincopy_to_slavemem overflow!\n" );
++      count = sizeof aligned_source;
++  }
++  if ((u32) source & 3) {
++    memcpy (aligned_source, source, count);
++    data = (u32 *) aligned_source;
++  }
++
++  /*
++   * SLV_MEM_CTL[17:16] = memory block chain mode with auto-increment
++   * SLV_MEM_CTL[5:2] = offset to data portion = 1 word
++   */
++  val = 2 << 16 | 1 << 2;
++  writel (val, &adev->iobase[ACX_SLV_MEM_CTL]);
++
++  /*
++   * SLV_MEM_CP[23:5] = start of 1st block
++   * SLV_MEM_CP[3:2] = offset to memblkptr = 0
++   */
++  val = destination & 0x00ffffe0;
++  writel (val, &adev->iobase[ACX_SLV_MEM_CP]);
++
++  /*
++   * SLV_MEM_ADDR[23:2] = SLV_MEM_CTL[5:2] + SLV_MEM_CP[23:5]
++   */
++  val = (destination & 0x00ffffe0) + (1<<2);
++  writel (val, &adev->iobase[ACX_SLV_MEM_ADDR]);
++
++  /*
++   * Write the data to the slave data register, rounding up to the end
++   * of the word containing the last byte (hence the > 0)
++   */
++  while (count > 0) {
++    writel (*data++, &adev->iobase[ACX_SLV_MEM_DATA]);
++    count -= 4;
++  }
++}
++
++
++/*
++ * Block copy from slave buffers using memory block chain mode.  Copies from the ACX
++ * receive buffer structures with minimal intervention on our part.
++ * Interrupts should be disabled when calling this.
++ */
++void
++chaincopy_from_slavemem (acx_device_t *adev, u8 *destination, u32 source, int count)
++{
++  u32 val;
++  u32 *data = (u32 *) destination;
++  static u8 aligned_destination[WLAN_A4FR_MAXLEN_WEP_FCS];
++  int saved_count = count;
++
++  /*
++   * Warn if the pointers don't look right.  Destination must fit in [23:5] with
++   * zero elsewhere and source should be 32 bit aligned.
++   * Turns out the network stack sends unaligned things, so fix them before
++   * copying to the ACX.
++   */
++  if ((source & 0x00ffffe0) != source) {
++    printk ("acx chaincopy: source block 0x%04x not aligned!\n", source);
++    dump_acxmem (adev, 0, 0x10000);
++  }
++  if ((u32) destination & 3) {
++    //printk ("acx chaincopy: data destination not word aligned!\n");
++    data = (u32 *) aligned_destination;
++    if (count > sizeof aligned_destination) {
++      printk( KERN_ERR "chaincopy_from_slavemem overflow!\n" );
++      count = sizeof aligned_destination;
++    }
++  }
++
++  /*
++   * SLV_MEM_CTL[17:16] = memory block chain mode with auto-increment
++   * SLV_MEM_CTL[5:2] = offset to data portion = 1 word
++   */
++  val = (2 << 16) | (1 << 2);
++  writel (val, &adev->iobase[ACX_SLV_MEM_CTL]);
++
++  /*
++   * SLV_MEM_CP[23:5] = start of 1st block
++   * SLV_MEM_CP[3:2] = offset to memblkptr = 0
++   */
++  val = source & 0x00ffffe0;
++  writel (val, &adev->iobase[ACX_SLV_MEM_CP]);
++
++  /*
++   * SLV_MEM_ADDR[23:2] = SLV_MEM_CTL[5:2] + SLV_MEM_CP[23:5]
++   */
++  val = (source & 0x00ffffe0) + (1<<2);
++  writel (val, &adev->iobase[ACX_SLV_MEM_ADDR]);
++
++  /*
++   * Read the data from the slave data register, rounding up to the end
++   * of the word containing the last byte (hence the > 0)
++   */
++  while (count > 0) {
++    *data++ = readl (&adev->iobase[ACX_SLV_MEM_DATA]);
++    count -= 4;
++  }
++
++  /*
++   * If the destination wasn't aligned, we would have saved it in
++   * the aligned buffer, so copy it where it should go.
++   */
++  if ((u32) destination & 3) {
++    memcpy (destination, aligned_destination, saved_count);
++  }
++}
++
++char
++printable (char c) 
++{
++  return ((c >= 20) && (c < 127)) ? c : '.';
++}
++
++#if DUMP_MEM_DEFINED > 0
++static void
++dump_acxmem (acx_device_t *adev, u32 start, int length)
++{
++  int i;
++  u8 buf[16];
++
++  while (length > 0) {
++    printk ("%04x ", start);
++    copy_from_slavemem (adev, buf, start, 16);
++    for (i = 0; (i < 16) && (i < length); i++) {
++      printk ("%02x ", buf[i]);
++    }
++    for (i = 0; (i < 16) && (i < length); i++) {
++      printk ("%c", printable (buf[i]));
++    }
++    printk ("\n");
++    start += 16;
++    length -= 16;
++  }
++}
++#endif
++
++static void
++enable_acx_irq(acx_device_t *adev);
++static void
++disable_acx_irq(acx_device_t *adev);
++
++/*
++ * Return an acx pointer to the next transmit data block.
++ */
++u32
++allocate_acx_txbuf_space (acx_device_t *adev, int count) {
++  u32 block, next, last_block;
++  int blocks_needed;
++  unsigned long flags;
++
++  spin_lock_irqsave(&adev->txbuf_lock, flags);
++  /*
++   * Take 4 off the memory block size to account for the reserved word at the start of
++   * the block.
++   */
++  blocks_needed = count / (adev->memblocksize - 4);
++  if (count % (adev->memblocksize - 4))
++    blocks_needed++;
++
++  if (blocks_needed <= adev->acx_txbuf_blocks_free) {
++    /*
++     * Take blocks at the head of the free list.
++     */
++    last_block = block = adev->acx_txbuf_free;
++
++    /*
++     * Follow block pointers through the requested number of blocks both to
++     * find the new head of the free list and to set the flags for the blocks
++     * appropriately.
++     */
++    while (blocks_needed--) {
++      /*
++       * Keep track of the last block of the allocation
++       */
++      last_block = adev->acx_txbuf_free;
++
++      /*
++       * Make sure the end control flag is not set.
++       */
++      next = read_slavemem32 (adev, adev->acx_txbuf_free) & 0x7ffff;
++      write_slavemem32 (adev, adev->acx_txbuf_free, next);
++
++      /*
++       * Update the new head of the free list
++       */
++      adev->acx_txbuf_free = next << 5;
++      adev->acx_txbuf_blocks_free--;
++
++    }
++
++    /*
++     * Flag the last block both by clearing out the next pointer
++     * and marking the control field.
++     */
++    write_slavemem32 (adev, last_block, 0x02000000);
++
++    /*
++     * If we're out of buffers make sure the free list pointer is NULL
++     */
++    if (!adev->acx_txbuf_blocks_free) {
++      adev->acx_txbuf_free = 0;
++    }
++  }
++  else {
++    block = 0;
++  }
++  spin_unlock_irqrestore (&adev->txbuf_lock, flags);
++  return block;
++}
++
++/*
++ * Return buffer space back to the pool by following the next pointers until we find
++ * the block marked as the end.  Point the last block to the head of the free list,
++ * then update the head of the free list to point to the newly freed memory.
++ * This routine gets called in interrupt context, so it shouldn't block to protect
++ * the integrity of the linked list.  The ISR already holds the lock.
++ */
++void
++reclaim_acx_txbuf_space (acx_device_t *adev, u32 blockptr) {
++  u32 cur, last, next;
++  unsigned long flags;
++
++  spin_lock_irqsave (&adev->txbuf_lock, flags);
++  if ((blockptr >= adev->acx_txbuf_start) &&
++      (blockptr <= adev->acx_txbuf_start +
++       (adev->acx_txbuf_numblocks - 1) * adev->memblocksize)) {
++    cur = blockptr;
++    do {
++      last = cur;
++      next = read_slavemem32 (adev, cur);
++      
++      /*
++       * Advance to the next block in this allocation
++       */
++      cur = (next & 0x7ffff) << 5;
++      
++      /*
++       * This block now counts as free.
++       */
++      adev->acx_txbuf_blocks_free++;
++    } while (!(next & 0x02000000));
++    
++    /*
++     * last now points to the last block of that allocation.  Update the pointer
++     * in that block to point to the free list and reset the free list to the
++     * first block of the free call.  If there were no free blocks, make sure
++     * the new end of the list marks itself as truly the end.
++     */
++    if (adev->acx_txbuf_free) {
++      write_slavemem32 (adev, last, adev->acx_txbuf_free >> 5);
++    }
++    else {
++      write_slavemem32 (adev, last, 0x02000000);
++    }
++    adev->acx_txbuf_free = blockptr;
++  } 
++  spin_unlock_irqrestore(&adev->txbuf_lock, flags);
++}
++
++/*
++ * Initialize the pieces managing the transmit buffer pool on the ACX.  The transmit
++ * buffer is a circular queue with one 32 bit word reserved at the beginning of each
++ * block.  The upper 13 bits are a control field, of which only 0x02000000 has any
++ * meaning.  The lower 19 bits are the address of the next block divided by 32.
++ */
++void
++init_acx_txbuf (acx_device_t *adev) {
++  
++  /*
++   * acx100_s_init_memory_pools set up txbuf_start and txbuf_numblocks for us.
++   * All we need to do is reset the rest of the bookeeping.
++   */
++  
++  adev->acx_txbuf_free = adev->acx_txbuf_start;
++  adev->acx_txbuf_blocks_free = adev->acx_txbuf_numblocks;
++  
++  /*
++   * Initialization leaves the last transmit pool block without a pointer back to
++   * the head of the list, but marked as the end of the list.  That's how we want
++   * to see it, too, so leave it alone.  This is only ever called after a firmware
++   * reset, so the ACX memory is in the state we want.
++   */
++      
++}
++
++INLINE_IO int
++adev_present(acx_device_t *adev)
++{
++      /* fast version (accesses the first register, IO_ACX_SOFT_RESET,
++       * which should be safe): */
++      return readl(adev->iobase) != 0xffffffff;
++}
++
++/***********************************************************************
++*/
++static inline txdesc_t*
++get_txdesc(acx_device_t *adev, int index)
++{
++      return (txdesc_t*) (((u8*)adev->txdesc_start) + index * adev->txdesc_size);
++}
++
++static inline txdesc_t*
++advance_txdesc(acx_device_t *adev, txdesc_t* txdesc, int inc)
++{
++      return (txdesc_t*) (((u8*)txdesc) + inc * adev->txdesc_size);
++}
++
++static txhostdesc_t*
++get_txhostdesc(acx_device_t *adev, txdesc_t* txdesc)
++{
++      int index = (u8*)txdesc - (u8*)adev->txdesc_start;
++      if (unlikely(ACX_DEBUG && (index % adev->txdesc_size))) {
++              printk("bad txdesc ptr %p\n", txdesc);
++              return NULL;
++      }
++      index /= adev->txdesc_size;
++      if (unlikely(ACX_DEBUG && (index >= TX_CNT))) {
++              printk("bad txdesc ptr %p\n", txdesc);
++              return NULL;
++      }
++      return &adev->txhostdesc_start[index*2];
++}
++
++static inline client_t*
++get_txc(acx_device_t *adev, txdesc_t* txdesc)
++{
++      int index = (u8*)txdesc - (u8*)adev->txdesc_start;
++      if (unlikely(ACX_DEBUG && (index % adev->txdesc_size))) {
++              printk("bad txdesc ptr %p\n", txdesc);
++              return NULL;
++      }
++      index /= adev->txdesc_size;
++      if (unlikely(ACX_DEBUG && (index >= TX_CNT))) {
++              printk("bad txdesc ptr %p\n", txdesc);
++              return NULL;
++      }
++      return adev->txc[index];
++}
++
++static inline u16
++get_txr(acx_device_t *adev, txdesc_t* txdesc)
++{
++      int index = (u8*)txdesc - (u8*)adev->txdesc_start;
++      index /= adev->txdesc_size;
++      return adev->txr[index];
++}
++
++static inline void
++put_txcr(acx_device_t *adev, txdesc_t* txdesc, client_t* c, u16 r111)
++{
++      int index = (u8*)txdesc - (u8*)adev->txdesc_start;
++      if (unlikely(ACX_DEBUG && (index % adev->txdesc_size))) {
++              printk("bad txdesc ptr %p\n", txdesc);
++              return;
++      }
++      index /= adev->txdesc_size;
++      if (unlikely(ACX_DEBUG && (index >= TX_CNT))) {
++              printk("bad txdesc ptr %p\n", txdesc);
++              return;
++      }
++      adev->txc[index] = c;
++      adev->txr[index] = r111;
++}
++
++
++/***********************************************************************
++** EEPROM and PHY read/write helpers
++*/
++/***********************************************************************
++** acxmem_read_eeprom_byte
++**
++** Function called to read an octet in the EEPROM.
++**
++** This function is used by acxmem_e_probe to check if the
++** connected card is a legal one or not.
++**
++** Arguments:
++**    adev            ptr to acx_device structure
++**    addr            address to read in the EEPROM
++**    charbuf         ptr to a char. This is where the read octet
++**                    will be stored
++*/
++int
++acxmem_read_eeprom_byte(acx_device_t *adev, u32 addr, u8 *charbuf)
++{
++      int result;
++      int count;
++
++      write_reg32(adev, IO_ACX_EEPROM_CFG, 0);
++      write_reg32(adev, IO_ACX_EEPROM_ADDR, addr);
++      write_flush(adev);
++      write_reg32(adev, IO_ACX_EEPROM_CTL, 2);
++
++      count = 0xffff;
++      while (read_reg16(adev, IO_ACX_EEPROM_CTL)) {
++              /* scheduling away instead of CPU burning loop
++               * doesn't seem to work here at all:
++               * awful delay, sometimes also failure.
++               * Doesn't matter anyway (only small delay). */
++              if (unlikely(!--count)) {
++                      printk("%s: timeout waiting for EEPROM read\n",
++                                                      adev->ndev->name);
++                      result = NOT_OK;
++                      goto fail;
++              }
++              cpu_relax();
++      }
++
++      *charbuf = read_reg8(adev, IO_ACX_EEPROM_DATA);
++      log(L_DEBUG, "EEPROM at 0x%04X = 0x%02X\n", addr, *charbuf);
++      result = OK;
++
++fail:
++      return result;
++}
++
++
++/***********************************************************************
++** We don't lock hw accesses here since we never r/w eeprom in IRQ
++** Note: this function sleeps only because of GFP_KERNEL alloc
++*/
++#ifdef UNUSED
++int
++acxmem_s_write_eeprom(acx_device_t *adev, u32 addr, u32 len, const u8 *charbuf)
++{
++      u8 *data_verify = NULL;
++      unsigned long flags;
++      int count, i;
++      int result = NOT_OK;
++      u16 gpio_orig;
++
++      printk("acx: WARNING! I would write to EEPROM now. "
++              "Since I really DON'T want to unless you know "
++              "what you're doing (THIS CODE WILL PROBABLY "
++              "NOT WORK YET!), I will abort that now. And "
++              "definitely make sure to make a "
++              "/proc/driver/acx_wlan0_eeprom backup copy first!!! "
++              "(the EEPROM content includes the PCI config header!! "
++              "If you kill important stuff, then you WILL "
++              "get in trouble and people DID get in trouble already)\n");
++      return OK;
++
++      FN_ENTER;
++
++      data_verify = kmalloc(len, GFP_KERNEL);
++      if (!data_verify) {
++              goto end;
++      }
++
++      /* first we need to enable the OE (EEPROM Output Enable) GPIO line
++       * to be able to write to the EEPROM.
++       * NOTE: an EEPROM writing success has been reported,
++       * but you probably have to modify GPIO_OUT, too,
++       * and you probably need to activate a different GPIO
++       * line instead! */
++      gpio_orig = read_reg16(adev, IO_ACX_GPIO_OE);
++      write_reg16(adev, IO_ACX_GPIO_OE, gpio_orig & ~1);
++      write_flush(adev);
++
++      /* ok, now start writing the data out */
++      for (i = 0; i < len; i++) {
++              write_reg32(adev, IO_ACX_EEPROM_CFG, 0);
++              write_reg32(adev, IO_ACX_EEPROM_ADDR, addr + i);
++              write_reg32(adev, IO_ACX_EEPROM_DATA, *(charbuf + i));
++              write_flush(adev);
++              write_reg32(adev, IO_ACX_EEPROM_CTL, 1);
++
++              count = 0xffff;
++              while (read_reg16(adev, IO_ACX_EEPROM_CTL)) {
++                      if (unlikely(!--count)) {
++                              printk("WARNING, DANGER!!! "
++                                      "Timeout waiting for EEPROM write\n");
++                              goto end;
++                      }
++                      cpu_relax();
++              }
++      }
++
++      /* disable EEPROM writing */
++      write_reg16(adev, IO_ACX_GPIO_OE, gpio_orig);
++      write_flush(adev);
++
++      /* now start a verification run */
++      for (i = 0; i < len; i++) {
++              write_reg32(adev, IO_ACX_EEPROM_CFG, 0);
++              write_reg32(adev, IO_ACX_EEPROM_ADDR, addr + i);
++              write_flush(adev);
++              write_reg32(adev, IO_ACX_EEPROM_CTL, 2);
++
++              count = 0xffff;
++              while (read_reg16(adev, IO_ACX_EEPROM_CTL)) {
++                      if (unlikely(!--count)) {
++                              printk("timeout waiting for EEPROM read\n");
++                              goto end;
++                      }
++                      cpu_relax();
++              }
++
++              data_verify[i] = read_reg16(adev, IO_ACX_EEPROM_DATA);
++      }
++
++      if (0 == memcmp(charbuf, data_verify, len))
++              result = OK; /* read data matches, success */
++
++end:
++      kfree(data_verify);
++      FN_EXIT1(result);
++      return result;
++}
++#endif /* UNUSED */
++
++
++/***********************************************************************
++** acxmem_s_read_phy_reg
++**
++** Messing with rx/tx disabling and enabling here
++** (write_reg32(adev, IO_ACX_ENABLE, 0b000000xx)) kills traffic
++*/
++int
++acxmem_s_read_phy_reg(acx_device_t *adev, u32 reg, u8 *charbuf)
++{
++      int result = NOT_OK;
++      int count;
++
++      FN_ENTER;
++
++      write_reg32(adev, IO_ACX_PHY_ADDR, reg);
++      write_flush(adev);
++      write_reg32(adev, IO_ACX_PHY_CTL, 2);
++
++      count = 0xffff;
++      while (read_reg32(adev, IO_ACX_PHY_CTL)) {
++              /* scheduling away instead of CPU burning loop
++               * doesn't seem to work here at all:
++               * awful delay, sometimes also failure.
++               * Doesn't matter anyway (only small delay). */
++              if (unlikely(!--count)) {
++                      printk("%s: timeout waiting for phy read\n",
++                                                      adev->ndev->name);
++                      *charbuf = 0;
++                      goto fail;
++              }
++              cpu_relax();
++      }
++
++      log(L_DEBUG, "count was %u\n", count);
++      *charbuf = read_reg8(adev, IO_ACX_PHY_DATA);
++
++      log(L_DEBUG, "radio PHY at 0x%04X = 0x%02X\n", *charbuf, reg);
++      result = OK;
++      goto fail; /* silence compiler warning */
++fail:
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/***********************************************************************
++*/
++int
++acxmem_s_write_phy_reg(acx_device_t *adev, u32 reg, u8 value)
++{
++        int count;
++      FN_ENTER;
++
++      /* mprusko said that 32bit accesses result in distorted sensitivity
++       * on his card. Unconfirmed, looks like it's not true (most likely since we
++       * now properly flush writes). */
++      write_reg32(adev, IO_ACX_PHY_DATA, value);
++      write_reg32(adev, IO_ACX_PHY_ADDR, reg);
++      write_flush(adev);
++      write_reg32(adev, IO_ACX_PHY_CTL, 1);
++      write_flush(adev);
++
++      count = 0xffff;
++      while (read_reg32(adev, IO_ACX_PHY_CTL)) {
++              /* scheduling away instead of CPU burning loop
++               * doesn't seem to work here at all:
++               * awful delay, sometimes also failure.
++               * Doesn't matter anyway (only small delay). */
++              if (unlikely(!--count)) {
++                      printk("%s: timeout waiting for phy read\n",
++                                                      adev->ndev->name);
++                      goto fail;
++              }
++              cpu_relax();
++      }
++
++      log(L_DEBUG, "radio PHY write 0x%02X at 0x%04X\n", value, reg);
++ fail:
++      FN_EXIT1(OK);
++      return OK;
++}
++
++
++#define NO_AUTO_INCREMENT     1
++
++/***********************************************************************
++** acxmem_s_write_fw
++**
++** Write the firmware image into the card.
++**
++** Arguments:
++**    adev            wlan device structure
++**    fw_image        firmware image.
++**
++** Returns:
++**    1       firmware image corrupted
++**    0       success
++*/
++static int
++acxmem_s_write_fw(acx_device_t *adev, const firmware_image_t *fw_image, u32 offset)
++{
++      int len, size, checkMismatch = -1;
++      u32 sum, v32, tmp, id;
++      /* we skip the first four bytes which contain the control sum */
++      const u8 *p = (u8*)fw_image + 4;
++
++      /* start the image checksum by adding the image size value */
++      sum = p[0]+p[1]+p[2]+p[3];
++      p += 4;
++
++#ifdef NOPE
++#if NO_AUTO_INCREMENT
++      write_reg32(adev, IO_ACX_SLV_MEM_CTL, 0); /* use basic mode */
++#else
++      write_reg32(adev, IO_ACX_SLV_MEM_CTL, 1); /* use autoincrement mode */
++      write_reg32(adev, IO_ACX_SLV_MEM_ADDR, offset); /* configure start address */
++      write_flush(adev);
++#endif
++#endif
++      len = 0;
++      size = le32_to_cpu(fw_image->size) & (~3);
++
++      while (likely(len < size)) {
++              v32 = be32_to_cpu(*(u32*)p);
++              sum += p[0]+p[1]+p[2]+p[3];
++              p += 4;
++              len += 4;
++
++#ifdef NOPE
++#if NO_AUTO_INCREMENT 
++              write_reg32(adev, IO_ACX_SLV_MEM_ADDR, offset + len - 4);
++              write_flush(adev);
++#endif
++              write_reg32(adev, IO_ACX_SLV_MEM_DATA, v32);
++              write_flush(adev);
++#endif
++              write_slavemem32 (adev, offset + len - 4, v32);
++
++              id = read_id_register (adev);
++              
++              /*
++               * check the data written
++               */
++              tmp = read_slavemem32 (adev, offset + len - 4);
++              if (checkMismatch && (tmp != v32)) {
++                printk ("first data mismatch at 0x%08x good 0x%08x bad 0x%08x id 0x%08x\n",
++                        offset + len - 4, v32, tmp, id);
++                checkMismatch = 0;
++              }
++      }
++      log(L_DEBUG, "firmware written, size:%d sum1:%x sum2:%x\n",
++                      size, sum, le32_to_cpu(fw_image->chksum));
++
++      /* compare our checksum with the stored image checksum */
++      return (sum != le32_to_cpu(fw_image->chksum));
++}
++
++
++/***********************************************************************
++** acxmem_s_validate_fw
++**
++** Compare the firmware image given with
++** the firmware image written into the card.
++**
++** Arguments:
++**    adev            wlan device structure
++**    fw_image        firmware image.
++**
++** Returns:
++**    NOT_OK  firmware image corrupted or not correctly written
++**    OK      success
++*/
++static int
++acxmem_s_validate_fw(acx_device_t *adev, const firmware_image_t *fw_image,
++                              u32 offset)
++{
++      u32 sum, v32, w32;
++      int len, size;
++      int result = OK;
++      /* we skip the first four bytes which contain the control sum */
++      const u8 *p = (u8*)fw_image + 4;
++
++      /* start the image checksum by adding the image size value */
++      sum = p[0]+p[1]+p[2]+p[3];
++      p += 4;
++
++      write_reg32(adev, IO_ACX_SLV_END_CTL, 0);
++
++#if NO_AUTO_INCREMENT
++      write_reg32(adev, IO_ACX_SLV_MEM_CTL, 0); /* use basic mode */
++#else
++      write_reg32(adev, IO_ACX_SLV_MEM_CTL, 1); /* use autoincrement mode */
++      write_reg32(adev, IO_ACX_SLV_MEM_ADDR, offset); /* configure start address */
++#endif
++
++      len = 0;
++      size = le32_to_cpu(fw_image->size) & (~3);
++
++      while (likely(len < size)) {
++              v32 = be32_to_cpu(*(u32*)p);
++              p += 4;
++              len += 4;
++
++#ifdef NOPE
++#if NO_AUTO_INCREMENT
++              write_reg32(adev, IO_ACX_SLV_MEM_ADDR, offset + len - 4);
++#endif
++              udelay(10);
++              w32 = read_reg32(adev, IO_ACX_SLV_MEM_DATA);
++#endif
++              w32 = read_slavemem32 (adev, offset + len - 4);
++
++              if (unlikely(w32 != v32)) {
++                      printk("acx: FATAL: firmware upload: "
++                      "data parts at offset %d don't match\n(0x%08X vs. 0x%08X)!\n"
++                      "I/O timing issues or defective memory, with DWL-xx0+? "
++                      "ACX_IO_WIDTH=16 may help. Please report\n",
++                              len, v32, w32);
++                      result = NOT_OK;
++                      break;
++              }
++
++              sum += (u8)w32 + (u8)(w32>>8) + (u8)(w32>>16) + (u8)(w32>>24);
++      }
++
++      /* sum control verification */
++      if (result != NOT_OK) {
++              if (sum != le32_to_cpu(fw_image->chksum)) {
++                      printk("acx: FATAL: firmware upload: "
++                              "checksums don't match!\n");
++                      result = NOT_OK;
++              }
++      }
++
++      return result;
++}
++
++
++/***********************************************************************
++** acxmem_s_upload_fw
++**
++** Called from acx_reset_dev
++*/
++static int
++acxmem_s_upload_fw(acx_device_t *adev)
++{
++      firmware_image_t *fw_image = NULL;
++      int res = NOT_OK;
++      int try;
++      u32 file_size;
++      char *filename = "WLANGEN.BIN";
++#ifdef PATCH_AROUND_BAD_SPOTS
++      u32 offset;
++      int i;
++        /*
++         * arm-linux-objdump -d patch.bin, or
++         * od -Ax -t x4 patch.bin after finding the bounds
++         * of the .text section with arm-linux-objdump -s patch.bin
++         */
++        u32 patch[] = {
++        0xe584c030, 0xe59fc008,
++        0xe92d1000, 0xe59fc004, 0xe8bd8000, 0x0000080c,
++        0x0000aa68, 0x605a2200, 0x2c0a689c, 0x2414d80a,
++        0x2f00689f, 0x1c27d007, 0x06241e7c, 0x2f000e24,
++        0xe000d1f6, 0x602e6018, 0x23036468, 0x480203db,
++        0x60ca6003, 0xbdf0750a, 0xffff0808
++      };
++#endif
++
++      FN_ENTER;
++      /* No combined image; tell common we need the radio firmware, too */
++      adev->need_radio_fw = 1;
++
++      fw_image = acx_s_read_fw(adev->dev, filename, &file_size);
++      if (!fw_image) {
++        FN_EXIT1(NOT_OK);
++        return NOT_OK;
++      }
++
++      for (try = 1; try <= 5; try++) {
++              res = acxmem_s_write_fw(adev, fw_image, 0);
++              log(L_DEBUG|L_INIT, "acx_write_fw (main): %d\n", res);
++              if (OK == res) {
++                      res = acxmem_s_validate_fw(adev, fw_image, 0);
++                      log(L_DEBUG|L_INIT, "acx_validate_fw "
++                                      "(main): %d\n", res);
++              }
++
++              if (OK == res) {
++                      SET_BIT(adev->dev_state_mask, ACX_STATE_FW_LOADED);
++                      break;
++              }
++              printk("acx: firmware upload attempt #%d FAILED, "
++                      "retrying...\n", try);
++              acx_s_msleep(1000); /* better wait for a while... */
++      }
++
++#ifdef PATCH_AROUND_BAD_SPOTS
++      /*
++       * Only want to do this if the firmware is exactly what we expect for an
++       * iPaq 4700; otherwise, bad things would ensue.
++       */
++      if ((HX4700_FIRMWARE_CHECKSUM == fw_image->chksum) ||
++          (HX4700_ALTERNATE_FIRMWARE_CHECKSUM == fw_image->chksum)) {
++        /*
++         * Put the patch after the main firmware image.  0x950c contains
++         * the ACX's idea of the end of the firmware.  Use that location to
++         * load ours (which depends on that location being 0xab58) then
++         * update that location to point to after ours.
++         */
++
++        offset = read_slavemem32 (adev, 0x950c);
++        
++        log (L_DEBUG, "acx: patching in at 0x%04x\n", offset);
++
++        for (i = 0; i < sizeof(patch) / sizeof(patch[0]); i++) {
++          write_slavemem32 (adev, offset, patch[i]);
++          offset += sizeof(u32);
++        }
++
++        /*
++         * Patch the instruction at 0x0804 to branch to our ARM patch at 0xab58
++         */
++        write_slavemem32 (adev, 0x0804, 0xea000000 + (0xab58-0x0804-8)/4);
++
++        /*
++         * Patch the instructions at 0x1f40 to branch to our Thumb patch at 0xab74
++         *
++         * 4a00 ldr r2, [pc, #0]
++         * 4710 bx  r2
++         * .data 0xab74+1
++         */
++        write_slavemem32 (adev, 0x1f40, 0x47104a00);
++        write_slavemem32 (adev, 0x1f44, 0x0000ab74+1);
++
++        /*
++         * Bump the end of the firmware up to beyond our patch.
++         */
++        write_slavemem32 (adev, 0x950c, offset);
++      
++      }
++#endif
++
++      vfree(fw_image);
++
++      FN_EXIT1(res);
++      return res;
++}
++
++
++/***********************************************************************
++** acxmem_s_upload_radio
++**
++** Uploads the appropriate radio module firmware into the card.
++*/
++int
++acxmem_s_upload_radio(acx_device_t *adev)
++{
++      acx_ie_memmap_t mm;
++      firmware_image_t *radio_image;
++      acx_cmd_radioinit_t radioinit;
++      int res = NOT_OK;
++      int try;
++      u32 offset;
++      u32 size;
++      char filename[sizeof("RADIONN.BIN")];
++
++      if (!adev->need_radio_fw) return OK;
++
++      FN_ENTER;
++
++      acx_s_interrogate(adev, &mm, ACX1xx_IE_MEMORY_MAP);
++      offset = le32_to_cpu(mm.CodeEnd);
++
++      snprintf(filename, sizeof(filename), "RADIO%02x.BIN",
++              adev->radio_type);
++      radio_image = acx_s_read_fw(adev->dev, filename, &size);
++      if (!radio_image) {
++              printk("acx: can't load radio module '%s'\n", filename);
++              goto fail;
++      }
++
++      acx_s_issue_cmd(adev, ACX1xx_CMD_SLEEP, NULL, 0);
++
++      for (try = 1; try <= 5; try++) {
++              res = acxmem_s_write_fw(adev, radio_image, offset);
++              log(L_DEBUG|L_INIT, "acx_write_fw (radio): %d\n", res);
++              if (OK == res) {
++                      res = acxmem_s_validate_fw(adev, radio_image, offset);
++                      log(L_DEBUG|L_INIT, "acx_validate_fw (radio): %d\n", res);
++              }
++
++              if (OK == res)
++                      break;
++              printk("acx: radio firmware upload attempt #%d FAILED, "
++                      "retrying...\n", try);
++              acx_s_msleep(1000); /* better wait for a while... */
++      }
++
++      acx_s_issue_cmd(adev, ACX1xx_CMD_WAKE, NULL, 0);
++      radioinit.offset = cpu_to_le32(offset);
++
++      /* no endian conversion needed, remains in card CPU area: */
++      radioinit.len = radio_image->size;
++
++      vfree(radio_image);
++
++      if (OK != res)
++              goto fail;
++
++      /* will take a moment so let's have a big timeout */
++      acx_s_issue_cmd_timeo(adev, ACX1xx_CMD_RADIOINIT,
++              &radioinit, sizeof(radioinit), CMD_TIMEOUT_MS(1000));
++
++      res = acx_s_interrogate(adev, &mm, ACX1xx_IE_MEMORY_MAP);
++
++fail:
++      FN_EXIT1(res);
++      return res;
++}
++
++/***********************************************************************
++** acxmem_l_reset_mac
++**
++** MAC will be reset
++** Call context: reset_dev
++*/
++static void
++acxmem_l_reset_mac(acx_device_t *adev)
++{
++  int count;
++      FN_ENTER;
++
++      /* halt eCPU */
++      set_regbits (adev, IO_ACX_ECPU_CTRL, 0x1);
++
++      /* now do soft reset of eCPU, set bit */
++      set_regbits (adev, IO_ACX_SOFT_RESET, 0x1);
++      log(L_DEBUG, "%s: enable soft reset...\n", __func__);
++
++      /* Windows driver sleeps here for a while with this sequence */
++      for (count = 0; count < 200; count++) {
++        udelay (50);
++      }
++
++      /* now clear bit again: deassert eCPU reset */
++      log(L_DEBUG, "%s: disable soft reset and go to init mode...\n", __func__);
++      clear_regbits (adev, IO_ACX_SOFT_RESET, 0x1);
++
++      /* now start a burst read from initial EEPROM */
++      set_regbits (adev, IO_ACX_EE_START, 0x1);
++
++      /*
++       * Windows driver sleeps here for a while with this sequence
++       */
++      for (count = 0; count < 200; count++) {
++        udelay (50);
++      }
++
++      /* Windows driver writes 0x10000 to register 0x808 here */
++      
++      write_reg32 (adev, 0x808, 0x10000);
++
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++** acxmem_s_verify_init
++*/
++static int
++acxmem_s_verify_init(acx_device_t *adev)
++{
++      int result = NOT_OK;
++      unsigned long timeout;
++
++      FN_ENTER;
++
++      timeout = jiffies + 2*HZ;
++      for (;;) {
++              u32 irqstat = read_reg32(adev, IO_ACX_IRQ_STATUS_NON_DES);
++              if ((irqstat != 0xFFFFFFFF) && (irqstat & HOST_INT_FCS_THRESHOLD)) {
++                      result = OK;
++                      write_reg32(adev, IO_ACX_IRQ_ACK, HOST_INT_FCS_THRESHOLD);
++                      break;
++              }
++              if (time_after(jiffies, timeout))
++                      break;
++              /* Init may take up to ~0.5 sec total */
++              acx_s_msleep(50);
++      }
++
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/***********************************************************************
++** A few low-level helpers
++**
++** Note: these functions are not protected by lock
++** and thus are never allowed to be called from IRQ.
++** Also they must not race with fw upload which uses same hw regs
++*/
++
++/***********************************************************************
++** acxmem_write_cmd_type_status
++*/
++
++static inline void
++acxmem_write_cmd_type_status(acx_device_t *adev, u16 type, u16 status)
++{
++  write_slavemem32 (adev, (u32) adev->cmd_area, type | (status << 16));
++  write_flush(adev);
++}
++
++
++/***********************************************************************
++** acxmem_read_cmd_type_status
++*/
++static u32
++acxmem_read_cmd_type_status(acx_device_t *adev)
++{
++      u32 cmd_type, cmd_status;
++
++      cmd_type = read_slavemem32 (adev, (u32) adev->cmd_area);
++
++      cmd_status = (cmd_type >> 16);
++      cmd_type = (u16)cmd_type;
++
++      log(L_CTL, "cmd_type:%04X cmd_status:%04X [%s]\n",
++              cmd_type, cmd_status,
++              acx_cmd_status_str(cmd_status));
++
++      return cmd_status;
++}
++
++
++/***********************************************************************
++** acxmem_s_reset_dev
++**
++** Arguments:
++**    netdevice that contains the adev variable
++** Returns:
++**    NOT_OK on fail
++**    OK on success
++** Side effects:
++**    device is hard reset
++** Call context:
++**    acxmem_e_probe
++** Comment:
++**    This resets the device using low level hardware calls
++**    as well as uploads and verifies the firmware to the card
++*/
++
++static inline void
++init_mboxes(acx_device_t *adev)
++{
++      u32 cmd_offs, info_offs;
++
++      cmd_offs = read_reg32(adev, IO_ACX_CMD_MAILBOX_OFFS);
++      info_offs = read_reg32(adev, IO_ACX_INFO_MAILBOX_OFFS);
++      adev->cmd_area = (u8*) cmd_offs;
++      adev->info_area = (u8*) info_offs;
++      /*
++      log(L_DEBUG, "iobase2=%p\n"
++      */
++      log( L_DEBUG, "cmd_mbox_offset=%X cmd_area=%p\n"
++              "info_mbox_offset=%X info_area=%p\n",
++              cmd_offs, adev->cmd_area,
++              info_offs, adev->info_area);
++}
++
++
++static inline void
++read_eeprom_area(acx_device_t *adev)
++{
++#if ACX_DEBUG > 1
++      int offs;
++      u8 tmp;
++
++      for (offs = 0x8c; offs < 0xb9; offs++)
++              acxmem_read_eeprom_byte(adev, offs, &tmp);
++#endif
++}
++
++static int
++acxmem_s_reset_dev(acx_device_t *adev)
++{
++      const char* msg = "";
++      unsigned long flags;
++      int result = NOT_OK;
++      u16 hardware_info;
++      u16 ecpu_ctrl;
++      int count;
++      u32 tmp;
++
++      FN_ENTER;
++      /*
++      write_reg32 (adev, IO_ACX_SLV_MEM_CP, 0);
++      */
++      /* reset the device to make sure the eCPU is stopped
++       * to upload the firmware correctly */
++
++      acx_lock(adev, flags);
++
++      /* Windows driver does some funny things here */
++      /*
++       * clear bit 0x200 in register 0x2A0
++       */
++      clear_regbits (adev, 0x2A0, 0x200);
++
++      /*
++       * Set bit 0x200 in ACX_GPIO_OUT
++       */
++      set_regbits (adev, IO_ACX_GPIO_OUT, 0x200);
++
++      /*
++       * read register 0x900 until its value is 0x8400104C, sleeping
++       * in between reads if it's not immediate
++       */
++      tmp = read_reg32 (adev, REG_ACX_VENDOR_ID);
++      count = 500;
++      while (count-- && (tmp != ACX_VENDOR_ID)) {
++        mdelay (10);
++        tmp = read_reg32 (adev, REG_ACX_VENDOR_ID);
++      }
++
++      /* end what Windows driver does */
++
++      acxmem_l_reset_mac(adev);
++
++      ecpu_ctrl = read_reg32(adev, IO_ACX_ECPU_CTRL) & 1;
++      if (!ecpu_ctrl) {
++              msg = "eCPU is already running. ";
++              goto end_unlock;
++      }
++
++#ifdef WE_DONT_NEED_THAT_DO_WE
++      if (read_reg16(adev, IO_ACX_SOR_CFG) & 2) {
++              /* eCPU most likely means "embedded CPU" */
++              msg = "eCPU did not start after boot from flash. ";
++              goto end_unlock;
++      }
++
++      /* check sense on reset flags */
++      if (read_reg16(adev, IO_ACX_SOR_CFG) & 0x10) {
++              printk("%s: eCPU did not start after boot (SOR), "
++                      "is this fatal?\n", adev->ndev->name);
++      }
++#endif
++      /* scan, if any, is stopped now, setting corresponding IRQ bit */
++      adev->irq_status |= HOST_INT_SCAN_COMPLETE;
++
++      acx_unlock(adev, flags);
++      
++      /* need to know radio type before fw load */
++      /* Need to wait for arrival of this information in a loop,
++       * most probably since eCPU runs some init code from EEPROM
++       * (started burst read in reset_mac()) which also
++       * sets the radio type ID */
++
++      count = 0xffff;
++      do {
++              hardware_info = read_reg16(adev, IO_ACX_EEPROM_INFORMATION);
++              if (!--count) {
++                      msg = "eCPU didn't indicate radio type";
++                      goto end_fail;
++              }
++              cpu_relax();
++      } while (!(hardware_info & 0xff00)); /* radio type still zero? */
++      printk("ACX radio type 0x%02x\n", (hardware_info >> 8) & 0xff);
++      /* printk("DEBUG: count %d\n", count); */
++      adev->form_factor = hardware_info & 0xff;
++      adev->radio_type = hardware_info >> 8;
++
++      /* load the firmware */
++      if (OK != acxmem_s_upload_fw(adev))
++              goto end_fail;
++
++      /* acx_s_msleep(10);    this one really shouldn't be required */
++
++      /* now start eCPU by clearing bit */
++      clear_regbits (adev, IO_ACX_ECPU_CTRL, 0x1);
++      log(L_DEBUG, "booted eCPU up and waiting for completion...\n");
++
++      /* Windows driver clears bit 0x200 in register 0x2A0 here */
++      clear_regbits (adev, 0x2A0, 0x200);
++
++      /* Windows driver sets bit 0x200 in ACX_GPIO_OUT here */
++      set_regbits (adev, IO_ACX_GPIO_OUT, 0x200);
++      /* wait for eCPU bootup */
++      if (OK != acxmem_s_verify_init(adev)) {
++              msg = "timeout waiting for eCPU. ";
++              goto end_fail;
++      }
++      log(L_DEBUG, "eCPU has woken up, card is ready to be configured\n");
++      init_mboxes(adev);
++      acxmem_write_cmd_type_status(adev, ACX1xx_CMD_RESET, 0);
++
++      /* test that EEPROM is readable */
++      read_eeprom_area(adev);
++
++      result = OK;
++      goto end;
++
++/* Finish error message. Indicate which function failed */
++end_unlock:
++      acx_unlock(adev, flags);
++end_fail:
++      printk("acx: %sreset_dev() FAILED\n", msg);
++end:
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/***********************************************************************
++** acxmem_s_issue_cmd_timeo
++**
++** Sends command to fw, extract result
++**
++** NB: we do _not_ take lock inside, so be sure to not touch anything
++** which may interfere with IRQ handler operation
++**
++** TODO: busy wait is a bit silly, so:
++** 1) stop doing many iters - go to sleep after first
++** 2) go to waitqueue based approach: wait, not poll!
++*/
++#undef FUNC
++#define FUNC "issue_cmd"
++
++#if !ACX_DEBUG
++int
++acxmem_s_issue_cmd_timeo(
++      acx_device_t *adev,
++      unsigned int cmd,
++      void *buffer,
++      unsigned buflen,
++      unsigned cmd_timeout)
++{
++#else
++int
++acxmem_s_issue_cmd_timeo_debug(
++      acx_device_t *adev,
++      unsigned cmd,
++      void *buffer,
++      unsigned buflen,
++      unsigned cmd_timeout,
++      const char* cmdstr)
++{
++      unsigned long start = jiffies;
++#endif
++      const char *devname;
++      unsigned counter;
++      u16 irqtype;
++      int i, j;
++      u8 *p;
++      u16 cmd_status;
++      unsigned long timeout;
++
++      FN_ENTER;
++
++      devname = adev->ndev->name;
++      if (!devname || !devname[0] || devname[4]=='%')
++              devname = "acx";
++
++      log(L_CTL, FUNC"(cmd:%s,buflen:%u,timeout:%ums,type:0x%04X)\n",
++              cmdstr, buflen, cmd_timeout,
++              buffer ? le16_to_cpu(((acx_ie_generic_t *)buffer)->type) : -1);
++
++      if (!(adev->dev_state_mask & ACX_STATE_FW_LOADED)) {
++              printk("%s: "FUNC"(): firmware is not loaded yet, "
++                      "cannot execute commands!\n", devname);
++              goto bad;
++      }
++
++      if ((acx_debug & L_DEBUG) && (cmd != ACX1xx_CMD_INTERROGATE)) {
++              printk("input buffer (len=%u):\n", buflen);
++              acx_dump_bytes(buffer, buflen);
++      }
++
++      /* wait for firmware to become idle for our command submission */
++      timeout = HZ/5;
++      counter = (timeout * 1000 / HZ) - 1; /* in ms */
++      timeout += jiffies;
++      do {
++              cmd_status = acxmem_read_cmd_type_status(adev);
++              /* Test for IDLE state */
++              if (!cmd_status)
++                      break;
++              if (counter % 8 == 0) {
++                      if (time_after(jiffies, timeout)) {
++                              counter = 0;
++                              break;
++                      }
++                      /* we waited 8 iterations, no luck. Sleep 8 ms */
++                      acx_s_msleep(8);
++              }
++      } while (likely(--counter));
++
++      if (!counter) {
++              /* the card doesn't get idle, we're in trouble */
++              printk("%s: "FUNC"(): cmd_status is not IDLE: 0x%04X!=0\n",
++                      devname, cmd_status);
++#if DUMP_IF_SLOW > 0
++              dump_acxmem (adev, 0, 0x10000);
++              panic ("not idle");
++#endif
++              goto bad;
++      } else if (counter < 190) { /* if waited >10ms... */
++              log(L_CTL|L_DEBUG, FUNC"(): waited for IDLE %dms. "
++                      "Please report\n", 199 - counter);
++      }
++
++      /* now write the parameters of the command if needed */
++      if (buffer && buflen) {
++              /* if it's an INTERROGATE command, just pass the length
++               * of parameters to read, as data */
++#if CMD_DISCOVERY
++              if (cmd == ACX1xx_CMD_INTERROGATE)
++                      memset_io(adev->cmd_area + 4, 0xAA, buflen);
++#endif
++              /*
++               * slave memory version
++               */
++              copy_to_slavemem (adev, (u32) (adev->cmd_area + 4), buffer, 
++                             (cmd == ACX1xx_CMD_INTERROGATE) ? 4 : buflen);
++      }
++      /* now write the actual command type */
++      acxmem_write_cmd_type_status(adev, cmd, 0);
++
++      /* clear CMD_COMPLETE bit. can be set only by IRQ handler: */
++      adev->irq_status &= ~HOST_INT_CMD_COMPLETE;
++
++      /* execute command */
++      write_reg16(adev, IO_ACX_INT_TRIG, INT_TRIG_CMD);
++      write_flush(adev);
++
++      /* wait for firmware to process command */
++
++      /* Ensure nonzero and not too large timeout.
++      ** Also converts e.g. 100->99, 200->199
++      ** which is nice but not essential */
++      cmd_timeout = (cmd_timeout-1) | 1;
++      if (unlikely(cmd_timeout > 1199))
++              cmd_timeout = 1199;
++
++      /* we schedule away sometimes (timeout can be large) */
++      counter = cmd_timeout;
++      timeout = jiffies + cmd_timeout * HZ / 1000;
++      do {
++              if (!adev->irqs_active) { /* IRQ disabled: poll */
++                      irqtype = read_reg16(adev, IO_ACX_IRQ_STATUS_NON_DES);
++                      if (irqtype & HOST_INT_CMD_COMPLETE) {
++                              write_reg16(adev, IO_ACX_IRQ_ACK,
++                                              HOST_INT_CMD_COMPLETE);
++                              break;
++                      }
++              } else { /* Wait when IRQ will set the bit */
++                      irqtype = adev->irq_status;
++                      if (irqtype & HOST_INT_CMD_COMPLETE)
++                              break;
++              }
++
++              if (counter % 8 == 0) {
++                      if (time_after(jiffies, timeout)) {
++                              counter = 0;
++                              break;
++                      }
++                      /* we waited 8 iterations, no luck. Sleep 8 ms */
++                      acx_s_msleep(8);
++              }
++      } while (likely(--counter));
++
++      /* save state for debugging */
++      cmd_status = acxmem_read_cmd_type_status(adev);
++
++      /* put the card in IDLE state */
++      acxmem_write_cmd_type_status(adev, ACX1xx_CMD_RESET, 0);
++
++      if (!counter) { /* timed out! */
++              printk("%s: "FUNC"(): timed out %s for CMD_COMPLETE. "
++                      "irq bits:0x%04X irq_status:0x%04X timeout:%dms "
++                      "cmd_status:%d (%s)\n",
++                      devname, (adev->irqs_active) ? "waiting" : "polling",
++                      irqtype, adev->irq_status, cmd_timeout,
++                      cmd_status, acx_cmd_status_str(cmd_status));
++              printk("%s: "FUNC"(): device irq status 0x%04x\n",
++                     devname, read_reg16(adev, IO_ACX_IRQ_STATUS_NON_DES));
++              printk("%s: "FUNC"(): IO_ACX_IRQ_MASK 0x%04x IO_ACX_FEMR 0x%04x\n",
++                     devname,
++                     read_reg16 (adev, IO_ACX_IRQ_MASK),
++                     read_reg16 (adev, IO_ACX_FEMR));
++              if (read_reg16 (adev, IO_ACX_IRQ_MASK) == 0xffff) {
++                      printk ("acxmem: firmware probably hosed - reloading\n");
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11)
++                      {
++                              pm_message_t state;
++                              /* acxmem_e_suspend (resume_pdev, state); */
++                              acxmem_e_suspend (adev->ndev , state);
++                      }
++#else
++                      acxmem_e_suspend (adev, 0);
++#endif
++                      {
++                              resume_ndev = adev->ndev;
++                              fw_resumer (NULL);
++                      }
++              }
++
++              goto bad;
++      } else if (cmd_timeout - counter > 30) { /* if waited >30ms... */
++              log(L_CTL|L_DEBUG, FUNC"(): %s for CMD_COMPLETE %dms. "
++                      "count:%d. Please report\n",
++                      (adev->irqs_active) ? "waited" : "polled",
++                      cmd_timeout - counter, counter);
++      }
++
++      if (1 != cmd_status) { /* it is not a 'Success' */
++              printk("%s: "FUNC"(): cmd_status is not SUCCESS: %d (%s). "
++                      "Took %dms of %d\n",
++                      devname, cmd_status, acx_cmd_status_str(cmd_status),
++                      cmd_timeout - counter, cmd_timeout);
++              /* zero out result buffer
++               * WARNING: this will trash stack in case of illegally large input
++               * length! */
++              if (buflen > 388) {
++                /*
++                 * 388 is maximum command length
++                 */
++                printk ("invalid length 0x%08x\n", buflen);
++                buflen = 388;
++              }
++              p = (u8 *) buffer;
++              for (i = 0; i < buflen; i+= 16) {
++                printk ("%04x:", i);
++                for (j = 0; (j < 16) && (i+j < buflen); j++) {
++                  printk (" %02x", *p++);
++                }
++                printk ("\n");
++              }
++              if (buffer && buflen)
++                      memset(buffer, 0, buflen);
++              goto bad;
++      }
++
++      /* read in result parameters if needed */
++      if (buffer && buflen && (cmd == ACX1xx_CMD_INTERROGATE)) {
++              copy_from_slavemem (adev, buffer, (u32) (adev->cmd_area + 4), buflen);
++              if (acx_debug & L_DEBUG) {
++                      printk("output buffer (len=%u): ", buflen);
++                      acx_dump_bytes(buffer, buflen);
++              }
++      }
++
++/* ok: */
++      log(L_CTL, FUNC"(%s): took %ld jiffies to complete\n",
++                       cmdstr, jiffies - start);
++      FN_EXIT1(OK);
++      return OK;
++
++bad:
++      /* Give enough info so that callers can avoid
++      ** printing their own diagnostic messages */
++#if ACX_DEBUG
++      printk("%s: "FUNC"(cmd:%s) FAILED\n", devname, cmdstr);
++#else
++      printk("%s: "FUNC"(cmd:0x%04X) FAILED\n", devname, cmd);
++#endif
++      dump_stack();
++      FN_EXIT1(NOT_OK);
++      return NOT_OK;
++}
++
++
++/***********************************************************************
++*/
++#if defined(NONESSENTIAL_FEATURES)
++typedef struct device_id {
++      unsigned char id[6];
++      char *descr;
++      char *type;
++} device_id_t;
++
++static const device_id_t
++device_ids[] =
++{
++      {
++              {'G', 'l', 'o', 'b', 'a', 'l'},
++              NULL,
++              NULL,
++      },
++      {
++              {0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
++              "uninitialized",
++              "SpeedStream SS1021 or Gigafast WF721-AEX"
++      },
++      {
++              {0x80, 0x81, 0x82, 0x83, 0x84, 0x85},
++              "non-standard",
++              "DrayTek Vigor 520"
++      },
++      {
++              {'?', '?', '?', '?', '?', '?'},
++              "non-standard",
++              "Level One WPC-0200"
++      },
++      {
++              {0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
++              "empty",
++              "DWL-650+ variant"
++      }
++};
++
++static void
++acx_show_card_eeprom_id(acx_device_t *adev)
++{
++      unsigned char buffer[CARD_EEPROM_ID_SIZE];
++      int i;
++
++      memset(&buffer, 0, CARD_EEPROM_ID_SIZE);
++      /* use direct EEPROM access */
++      for (i = 0; i < CARD_EEPROM_ID_SIZE; i++) {
++              if (OK != acxmem_read_eeprom_byte(adev,
++                                       ACX100_EEPROM_ID_OFFSET + i,
++                                       &buffer[i])) {
++                      printk("acx: reading EEPROM FAILED\n");
++                      break;
++              }
++      }
++
++      for (i = 0; i < VEC_SIZE(device_ids); i++) {
++              if (!memcmp(&buffer, device_ids[i].id, CARD_EEPROM_ID_SIZE)) {
++                      if (device_ids[i].descr) {
++                              printk("acx: EEPROM card ID string check "
++                                      "found %s card ID: is this %s?\n",
++                                      device_ids[i].descr, device_ids[i].type);
++                      }
++                      break;
++              }
++      }
++      if (i == VEC_SIZE(device_ids)) {
++              printk("acx: EEPROM card ID string check found "
++                      "unknown card: expected 'Global', got '%.*s\'. "
++                      "Please report\n", CARD_EEPROM_ID_SIZE, buffer);
++      }
++}
++#endif /* NONESSENTIAL_FEATURES */
++
++/***********************************************************************
++** acxmem_free_desc_queues
++**
++** Releases the queues that have been allocated, the
++** others have been initialised to NULL so this
++** function can be used if only part of the queues were allocated.
++*/
++
++void
++acxmem_free_desc_queues(acx_device_t *adev)
++{
++#define ACX_FREE_QUEUE(size, ptr, phyaddr) \
++        if (ptr) { \
++                kfree(ptr); \
++                ptr = NULL; \
++                size = 0; \
++        }
++
++      FN_ENTER;
++
++      ACX_FREE_QUEUE(adev->txhostdesc_area_size, adev->txhostdesc_start, adev->txhostdesc_startphy);
++      ACX_FREE_QUEUE(adev->txbuf_area_size, adev->txbuf_start, adev->txbuf_startphy);
++
++      adev->txdesc_start = NULL;
++
++      ACX_FREE_QUEUE(adev->rxhostdesc_area_size, adev->rxhostdesc_start, adev->rxhostdesc_startphy);
++      ACX_FREE_QUEUE(adev->rxbuf_area_size, adev->rxbuf_start, adev->rxbuf_startphy);
++
++      adev->rxdesc_start = NULL;
++
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++** acxmem_s_delete_dma_regions
++*/
++static void
++acxmem_s_delete_dma_regions(acx_device_t *adev)
++{
++      unsigned long flags;
++
++      FN_ENTER;
++      /* disable radio Tx/Rx. Shouldn't we use the firmware commands
++       * here instead? Or are we that much down the road that it's no
++       * longer possible here? */
++      /*
++       * slave memory interface really doesn't like this.
++       */
++      /*
++      write_reg16(adev, IO_ACX_ENABLE, 0);
++      */
++
++      acx_s_msleep(100);
++
++      acx_lock(adev, flags);
++      acxmem_free_desc_queues(adev);
++      acx_unlock(adev, flags);
++
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++** acxmem_e_probe
++**
++** Probe routine called when a PCI device w/ matching ID is found.
++** Here's the sequence:
++**   - Allocate the PCI resources.
++**   - Read the PCMCIA attribute memory to make sure we have a WLAN card
++**   - Reset the MAC
++**   - Initialize the dev and wlan data
++**   - Initialize the MAC
++**
++** pdev       - ptr to pci device structure containing info about pci configuration
++** id - ptr to the device id entry that matched this device
++*/
++static const u16
++IO_ACX100[] =
++{
++      0x0000, /* IO_ACX_SOFT_RESET */
++
++      0x0014, /* IO_ACX_SLV_MEM_ADDR */
++      0x0018, /* IO_ACX_SLV_MEM_DATA */
++      0x001c, /* IO_ACX_SLV_MEM_CTL */
++      0x0020, /* IO_ACX_SLV_END_CTL */
++
++      0x0034, /* IO_ACX_FEMR */
++
++      0x007c, /* IO_ACX_INT_TRIG */
++      0x0098, /* IO_ACX_IRQ_MASK */
++      0x00a4, /* IO_ACX_IRQ_STATUS_NON_DES */
++      0x00a8, /* IO_ACX_IRQ_STATUS_CLEAR */
++      0x00ac, /* IO_ACX_IRQ_ACK */
++      0x00b0, /* IO_ACX_HINT_TRIG */
++
++      0x0104, /* IO_ACX_ENABLE */
++
++      0x0250, /* IO_ACX_EEPROM_CTL */
++      0x0254, /* IO_ACX_EEPROM_ADDR */
++      0x0258, /* IO_ACX_EEPROM_DATA */
++      0x025c, /* IO_ACX_EEPROM_CFG */
++
++      0x0268, /* IO_ACX_PHY_ADDR */
++      0x026c, /* IO_ACX_PHY_DATA */
++      0x0270, /* IO_ACX_PHY_CTL */
++
++      0x0290, /* IO_ACX_GPIO_OE */
++
++      0x0298, /* IO_ACX_GPIO_OUT */
++
++      0x02a4, /* IO_ACX_CMD_MAILBOX_OFFS */
++      0x02a8, /* IO_ACX_INFO_MAILBOX_OFFS */
++      0x02ac, /* IO_ACX_EEPROM_INFORMATION */
++
++      0x02d0, /* IO_ACX_EE_START */
++      0x02d4, /* IO_ACX_SOR_CFG */
++      0x02d8 /* IO_ACX_ECPU_CTRL */
++};
++
++static const u16
++IO_ACX111[] =
++{
++      0x0000, /* IO_ACX_SOFT_RESET */
++
++      0x0014, /* IO_ACX_SLV_MEM_ADDR */
++      0x0018, /* IO_ACX_SLV_MEM_DATA */
++      0x001c, /* IO_ACX_SLV_MEM_CTL */
++      0x0020, /* IO_ACX_SLV_MEM_CP */
++
++      0x0034, /* IO_ACX_FEMR */
++
++      0x00b4, /* IO_ACX_INT_TRIG */
++      0x00d4, /* IO_ACX_IRQ_MASK */
++      /* we do mean NON_DES (0xf0), not NON_DES_MASK which is at 0xe0: */
++      0x00f0, /* IO_ACX_IRQ_STATUS_NON_DES */
++      0x00e4, /* IO_ACX_IRQ_STATUS_CLEAR */
++      0x00e8, /* IO_ACX_IRQ_ACK */
++      0x00ec, /* IO_ACX_HINT_TRIG */
++
++      0x01d0, /* IO_ACX_ENABLE */
++
++      0x0338, /* IO_ACX_EEPROM_CTL */
++      0x033c, /* IO_ACX_EEPROM_ADDR */
++      0x0340, /* IO_ACX_EEPROM_DATA */
++      0x0344, /* IO_ACX_EEPROM_CFG */
++
++      0x0350, /* IO_ACX_PHY_ADDR */
++      0x0354, /* IO_ACX_PHY_DATA */
++      0x0358, /* IO_ACX_PHY_CTL */
++
++      0x0374, /* IO_ACX_GPIO_OE */
++
++      0x037c, /* IO_ACX_GPIO_OUT */
++
++      0x0388, /* IO_ACX_CMD_MAILBOX_OFFS */
++      0x038c, /* IO_ACX_INFO_MAILBOX_OFFS */
++      0x0390, /* IO_ACX_EEPROM_INFORMATION */
++
++      0x0100, /* IO_ACX_EE_START */
++      0x0104, /* IO_ACX_SOR_CFG */
++      0x0108, /* IO_ACX_ECPU_CTRL */
++};
++
++static void
++dummy_netdev_init(struct net_device *ndev) {}
++
++/*
++ * Most of the acx specific pieces of hardware reset.
++ */
++static int
++acxmem_complete_hw_reset (acx_device_t *adev)
++{
++      acx111_ie_configoption_t co;
++
++      /* NB: read_reg() reads may return bogus data before reset_dev(),
++       * since the firmware which directly controls large parts of the I/O
++       * registers isn't initialized yet.
++       * acx100 seems to be more affected than acx111 */
++      if (OK != acxmem_s_reset_dev (adev))
++        return -1;
++
++      if (IS_ACX100(adev)) {
++              /* ACX100: configopt struct in cmd mailbox - directly after reset */
++              copy_from_slavemem (adev, (u8*) &co, (u32) adev->cmd_area, sizeof (co));
++      }
++
++      if (OK != acx_s_init_mac(adev))
++        return -3;
++
++      if (IS_ACX111(adev)) {
++              /* ACX111: configopt struct needs to be queried after full init */
++              acx_s_interrogate(adev, &co, ACX111_IE_CONFIG_OPTIONS);
++      }
++
++      /*
++       * Set up transmit buffer administration
++       */
++      init_acx_txbuf (adev);
++
++      /*
++       * Windows driver writes 0x01000000 to register 0x288, RADIO_CTL, if the form factor
++       * is 3.  It also write protects the EEPROM by writing 1<<9 to GPIO_OUT
++       */
++      if (adev->form_factor == 3) {
++        set_regbits (adev, 0x288, 0x01000000);
++        set_regbits (adev, 0x298, 1<<9);
++      }
++
++/* TODO: merge them into one function, they are called just once and are the same for pci & usb */
++      if (OK != acxmem_read_eeprom_byte(adev, 0x05, &adev->eeprom_version))
++        return -2;
++
++      acx_s_parse_configoption(adev, &co);
++      acx_s_get_firmware_version(adev); /* needs to be after acx_s_init_mac() */
++      acx_display_hardware_details(adev);
++
++      return 0;
++}
++
++static int acx_init_netdev(struct net_device *ndev, struct device *dev, int base_addr, int addr_size, int irq)
++{
++      const char *chip_name;
++      int result = -EIO;
++      int err;
++      u8 chip_type;
++      acx_device_t *adev = NULL;
++ 
++      FN_ENTER;
++
++      /* FIXME: prism54 calls pci_set_mwi() here,
++       * should we do/support the same? */
++
++      /* chiptype is u8 but id->driver_data is ulong
++      ** Works for now (possible values are 1 and 2) */
++      chip_type = CHIPTYPE_ACX100;
++      /* acx100 and acx111 have different PCI memory regions */
++      if (chip_type == CHIPTYPE_ACX100) {
++              chip_name = "ACX100";
++      } else if (chip_type == CHIPTYPE_ACX111) {
++              chip_name = "ACX111";
++      } else {
++              printk("acx: unknown chip type 0x%04X\n", chip_type);
++              goto fail_unknown_chiptype;
++      }
++
++      printk("acx: found %s-based wireless network card\n", chip_name);
++      log(L_ANY, "initial debug setting is 0x%04X\n", acx_debug);
++
++
++      dev_set_drvdata(dev, ndev);
++
++      ether_setup(ndev);
++
++      ndev->irq = irq;
++
++      ndev->base_addr = base_addr;
++printk (KERN_INFO "memwinbase=%lx memwinsize=%u\n",memwin.Base,memwin.Size);
++      if (addr_size == 0 || ndev->irq == 0)
++              goto fail_hw_params;
++      ndev->open = &acxmem_e_open;
++      ndev->stop = &acxmem_e_close;
++      //pdev->dev.release = &acxmem_e_release;
++      ndev->hard_start_xmit = &acx_i_start_xmit;
++      ndev->get_stats = &acx_e_get_stats;
++#if IW_HANDLER_VERSION <= 5
++      ndev->get_wireless_stats = &acx_e_get_wireless_stats;
++#endif
++      ndev->wireless_handlers = (struct iw_handler_def *)&acx_ioctl_handler_def;
++      ndev->set_multicast_list = &acxmem_i_set_multicast_list;
++      ndev->tx_timeout = &acxmem_i_tx_timeout;
++      ndev->change_mtu = &acx_e_change_mtu;
++      ndev->watchdog_timeo = 4 * HZ;
++
++      adev = ndev2adev(ndev);
++      spin_lock_init(&adev->lock);    /* initial state: unlocked */
++      spin_lock_init(&adev->txbuf_lock);
++      /* We do not start with downed sem: we want PARANOID_LOCKING to work */
++      sema_init(&adev->sem, 1);       /* initial state: 1 (upped) */
++      /* since nobody can see new netdev yet, we can as well
++      ** just _presume_ that we're under sem (instead of actually taking it): */
++      /* acx_sem_lock(adev); */
++      adev->dev = dev;
++      adev->ndev = ndev;
++      adev->dev_type = DEVTYPE_MEM;
++      adev->chip_type = chip_type;
++      adev->chip_name = chip_name;
++      adev->io = (CHIPTYPE_ACX100 == chip_type) ? IO_ACX100 : IO_ACX111;
++      adev->membase = (volatile u32 *) ndev->base_addr;
++      adev->iobase = (volatile u32 *) ioremap_nocache (ndev->base_addr, addr_size);
++      /* to find crashes due to weird driver access
++       * to unconfigured interface (ifup) */
++      adev->mgmt_timer.function = (void (*)(unsigned long))0x0000dead;
++
++#if defined(NONESSENTIAL_FEATURES)
++      acx_show_card_eeprom_id(adev);
++#endif /* NONESSENTIAL_FEATURES */
++
++#ifdef SET_MODULE_OWNER
++      SET_MODULE_OWNER(ndev);
++#endif
++      // need to fix that @@
++      SET_NETDEV_DEV(ndev, dev);
++
++      log(L_IRQ|L_INIT, "using IRQ %d\n", ndev->irq);
++
++      /* ok, pci setup is finished, now start initializing the card */
++
++      if (OK != acxmem_complete_hw_reset (adev))
++        goto fail_reset;
++
++      /*
++       * Set up default things for most of the card settings.
++       */
++      acx_s_set_defaults(adev);
++
++      /* Register the card, AFTER everything else has been set up,
++       * since otherwise an ioctl could step on our feet due to
++       * firmware operations happening in parallel or uninitialized data */
++      err = register_netdev(ndev);
++      if (OK != err) {
++              printk("acx: register_netdev() FAILED: %d\n", err);
++              goto fail_register_netdev;
++      }
++
++      acx_proc_register_entries(ndev);
++
++      /* Now we have our device, so make sure the kernel doesn't try
++       * to send packets even though we're not associated to a network yet */
++      acx_stop_queue(ndev, "on probe");
++      acx_carrier_off(ndev, "on probe");
++
++      /*
++       * Set up a default monitor type so that poor combinations of initialization
++       * sequences in monitor mode don't end up destroying the hardware type.
++       */
++      adev->monitor_type = ARPHRD_ETHER;
++
++      /*
++       * Register to receive inetaddr notifier changes.  This will allow us to
++       * catch if the user changes the MAC address of the interface.
++       */
++      register_netdevice_notifier(&acx_netdev_notifier);
++
++      /* after register_netdev() userspace may start working with dev
++       * (in particular, on other CPUs), we only need to up the sem */
++      /* acx_sem_unlock(adev); */
++
++      printk("acx "ACX_RELEASE": net device %s, driver compiled "
++              "against wireless extensions %d and Linux %s\n",
++              ndev->name, WIRELESS_EXT, UTS_RELEASE);
++
++#if CMD_DISCOVERY
++      great_inquisitor(adev);
++#endif
++
++      result = OK;
++      goto done;
++
++      /* error paths: undo everything in reverse order... */
++
++fail_register_netdev:
++
++      acxmem_s_delete_dma_regions(adev);
++
++fail_reset:
++fail_hw_params:
++      free_netdev(ndev);
++fail_unknown_chiptype:
++
++
++done:
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/***********************************************************************
++** acxmem_e_remove
++**
++** Shut device down (if not hot unplugged)
++** and deallocate PCI resources for the acx chip.
++**
++** pdev - ptr to PCI device structure containing info about pci configuration
++*/
++static int __devexit
++acxmem_e_remove(struct pcmcia_device *link)
++{
++      struct net_device *ndev;
++      acx_device_t *adev;
++      unsigned long flags;
++
++      FN_ENTER;
++
++      ndev = ((local_info_t*)link->priv)->ndev;
++      if (!ndev) {
++              log(L_DEBUG, "%s: card is unused. Skipping any release code\n",
++                      __func__);
++              goto end;
++      }
++
++      adev = ndev2adev(ndev);
++
++      /* If device wasn't hot unplugged... */
++      if (adev_present(adev)) {
++
++              acx_sem_lock(adev);
++
++              /* disable both Tx and Rx to shut radio down properly */
++              acx_s_issue_cmd(adev, ACX1xx_CMD_DISABLE_TX, NULL, 0);
++              acx_s_issue_cmd(adev, ACX1xx_CMD_DISABLE_RX, NULL, 0);
++
++#ifdef REDUNDANT
++              /* put the eCPU to sleep to save power
++               * Halting is not possible currently,
++               * since not supported by all firmware versions */
++              acx_s_issue_cmd(adev, ACX100_CMD_SLEEP, NULL, 0);
++#endif
++              acx_lock(adev, flags);
++
++              /* disable power LED to save power :-) */
++              log(L_INIT, "switching off power LED to save power\n");
++              acxmem_l_power_led(adev, 0);
++
++              /* stop our eCPU */
++              if (IS_ACX111(adev)) {
++                      /* FIXME: does this actually keep halting the eCPU?
++                       * I don't think so...
++                       */
++                      acxmem_l_reset_mac(adev);
++              } else {
++                      u16 temp;
++
++                      /* halt eCPU */
++                      temp = read_reg16(adev, IO_ACX_ECPU_CTRL) | 0x1;
++                      write_reg16(adev, IO_ACX_ECPU_CTRL, temp);
++                      write_flush(adev);
++              }
++
++              acx_unlock(adev, flags);
++
++              acx_sem_unlock(adev);
++      }
++
++
++      /*
++       * Unregister the notifier chain
++       */
++      unregister_netdevice_notifier(&acx_netdev_notifier);
++
++      /* unregister the device to not let the kernel
++       * (e.g. ioctls) access a half-deconfigured device
++       * NB: this will cause acxmem_e_close() to be called,
++       * thus we shouldn't call it under sem! */
++      log(L_INIT, "removing device %s\n", ndev->name);
++      unregister_netdev(ndev);
++
++      /* unregister_netdev ensures that no references to us left.
++       * For paranoid reasons we continue to follow the rules */
++      acx_sem_lock(adev);
++
++      if (adev->dev_state_mask & ACX_STATE_IFACE_UP) {
++              acxmem_s_down(ndev);
++              CLEAR_BIT(adev->dev_state_mask, ACX_STATE_IFACE_UP);
++      }
++
++      acx_proc_unregister_entries(ndev);
++
++      acxmem_s_delete_dma_regions(adev);
++
++      /* finally, clean up PCI bus state */
++      if (adev->iobase) iounmap((void *)adev->iobase);
++
++      acx_sem_unlock(adev);
++
++      /* Free netdev (quite late,
++       * since otherwise we might get caught off-guard
++       * by a netdev timeout handler execution
++       * expecting to see a working dev...) */
++      free_netdev(ndev);
++
++      printk ("e_remove done\n");
++end:
++      FN_EXIT0;
++
++      return 0;
++}
++
++
++/***********************************************************************
++** TODO: PM code needs to be fixed / debugged / tested.
++*/
++#ifdef CONFIG_PM
++static int
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11)
++acxmem_e_suspend( struct net_device *ndev, pm_message_t state)
++#else
++acxmem_e_suspend( struct net_device *ndev, u32 state)
++#endif
++{
++      FN_ENTER;
++      acx_device_t *adev;
++      printk("acx: suspend handler is experimental!\n");
++      printk("sus: dev %p\n", ndev);
++
++      if (!netif_running(ndev))
++              goto end;
++      // @@ need to get it from link or something like that
++      adev = ndev2adev(ndev);
++      printk("sus: adev %p\n", adev);
++
++      acx_sem_lock(adev);
++
++      netif_device_detach(adev->ndev);        /* this one cannot sleep */
++      acxmem_s_down(adev->ndev);
++      /* down() does not set it to 0xffff, but here we really want that */
++      write_reg16(adev, IO_ACX_IRQ_MASK, 0xffff);
++      write_reg16(adev, IO_ACX_FEMR, 0x0);
++      acxmem_s_delete_dma_regions(adev);
++
++      /*
++       * Turn the ACX chip off.
++       */
++
++      acx_sem_unlock(adev);
++end:
++      FN_EXIT0;
++      return OK;
++}
++
++
++static void
++fw_resumer(struct work_struct *notused)
++{
++      acx_device_t *adev;
++      struct net_device *ndev = resume_ndev;
++
++      printk("acx: resume handler is experimental!\n");
++      printk("rsm: got dev %p\n", ndev);
++
++      if (!netif_running(ndev))
++              return;
++
++      adev = ndev2adev(ndev);
++      printk("rsm: got adev %p\n", adev);
++
++      acx_sem_lock(adev);
++
++      /*
++       * Turn on the ACX.
++       */
++
++      acxmem_complete_hw_reset (adev);
++
++      /*
++       * done by acx_s_set_defaults for initial startup
++       */
++      acxmem_set_interrupt_mask(adev);
++
++      printk ("rsm: bringing up interface\n");
++      SET_BIT (adev->set_mask, GETSET_ALL);
++      acxmem_s_up(ndev);
++      printk("rsm: acx up done\n");
++
++      /* now even reload all card parameters as they were before suspend,
++       * and possibly be back in the network again already :-) 
++       */
++      /* - most settings updated in acxmem_s_up()
++      if (ACX_STATE_IFACE_UP & adev->dev_state_mask) {
++              adev->set_mask = GETSET_ALL;
++              acx_s_update_card_settings(adev);
++              printk("rsm: settings updated\n");
++      }
++      */
++      netif_device_attach(ndev);
++      printk("rsm: device attached\n");
++
++      acx_sem_unlock(adev);
++}
++
++DECLARE_WORK( fw_resume_work, fw_resumer );
++
++static int
++acxmem_e_resume(struct pcmcia_device *link)
++{
++      FN_ENTER;
++
++      //resume_pdev = pdev;
++      schedule_work( &fw_resume_work );
++
++      FN_EXIT0;
++      return OK;
++}
++#endif /* CONFIG_PM */
++
++
++/***********************************************************************
++** acxmem_s_up
++**
++** This function is called by acxmem_e_open (when ifconfig sets the device as up)
++**
++** Side effects:
++** - Enables on-card interrupt requests
++** - calls acx_s_start
++*/
++
++static void
++enable_acx_irq(acx_device_t *adev)
++{
++      FN_ENTER;
++      write_reg16(adev, IO_ACX_IRQ_MASK, adev->irq_mask);
++      write_reg16(adev, IO_ACX_FEMR, 0x8000);
++      adev->irqs_active = 1;
++      FN_EXIT0;
++}
++
++static void
++acxmem_s_up(struct net_device *ndev)
++{
++      acx_device_t *adev = ndev2adev(ndev);
++      unsigned long flags;
++
++      FN_ENTER;
++
++      acx_lock(adev, flags);
++      enable_acx_irq(adev);
++      acx_unlock(adev, flags);
++
++      /* acx fw < 1.9.3.e has a hardware timer, and older drivers
++      ** used to use it. But we don't do that anymore, our OS
++      ** has reliable software timers */
++      init_timer(&adev->mgmt_timer);
++      adev->mgmt_timer.function = acx_i_timer;
++      adev->mgmt_timer.data = (unsigned long)adev;
++
++      /* Need to set ACX_STATE_IFACE_UP first, or else
++      ** timer won't be started by acx_set_status() */
++      SET_BIT(adev->dev_state_mask, ACX_STATE_IFACE_UP);
++      switch (adev->mode) {
++      case ACX_MODE_0_ADHOC:
++      case ACX_MODE_2_STA:
++              /* actual scan cmd will happen in start() */
++              acx_set_status(adev, ACX_STATUS_1_SCANNING); break;
++      case ACX_MODE_3_AP:
++      case ACX_MODE_MONITOR:
++              acx_set_status(adev, ACX_STATUS_4_ASSOCIATED); break;
++      }
++
++      acx_s_start(adev);
++
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++** acxmem_s_down
++**
++** This disables the netdevice
++**
++** Side effects:
++** - disables on-card interrupt request
++*/
++
++static void
++disable_acx_irq(acx_device_t *adev)
++{
++      FN_ENTER;
++
++      /* I guess mask is not 0xffff because acx100 won't signal
++      ** cmd completion then (needed for ifup).
++      ** Someone with acx100 please confirm */
++      write_reg16(adev, IO_ACX_IRQ_MASK, adev->irq_mask_off);
++      write_reg16(adev, IO_ACX_FEMR, 0x0);
++      adev->irqs_active = 0;
++      FN_EXIT0;
++}
++
++static void
++acxmem_s_down(struct net_device *ndev)
++{
++      acx_device_t *adev = ndev2adev(ndev);
++      unsigned long flags;
++
++      FN_ENTER;
++
++      /* Disable IRQs first, so that IRQs cannot race with us */
++      /* then wait until interrupts have finished executing on other CPUs */
++      acx_lock(adev, flags);
++      disable_acx_irq(adev);
++      synchronize_irq(adev->pdev->irq);
++      acx_unlock(adev, flags);
++
++      /* we really don't want to have an asynchronous tasklet disturb us
++      ** after something vital for its job has been shut down, so
++      ** end all remaining work now.
++      **
++      ** NB: carrier_off (done by set_status below) would lead to
++      ** not yet fully understood deadlock in FLUSH_SCHEDULED_WORK().
++      ** That's why we do FLUSH first.
++      **
++      ** NB2: we have a bad locking bug here: FLUSH_SCHEDULED_WORK()
++      ** waits for acx_e_after_interrupt_task to complete if it is running
++      ** on another CPU, but acx_e_after_interrupt_task
++      ** will sleep on sem forever, because it is taken by us!
++      ** Work around that by temporary sem unlock.
++      ** This will fail miserably if we'll be hit by concurrent
++      ** iwconfig or something in between. TODO! */
++      acx_sem_unlock(adev);
++      FLUSH_SCHEDULED_WORK();
++      acx_sem_lock(adev);
++
++      /* This is possible:
++      ** FLUSH_SCHEDULED_WORK -> acx_e_after_interrupt_task ->
++      ** -> set_status(ASSOCIATED) -> wake_queue()
++      ** That's why we stop queue _after_ FLUSH_SCHEDULED_WORK
++      ** lock/unlock is just paranoia, maybe not needed */
++      acx_lock(adev, flags);
++      acx_stop_queue(ndev, "on ifdown");
++      acx_set_status(adev, ACX_STATUS_0_STOPPED);
++      acx_unlock(adev, flags);
++
++      /* kernel/timer.c says it's illegal to del_timer_sync()
++      ** a timer which restarts itself. We guarantee this cannot
++      ** ever happen because acx_i_timer() never does this if
++      ** status is ACX_STATUS_0_STOPPED */
++      del_timer_sync(&adev->mgmt_timer);
++
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++** acxmem_e_open
++**
++** Called as a result of SIOCSIFFLAGS ioctl changing the flags bit IFF_UP
++** from clear to set. In other words: ifconfig up.
++**
++** Returns:
++**    0       success
++**    >0      f/w reported error
++**    <0      driver reported error
++*/
++static int
++acxmem_e_open(struct net_device *ndev)
++{
++      acx_device_t *adev = ndev2adev(ndev);
++      int result = OK;
++
++      FN_ENTER;
++
++      acx_sem_lock(adev);
++
++      acx_init_task_scheduler(adev);
++
++/* TODO: pci_set_power_state(pdev, PCI_D0); ? */
++
++#if 0
++      /* request shared IRQ handler */
++      if (request_irq(ndev->irq, acxmem_i_interrupt, SA_INTERRUPT, ndev->name, ndev)) {
++              printk("%s: request_irq FAILED\n", ndev->name);
++              result = -EAGAIN;
++              goto done;
++      }
++      set_irq_type (ndev->irq, IRQT_FALLING);
++      log(L_DEBUG|L_IRQ, "request_irq %d successful\n", ndev->irq);
++#endif
++
++      /* ifup device */
++      acxmem_s_up(ndev);
++
++      /* We don't currently have to do anything else.
++       * The setup of the MAC should be subsequently completed via
++       * the mlme commands.
++       * Higher layers know we're ready from dev->start==1 and
++       * dev->tbusy==0.  Our rx path knows to pass up received/
++       * frames because of dev->flags&IFF_UP is true.
++       */
++done:
++      acx_sem_unlock(adev);
++
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/***********************************************************************
++** acxmem_e_close
++**
++** Called as a result of SIOCSIIFFLAGS ioctl changing the flags bit IFF_UP
++** from set to clear. I.e. called by "ifconfig DEV down"
++**
++** Returns:
++**    0       success
++**    >0      f/w reported error
++**    <0      driver reported error
++*/
++static int
++acxmem_e_close(struct net_device *ndev)
++{
++      acx_device_t *adev = ndev2adev(ndev);
++
++      FN_ENTER;
++
++      acx_sem_lock(adev);
++
++      /* ifdown device */
++      CLEAR_BIT(adev->dev_state_mask, ACX_STATE_IFACE_UP);
++      if (netif_device_present(ndev)) {
++              acxmem_s_down(ndev);
++      }
++
++      /* disable all IRQs, release shared IRQ handler */
++      write_reg16(adev, IO_ACX_IRQ_MASK, 0xffff);
++      write_reg16(adev, IO_ACX_FEMR, 0x0);
++      free_irq(ndev->irq, ndev);
++
++/* TODO: pci_set_power_state(pdev, PCI_D3hot); ? */
++
++      /* We currently don't have to do anything else.
++       * Higher layers know we're not ready from dev->start==0 and
++       * dev->tbusy==1.  Our rx path knows to not pass up received
++       * frames because of dev->flags&IFF_UP is false.
++       */
++      acx_sem_unlock(adev);
++
++      log(L_INIT, "closed device\n");
++      FN_EXIT0;
++      return OK;
++}
++
++
++/***********************************************************************
++** acxmem_i_tx_timeout
++**
++** Called from network core. Must not sleep!
++*/
++static void
++acxmem_i_tx_timeout(struct net_device *ndev)
++{
++      acx_device_t *adev = ndev2adev(ndev);
++      unsigned long flags;
++      unsigned int tx_num_cleaned;
++
++      FN_ENTER;
++
++      acx_lock(adev, flags);
++
++      /* clean processed tx descs, they may have been completely full */
++      tx_num_cleaned = acxmem_l_clean_txdesc(adev);
++
++      /* nothing cleaned, yet (almost) no free buffers available?
++       * --> clean all tx descs, no matter which status!!
++       * Note that I strongly suspect that doing emergency cleaning
++       * may confuse the firmware. This is a last ditch effort to get
++       * ANYTHING to work again...
++       *
++       * TODO: it's best to simply reset & reinit hw from scratch...
++       */
++      if ((adev->tx_free <= TX_EMERG_CLEAN) && (tx_num_cleaned == 0)) {
++              printk("%s: FAILED to free any of the many full tx buffers. "
++                      "Switching to emergency freeing. "
++                      "Please report!\n", ndev->name);
++              acxmem_l_clean_txdesc_emergency(adev);
++      }
++
++      if (acx_queue_stopped(ndev) && (ACX_STATUS_4_ASSOCIATED == adev->status))
++              acx_wake_queue(ndev, "after tx timeout");
++
++      /* stall may have happened due to radio drift, so recalib radio */
++      acx_schedule_task(adev, ACX_AFTER_IRQ_CMD_RADIO_RECALIB);
++
++      /* do unimportant work last */
++      printk("%s: tx timeout!\n", ndev->name);
++      adev->stats.tx_errors++;
++
++      acx_unlock(adev, flags);
++
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++** acxmem_i_set_multicast_list
++** FIXME: most likely needs refinement
++*/
++static void
++acxmem_i_set_multicast_list(struct net_device *ndev)
++{
++      acx_device_t *adev = ndev2adev(ndev);
++      unsigned long flags;
++
++      FN_ENTER;
++
++      acx_lock(adev, flags);
++
++      /* firmwares don't have allmulti capability,
++       * so just use promiscuous mode instead in this case. */
++      if (ndev->flags & (IFF_PROMISC|IFF_ALLMULTI)) {
++              SET_BIT(adev->rx_config_1, RX_CFG1_RCV_PROMISCUOUS);
++              CLEAR_BIT(adev->rx_config_1, RX_CFG1_FILTER_ALL_MULTI);
++              SET_BIT(adev->set_mask, SET_RXCONFIG);
++              /* let kernel know in case *we* needed to set promiscuous */
++              ndev->flags |= (IFF_PROMISC|IFF_ALLMULTI);
++      } else {
++              CLEAR_BIT(adev->rx_config_1, RX_CFG1_RCV_PROMISCUOUS);
++              SET_BIT(adev->rx_config_1, RX_CFG1_FILTER_ALL_MULTI);
++              SET_BIT(adev->set_mask, SET_RXCONFIG);
++              ndev->flags &= ~(IFF_PROMISC|IFF_ALLMULTI);
++      }
++
++      /* cannot update card settings directly here, atomic context */
++      acx_schedule_task(adev, ACX_AFTER_IRQ_UPDATE_CARD_CFG);
++
++      acx_unlock(adev, flags);
++
++      FN_EXIT0;
++}
++
++
++/***************************************************************
++** acxmem_l_process_rxdesc
++**
++** Called directly and only from the IRQ handler
++*/
++
++#if !ACX_DEBUG
++static inline void log_rxbuffer(const acx_device_t *adev) {}
++#else
++static void
++log_rxbuffer(const acx_device_t *adev)
++{
++      register const struct rxhostdesc *rxhostdesc;
++      int i;
++      /* no FN_ENTER here, we don't want that */
++
++      rxhostdesc = adev->rxhostdesc_start;
++      if (unlikely(!rxhostdesc)) return;
++      for (i = 0; i < RX_CNT; i++) {
++              if ((rxhostdesc->Ctl_16 & cpu_to_le16(DESC_CTL_HOSTOWN))
++               && (rxhostdesc->Status & cpu_to_le32(DESC_STATUS_FULL)))
++                      printk("rx: buf %d full\n", i);
++              rxhostdesc++;
++      }
++}
++#endif
++
++static void
++acxmem_l_process_rxdesc(acx_device_t *adev)
++{
++      register rxhostdesc_t *hostdesc;
++      register rxdesc_t *rxdesc;
++      unsigned count, tail;
++      u32 addr;
++      u8 Ctl_8;
++
++      FN_ENTER;
++
++      if (unlikely(acx_debug & L_BUFR))
++              log_rxbuffer(adev);
++
++      /* First, have a loop to determine the first descriptor that's
++       * full, just in case there's a mismatch between our current
++       * rx_tail and the full descriptor we're supposed to handle. */
++      tail = adev->rx_tail;
++      count = RX_CNT;
++      while (1) {
++              hostdesc = &adev->rxhostdesc_start[tail];
++              rxdesc = &adev->rxdesc_start[tail];
++              /* advance tail regardless of outcome of the below test */
++              tail = (tail + 1) % RX_CNT;
++
++              /*
++               * Unlike the PCI interface, where the ACX can write directly to
++               * the host descriptors, on the slave memory interface we have to
++               * pull these.  All we really need to do is check the Ctl_8 field
++               * in the rx descriptor on the ACX, which should be 0x11000000 if
++               * we should process it.
++               */
++              Ctl_8 = hostdesc->Ctl_16 = read_slavemem8 (adev, (u32) &(rxdesc->Ctl_8));
++                if ((Ctl_8 & DESC_CTL_HOSTOWN) &&
++                  (Ctl_8 & DESC_CTL_ACXDONE))
++                break;                /* found it! */
++
++              if (unlikely(!--count)) /* hmm, no luck: all descs empty, bail out */
++                      goto end;
++      }
++
++      /* now process descriptors, starting with the first we figured out */
++      while (1) {
++              log(L_BUFR, "rx: tail=%u Ctl_8=%02X\n", tail, Ctl_8);
++              /*
++               * If the ACX has CTL_RECLAIM set on this descriptor there
++               * is no buffer associated; it just wants us to tell it to
++               * reclaim the memory.
++               */
++              if (!(Ctl_8 & DESC_CTL_RECLAIM)) {
++
++                /*
++               * slave interface - pull data now
++               */
++              hostdesc->length = read_slavemem16 (adev, (u32) &(rxdesc->total_length));
++
++              /*
++               * hostdesc->data is an rxbuffer_t, which includes header information,
++               * but the length in the data packet doesn't.  The header information
++               * takes up an additional 12 bytes, so add that to the length we copy.
++               */
++              addr = read_slavemem32 (adev, (u32) &(rxdesc->ACXMemPtr));
++                if (addr) {
++                  /*
++                   * How can &(rxdesc->ACXMemPtr) above ever be zero?  Looks like we
++                   * get that now and then - try to trap it for debug.
++                   */
++                  if (addr & 0xffff0000) {
++                    printk("rxdesc 0x%08x\n", (u32) rxdesc);
++                    dump_acxmem (adev, 0, 0x10000);
++                    panic ("Bad access!");
++                  }
++                chaincopy_from_slavemem (adev, (u8 *) hostdesc->data, addr,
++                                         hostdesc->length +
++                                         (u32) &((rxbuffer_t *)0)->hdr_a3);
++              acx_l_process_rxbuf(adev, hostdesc->data);
++                }
++              }
++              else {
++                printk ("rx reclaim only!\n");
++              }
++
++              hostdesc->Status = 0;
++
++              /*
++               * Let the ACX know we're done.
++               */
++              CLEAR_BIT (Ctl_8, DESC_CTL_HOSTOWN);
++                SET_BIT (Ctl_8, DESC_CTL_HOSTDONE);
++              SET_BIT (Ctl_8, DESC_CTL_RECLAIM);
++              write_slavemem8 (adev, (u32) &rxdesc->Ctl_8, Ctl_8);
++
++              /*
++               * Now tell the ACX we've finished with the receive buffer so 
++               * it can finish the reclaim.
++               */
++              write_reg16 (adev, IO_ACX_INT_TRIG, INT_TRIG_RXPRC);
++
++              /* ok, descriptor is handled, now check the next descriptor */
++              hostdesc = &adev->rxhostdesc_start[tail];
++              rxdesc = &adev->rxdesc_start[tail];
++
++              Ctl_8 = hostdesc->Ctl_16 = read_slavemem8 (adev, (u32) &(rxdesc->Ctl_8));
++
++              /* if next descriptor is empty, then bail out */
++              if (!(Ctl_8 & DESC_CTL_HOSTOWN) || !(Ctl_8 & DESC_CTL_ACXDONE))
++                      break;
++
++              tail = (tail + 1) % RX_CNT;
++      }
++end:
++      adev->rx_tail = tail;
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++** acxmem_i_interrupt
++**
++** IRQ handler (atomic context, must not sleep, blah, blah)
++*/
++
++/* scan is complete. all frames now on the receive queue are valid */
++#define INFO_SCAN_COMPLETE      0x0001
++#define INFO_WEP_KEY_NOT_FOUND  0x0002
++/* hw has been reset as the result of a watchdog timer timeout */
++#define INFO_WATCH_DOG_RESET    0x0003
++/* failed to send out NULL frame from PS mode notification to AP */
++/* recommended action: try entering 802.11 PS mode again */
++#define INFO_PS_FAIL            0x0004
++/* encryption/decryption process on a packet failed */
++#define INFO_IV_ICV_FAILURE     0x0005
++
++/* Info mailbox format:
++2 bytes: type
++2 bytes: status
++more bytes may follow
++    rumors say about status:
++      0x0000 info available (set by hw)
++      0x0001 information received (must be set by host)
++      0x1000 info available, mailbox overflowed (messages lost) (set by hw)
++    but in practice we've seen:
++      0x9000 when we did not set status to 0x0001 on prev message
++      0x1001 when we did set it
++      0x0000 was never seen
++    conclusion: this is really a bitfield:
++    0x1000 is 'info available' bit
++    'mailbox overflowed' bit is 0x8000, not 0x1000
++    value of 0x0000 probably means that there are no messages at all
++    P.S. I dunno how in hell hw is supposed to notice that messages are lost -
++    it does NOT clear bit 0x0001, and this bit will probably stay forever set
++    after we set it once. Let's hope this will be fixed in firmware someday
++*/
++
++static void
++handle_info_irq(acx_device_t *adev)
++{
++#if ACX_DEBUG
++      static const char * const info_type_msg[] = {
++              "(unknown)",
++              "scan complete",
++              "WEP key not found",
++              "internal watchdog reset was done",
++              "failed to send powersave (NULL frame) notification to AP",
++              "encrypt/decrypt on a packet has failed",
++              "TKIP tx keys disabled",
++              "TKIP rx keys disabled",
++              "TKIP rx: key ID not found",
++              "???",
++              "???",
++              "???",
++              "???",
++              "???",
++              "???",
++              "???",
++              "TKIP IV value exceeds thresh"
++      };
++#endif
++      u32 info_type, info_status;
++
++      info_type = read_slavemem32 (adev, (u32) adev->info_area);
++
++      info_status = (info_type >> 16);
++      info_type = (u16)info_type;
++
++      /* inform fw that we have read this info message */
++      write_slavemem32(adev, (u32) adev->info_area, info_type | 0x00010000);
++      write_reg16(adev, IO_ACX_INT_TRIG, INT_TRIG_INFOACK);
++      write_flush(adev);
++
++      log(L_CTL, "info_type:%04X info_status:%04X\n",
++                      info_type, info_status);
++
++      log(L_IRQ, "got Info IRQ: status %04X type %04X: %s\n",
++              info_status, info_type,
++              info_type_msg[(info_type >= VEC_SIZE(info_type_msg)) ?
++                              0 : info_type]
++      );
++}
++
++
++static void
++log_unusual_irq(u16 irqtype) {
++      /*
++      if (!printk_ratelimit())
++              return;
++      */
++
++      printk("acx: got");
++      if (irqtype & HOST_INT_TX_XFER) {
++              printk(" Tx_Xfer");
++      }
++      if (irqtype & HOST_INT_RX_COMPLETE) {
++              printk(" Rx_Complete");
++      }
++      if (irqtype & HOST_INT_DTIM) {
++              printk(" DTIM");
++      }
++      if (irqtype & HOST_INT_BEACON) {
++              printk(" Beacon");
++      }
++      if (irqtype & HOST_INT_TIMER) {
++              log(L_IRQ, " Timer");
++      }
++      if (irqtype & HOST_INT_KEY_NOT_FOUND) {
++              printk(" Key_Not_Found");
++      }
++      if (irqtype & HOST_INT_IV_ICV_FAILURE) {
++              printk(" IV_ICV_Failure (crypto)");
++      }
++              /* HOST_INT_CMD_COMPLETE  */
++              /* HOST_INT_INFO          */
++      if (irqtype & HOST_INT_OVERFLOW) {
++              printk(" Overflow");
++      }
++      if (irqtype & HOST_INT_PROCESS_ERROR) {
++              printk(" Process_Error");
++      }
++              /* HOST_INT_SCAN_COMPLETE */
++      if (irqtype & HOST_INT_FCS_THRESHOLD) {
++              printk(" FCS_Threshold");
++      }
++      if (irqtype & HOST_INT_UNKNOWN) {
++              printk(" Unknown");
++      }
++      printk(" IRQ(s)\n");
++}
++
++
++static void
++update_link_quality_led(acx_device_t *adev)
++{
++      int qual;
++
++      qual = acx_signal_determine_quality(adev->wstats.qual.level, adev->wstats.qual.noise);
++      if (qual > adev->brange_max_quality)
++              qual = adev->brange_max_quality;
++
++      if (time_after(jiffies, adev->brange_time_last_state_change +
++                              (HZ/2 - HZ/2 * (unsigned long)qual / adev->brange_max_quality ) )) {
++              acxmem_l_power_led(adev, (adev->brange_last_state == 0));
++              adev->brange_last_state ^= 1; /* toggle */
++              adev->brange_time_last_state_change = jiffies;
++      }
++}
++
++
++#define MAX_IRQLOOPS_PER_JIFFY  (20000/HZ) /* a la orinoco.c */
++
++static irqreturn_t
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
++acxmem_i_interrupt(int irq, void *dev_id)
++#else
++acxmwm_i_interrupt(int irq, void *dev_id, struct pt_regs *regs)
++#endif
++{
++      acx_device_t *adev;
++      unsigned long flags;
++      unsigned int irqcount = MAX_IRQLOOPS_PER_JIFFY;
++      register u16 irqtype;
++      u16 unmasked;
++
++      adev = ndev2adev((struct net_device*)dev_id);
++
++      /* LOCKING: can just spin_lock() since IRQs are disabled anyway.
++       * I am paranoid */
++      acx_lock(adev, flags);
++
++      unmasked = read_reg16(adev, IO_ACX_IRQ_STATUS_CLEAR);
++      if (unlikely(0xffff == unmasked)) {
++              /* 0xffff value hints at missing hardware,
++               * so don't do anything.
++               * Not very clean, but other drivers do the same... */
++              log(L_IRQ, "IRQ type:FFFF - device removed? IRQ_NONE\n");
++              goto none;
++      }
++
++      /* We will check only "interesting" IRQ types */
++      irqtype = unmasked & ~adev->irq_mask;
++      if (!irqtype) {
++              /* We are on a shared IRQ line and it wasn't our IRQ */
++              log(L_IRQ, "IRQ type:%04X, mask:%04X - all are masked, IRQ_NONE\n",
++                      unmasked, adev->irq_mask);
++              goto none;
++      }
++
++      /* Done here because IRQ_NONEs taking three lines of log
++      ** drive me crazy */
++      FN_ENTER;
++
++#define IRQ_ITERATE 1
++#if IRQ_ITERATE
++if (jiffies != adev->irq_last_jiffies) {
++      adev->irq_loops_this_jiffy = 0;
++      adev->irq_last_jiffies = jiffies;
++}
++
++/* safety condition; we'll normally abort loop below
++ * in case no IRQ type occurred */
++while (likely(--irqcount)) {
++#endif
++      /* ACK all IRQs ASAP */
++      write_reg16(adev, IO_ACX_IRQ_ACK, 0xffff);
++
++      log(L_IRQ, "IRQ type:%04X, mask:%04X, type & ~mask:%04X\n",
++                              unmasked, adev->irq_mask, irqtype);
++
++      /* Handle most important IRQ types first */
++      if (irqtype & HOST_INT_RX_DATA) {
++              log(L_IRQ, "got Rx_Data IRQ\n");
++              acxmem_l_process_rxdesc(adev);
++      }
++      if (irqtype & HOST_INT_TX_COMPLETE) {
++              log(L_IRQ, "got Tx_Complete IRQ\n");
++              /* don't clean up on each Tx complete, wait a bit
++               * unless we're going towards full, in which case
++               * we do it immediately, too (otherwise we might lockup
++               * with a full Tx buffer if we go into
++               * acxmem_l_clean_txdesc() at a time when we won't wakeup
++               * the net queue in there for some reason...) */
++              if (adev->tx_free <= TX_START_CLEAN) {
++#if TX_CLEANUP_IN_SOFTIRQ
++                      acx_schedule_task(adev, ACX_AFTER_IRQ_TX_CLEANUP);
++#else
++                      acxmem_l_clean_txdesc(adev);
++#endif
++              }
++      }
++
++      /* Less frequent ones */
++      if (irqtype & (0
++              | HOST_INT_CMD_COMPLETE
++              | HOST_INT_INFO
++              | HOST_INT_SCAN_COMPLETE
++      )) {
++              if (irqtype & HOST_INT_CMD_COMPLETE) {
++                      log(L_IRQ, "got Command_Complete IRQ\n");
++                      /* save the state for the running issue_cmd() */
++                      SET_BIT(adev->irq_status, HOST_INT_CMD_COMPLETE);
++              }
++              if (irqtype & HOST_INT_INFO) {
++                      handle_info_irq(adev);
++              }
++              if (irqtype & HOST_INT_SCAN_COMPLETE) {
++                      log(L_IRQ, "got Scan_Complete IRQ\n");
++                      /* need to do that in process context */
++                      acx_schedule_task(adev, ACX_AFTER_IRQ_COMPLETE_SCAN);
++                      /* remember that fw is not scanning anymore */
++                      SET_BIT(adev->irq_status, HOST_INT_SCAN_COMPLETE);
++              }
++      }
++
++      /* These we just log, but either they happen rarely
++       * or we keep them masked out */
++      if (irqtype & (0
++              /* | HOST_INT_RX_DATA */
++              /* | HOST_INT_TX_COMPLETE   */
++              | HOST_INT_TX_XFER
++              | HOST_INT_RX_COMPLETE
++              | HOST_INT_DTIM
++              | HOST_INT_BEACON
++              | HOST_INT_TIMER
++              | HOST_INT_KEY_NOT_FOUND
++              | HOST_INT_IV_ICV_FAILURE
++              /* | HOST_INT_CMD_COMPLETE  */
++              /* | HOST_INT_INFO          */
++              | HOST_INT_OVERFLOW
++              | HOST_INT_PROCESS_ERROR
++              /* | HOST_INT_SCAN_COMPLETE */
++              | HOST_INT_FCS_THRESHOLD
++              | HOST_INT_UNKNOWN
++      )) {
++              log_unusual_irq(irqtype);
++      }
++
++#if IRQ_ITERATE
++      unmasked = read_reg16(adev, IO_ACX_IRQ_STATUS_CLEAR);
++      irqtype = unmasked & ~adev->irq_mask;
++      /* Bail out if no new IRQ bits or if all are masked out */
++      if (!irqtype)
++              break;
++
++      if (unlikely(++adev->irq_loops_this_jiffy > MAX_IRQLOOPS_PER_JIFFY)) {
++              printk(KERN_ERR "acx: too many interrupts per jiffy!\n");
++              /* Looks like card floods us with IRQs! Try to stop that */
++              write_reg16(adev, IO_ACX_IRQ_MASK, 0xffff);
++              /* This will short-circuit all future attempts to handle IRQ.
++               * We cant do much more... */
++              adev->irq_mask = 0;
++              break;
++      }
++}
++#endif
++      /* Routine to perform blink with range */
++      if (unlikely(adev->led_power == 2))
++              update_link_quality_led(adev);
++
++/* handled: */
++      /* write_flush(adev); - not needed, last op was read anyway */
++      acx_unlock(adev, flags);
++      FN_EXIT0;
++      return IRQ_HANDLED;
++
++none:
++      acx_unlock(adev, flags);
++      return IRQ_NONE;
++}
++
++
++/***********************************************************************
++** acxmem_l_power_led
++*/
++void
++acxmem_l_power_led(acx_device_t *adev, int enable)
++{
++      u16 gpio_pled = IS_ACX111(adev) ? 0x0040 : 0x0800;
++
++      /* A hack. Not moving message rate limiting to adev->xxx
++       * (it's only a debug message after all) */
++      static int rate_limit = 0;
++
++      if (rate_limit++ < 3)
++              log(L_IOCTL, "Please report in case toggling the power "
++                              "LED doesn't work for your card!\n");
++      if (enable)
++              write_reg16(adev, IO_ACX_GPIO_OUT,
++                      read_reg16(adev, IO_ACX_GPIO_OUT) & ~gpio_pled);
++      else
++              write_reg16(adev, IO_ACX_GPIO_OUT,
++                      read_reg16(adev, IO_ACX_GPIO_OUT) | gpio_pled);
++}
++
++
++/***********************************************************************
++** Ioctls
++*/
++
++/***********************************************************************
++*/
++int
++acx111pci_ioctl_info(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      struct iw_param *vwrq,
++      char *extra)
++{
++#if ACX_DEBUG > 1
++      acx_device_t *adev = ndev2adev(ndev);
++      rxdesc_t *rxdesc;
++      txdesc_t *txdesc;
++      rxhostdesc_t *rxhostdesc;
++      txhostdesc_t *txhostdesc;
++      struct acx111_ie_memoryconfig memconf;
++      struct acx111_ie_queueconfig queueconf;
++      unsigned long flags;
++      int i;
++      char memmap[0x34];
++      char rxconfig[0x8];
++      char fcserror[0x8];
++      char ratefallback[0x5];
++
++      if ( !(acx_debug & (L_IOCTL|L_DEBUG)) )
++              return OK;
++      /* using printk() since we checked debug flag already */
++
++      acx_sem_lock(adev);
++
++      if (!IS_ACX111(adev)) {
++              printk("acx111-specific function called "
++                      "with non-acx111 chip, aborting\n");
++              goto end_ok;
++      }
++
++      /* get Acx111 Memory Configuration */
++      memset(&memconf, 0, sizeof(memconf));
++      /* BTW, fails with 12 (Write only) error code.
++      ** Retained for easy testing of issue_cmd error handling :) */
++      printk ("Interrogating queue config\n");
++      acx_s_interrogate(adev, &memconf, ACX1xx_IE_QUEUE_CONFIG);
++      printk ("done with queue config\n");
++
++      /* get Acx111 Queue Configuration */
++      memset(&queueconf, 0, sizeof(queueconf));
++      printk ("Interrogating mem config options\n");
++      acx_s_interrogate(adev, &queueconf, ACX1xx_IE_MEMORY_CONFIG_OPTIONS);
++      printk ("done with mem config options\n");
++
++      /* get Acx111 Memory Map */
++      memset(memmap, 0, sizeof(memmap));
++      printk ("Interrogating mem map\n");
++      acx_s_interrogate(adev, &memmap, ACX1xx_IE_MEMORY_MAP);
++      printk ("done with mem map\n");
++
++      /* get Acx111 Rx Config */
++      memset(rxconfig, 0, sizeof(rxconfig));
++      printk ("Interrogating rxconfig\n");
++      acx_s_interrogate(adev, &rxconfig, ACX1xx_IE_RXCONFIG);
++      printk ("done with queue rxconfig\n");
++
++      /* get Acx111 fcs error count */
++      memset(fcserror, 0, sizeof(fcserror));
++      printk ("Interrogating fcs err count\n");
++      acx_s_interrogate(adev, &fcserror, ACX1xx_IE_FCS_ERROR_COUNT);
++      printk ("done with err count\n");
++
++      /* get Acx111 rate fallback */
++      memset(ratefallback, 0, sizeof(ratefallback));
++      printk ("Interrogating rate fallback\n");
++      acx_s_interrogate(adev, &ratefallback, ACX1xx_IE_RATE_FALLBACK);
++      printk ("done with rate fallback\n");
++
++      /* force occurrence of a beacon interrupt */
++      /* TODO: comment why is this necessary */
++      write_reg16(adev, IO_ACX_HINT_TRIG, HOST_INT_BEACON);
++
++      /* dump Acx111 Mem Configuration */
++      printk("dump mem config:\n"
++              "data read: %d, struct size: %d\n"
++              "Number of stations: %1X\n"
++              "Memory block size: %1X\n"
++              "tx/rx memory block allocation: %1X\n"
++              "count rx: %X / tx: %X queues\n"
++              "options %1X\n"
++              "fragmentation %1X\n"
++              "Rx Queue 1 Count Descriptors: %X\n"
++              "Rx Queue 1 Host Memory Start: %X\n"
++              "Tx Queue 1 Count Descriptors: %X\n"
++              "Tx Queue 1 Attributes: %X\n",
++              memconf.len, (int) sizeof(memconf),
++              memconf.no_of_stations,
++              memconf.memory_block_size,
++              memconf.tx_rx_memory_block_allocation,
++              memconf.count_rx_queues, memconf.count_tx_queues,
++              memconf.options,
++              memconf.fragmentation,
++              memconf.rx_queue1_count_descs,
++      acx2cpu(memconf.rx_queue1_host_rx_start),
++              memconf.tx_queue1_count_descs,
++              memconf.tx_queue1_attributes);
++
++      /* dump Acx111 Queue Configuration */
++      printk("dump queue head:\n"
++              "data read: %d, struct size: %d\n"
++              "tx_memory_block_address (from card): %X\n"
++              "rx_memory_block_address (from card): %X\n"
++              "rx1_queue address (from card): %X\n"
++              "tx1_queue address (from card): %X\n"
++              "tx1_queue attributes (from card): %X\n",
++              queueconf.len, (int) sizeof(queueconf),
++              queueconf.tx_memory_block_address,
++              queueconf.rx_memory_block_address,
++              queueconf.rx1_queue_address,
++              queueconf.tx1_queue_address,
++              queueconf.tx1_attributes);
++
++      /* dump Acx111 Mem Map */
++      printk("dump mem map:\n"
++              "data read: %d, struct size: %d\n"
++              "Code start: %X\n"
++              "Code end: %X\n"
++              "WEP default key start: %X\n"
++              "WEP default key end: %X\n"
++              "STA table start: %X\n"
++              "STA table end: %X\n"
++              "Packet template start: %X\n"
++              "Packet template end: %X\n"
++              "Queue memory start: %X\n"
++              "Queue memory end: %X\n"
++              "Packet memory pool start: %X\n"
++              "Packet memory pool end: %X\n"
++              "iobase: %p\n"
++              "iobase2: %p\n",
++              *((u16 *)&memmap[0x02]), (int) sizeof(memmap),
++              *((u32 *)&memmap[0x04]),
++              *((u32 *)&memmap[0x08]),
++              *((u32 *)&memmap[0x0C]),
++              *((u32 *)&memmap[0x10]),
++              *((u32 *)&memmap[0x14]),
++              *((u32 *)&memmap[0x18]),
++              *((u32 *)&memmap[0x1C]),
++              *((u32 *)&memmap[0x20]),
++              *((u32 *)&memmap[0x24]),
++              *((u32 *)&memmap[0x28]),
++              *((u32 *)&memmap[0x2C]),
++              *((u32 *)&memmap[0x30]),
++              adev->iobase,
++              adev->iobase2);
++
++      /* dump Acx111 Rx Config */
++      printk("dump rx config:\n"
++              "data read: %d, struct size: %d\n"
++              "rx config: %X\n"
++              "rx filter config: %X\n",
++              *((u16 *)&rxconfig[0x02]), (int) sizeof(rxconfig),
++              *((u16 *)&rxconfig[0x04]),
++              *((u16 *)&rxconfig[0x06]));
++
++      /* dump Acx111 fcs error */
++      printk("dump fcserror:\n"
++              "data read: %d, struct size: %d\n"
++              "fcserrors: %X\n",
++              *((u16 *)&fcserror[0x02]), (int) sizeof(fcserror),
++              *((u32 *)&fcserror[0x04]));
++
++      /* dump Acx111 rate fallback */
++      printk("dump rate fallback:\n"
++              "data read: %d, struct size: %d\n"
++              "ratefallback: %X\n",
++              *((u16 *)&ratefallback[0x02]), (int) sizeof(ratefallback),
++              *((u8 *)&ratefallback[0x04]));
++
++      /* protect against IRQ */
++      acx_lock(adev, flags);
++
++      /* dump acx111 internal rx descriptor ring buffer */
++      rxdesc = adev->rxdesc_start;
++
++      /* loop over complete receive pool */
++      if (rxdesc) for (i = 0; i < RX_CNT; i++) {
++              printk("\ndump internal rxdesc %d:\n"
++                      "mem pos %p\n"
++                      "next 0x%X\n"
++                      "acx mem pointer (dynamic) 0x%X\n"
++                      "CTL (dynamic) 0x%X\n"
++                      "Rate (dynamic) 0x%X\n"
++                      "RxStatus (dynamic) 0x%X\n"
++                      "Mod/Pre (dynamic) 0x%X\n",
++                      i,
++                      rxdesc,
++                      acx2cpu(rxdesc->pNextDesc),
++                      acx2cpu(rxdesc->ACXMemPtr),
++                      rxdesc->Ctl_8,
++                      rxdesc->rate,
++                      rxdesc->error,
++                      rxdesc->SNR);
++              rxdesc++;
++      }
++
++      /* dump host rx descriptor ring buffer */
++
++      rxhostdesc = adev->rxhostdesc_start;
++
++      /* loop over complete receive pool */
++      if (rxhostdesc) for (i = 0; i < RX_CNT; i++) {
++              printk("\ndump host rxdesc %d:\n"
++                      "mem pos %p\n"
++                      "buffer mem pos 0x%X\n"
++                      "buffer mem offset 0x%X\n"
++                      "CTL 0x%X\n"
++                      "Length 0x%X\n"
++                      "next 0x%X\n"
++                      "Status 0x%X\n",
++                      i,
++                      rxhostdesc,
++                      acx2cpu(rxhostdesc->data_phy),
++                      rxhostdesc->data_offset,
++                      le16_to_cpu(rxhostdesc->Ctl_16),
++                      le16_to_cpu(rxhostdesc->length),
++                      acx2cpu(rxhostdesc->desc_phy_next),
++                      rxhostdesc->Status);
++              rxhostdesc++;
++      }
++
++      /* dump acx111 internal tx descriptor ring buffer */
++      txdesc = adev->txdesc_start;
++
++      /* loop over complete transmit pool */
++      if (txdesc) for (i = 0; i < TX_CNT; i++) {
++              printk("\ndump internal txdesc %d:\n"
++                      "size 0x%X\n"
++                      "mem pos %p\n"
++                      "next 0x%X\n"
++                      "acx mem pointer (dynamic) 0x%X\n"
++                      "host mem pointer (dynamic) 0x%X\n"
++                      "length (dynamic) 0x%X\n"
++                      "CTL (dynamic) 0x%X\n"
++                      "CTL2 (dynamic) 0x%X\n"
++                      "Status (dynamic) 0x%X\n"
++                      "Rate (dynamic) 0x%X\n",
++                      i,
++                      (int) sizeof(struct txdesc),
++                      txdesc,
++                      acx2cpu(txdesc->pNextDesc),
++                      acx2cpu(txdesc->AcxMemPtr),
++                      acx2cpu(txdesc->HostMemPtr),
++                      le16_to_cpu(txdesc->total_length),
++                      txdesc->Ctl_8,
++                      txdesc->Ctl2_8, txdesc->error,
++                      txdesc->u.r1.rate);
++              txdesc = advance_txdesc(adev, txdesc, 1);
++      }
++
++      /* dump host tx descriptor ring buffer */
++
++      txhostdesc = adev->txhostdesc_start;
++
++      /* loop over complete host send pool */
++      if (txhostdesc) for (i = 0; i < TX_CNT * 2; i++) {
++              printk("\ndump host txdesc %d:\n"
++                      "mem pos %p\n"
++                      "buffer mem pos 0x%X\n"
++                      "buffer mem offset 0x%X\n"
++                      "CTL 0x%X\n"
++                      "Length 0x%X\n"
++                      "next 0x%X\n"
++                      "Status 0x%X\n",
++                      i,
++                      txhostdesc,
++                      acx2cpu(txhostdesc->data_phy),
++                      txhostdesc->data_offset,
++                      le16_to_cpu(txhostdesc->Ctl_16),
++                      le16_to_cpu(txhostdesc->length),
++                      acx2cpu(txhostdesc->desc_phy_next),
++                      le32_to_cpu(txhostdesc->Status));
++              txhostdesc++;
++      }
++
++      /* write_reg16(adev, 0xb4, 0x4); */
++
++      acx_unlock(adev, flags);
++end_ok:
++
++      acx_sem_unlock(adev);
++#endif /* ACX_DEBUG */
++      return OK;
++}
++
++
++/***********************************************************************
++*/
++int
++acx100mem_ioctl_set_phy_amp_bias(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      struct iw_param *vwrq,
++      char *extra)
++{
++      acx_device_t *adev = ndev2adev(ndev);
++      unsigned long flags;
++      u16 gpio_old;
++
++      if (!IS_ACX100(adev)) {
++              /* WARNING!!!
++               * Removing this check *might* damage
++               * hardware, since we're tweaking GPIOs here after all!!!
++               * You've been warned...
++               * WARNING!!! */
++              printk("acx: sorry, setting bias level for non-acx100 "
++                      "is not supported yet\n");
++              return OK;
++      }
++
++      if (*extra > 7) {
++              printk("acx: invalid bias parameter, range is 0-7\n");
++              return -EINVAL;
++      }
++
++      acx_sem_lock(adev);
++
++      /* Need to lock accesses to [IO_ACX_GPIO_OUT]:
++       * IRQ handler uses it to update LED */
++      acx_lock(adev, flags);
++      gpio_old = read_reg16(adev, IO_ACX_GPIO_OUT);
++      write_reg16(adev, IO_ACX_GPIO_OUT, (gpio_old & 0xf8ff) | ((u16)*extra << 8));
++      acx_unlock(adev, flags);
++
++      log(L_DEBUG, "gpio_old: 0x%04X\n", gpio_old);
++      printk("%s: PHY power amplifier bias: old:%d, new:%d\n",
++              ndev->name,
++              (gpio_old & 0x0700) >> 8, (unsigned char)*extra);
++
++      acx_sem_unlock(adev);
++
++      return OK;
++}
++
++/***************************************************************
++** acxmem_l_alloc_tx
++** Actually returns a txdesc_t* ptr
++**
++** FIXME: in case of fragments, should allocate multiple descrs
++** after figuring out how many we need and whether we still have
++** sufficiently many.
++*/
++tx_t*
++acxmem_l_alloc_tx(acx_device_t *adev)
++{
++      struct txdesc *txdesc;
++      unsigned head;
++      u8 ctl8;
++      static int txattempts = 0;
++
++      FN_ENTER;
++
++      if (unlikely(!adev->tx_free)) {
++              printk("acx: BUG: no free txdesc left\n");
++              /*
++               * Probably the ACX ignored a transmit attempt and now there's a packet
++               * sitting in the queue we think should be transmitting but the ACX doesn't
++               * know about.
++               * On the first pass, send the ACX a TxProc interrupt to try moving
++               * things along, and if that doesn't work (ie, we get called again) completely
++               * flush the transmit queue.
++               */
++              if (txattempts < 10) {
++                txattempts++;
++                printk ("acx: trying to wake up ACX\n");
++                write_reg16(adev, IO_ACX_INT_TRIG, INT_TRIG_TXPRC);
++                write_flush(adev);            }
++              else  {
++                txattempts = 0;
++                printk ("acx: flushing transmit queue.\n");
++                acxmem_l_clean_txdesc_emergency (adev);
++              }
++              txdesc = NULL;
++              goto end;
++      }
++
++      /*
++       * Make a quick check to see if there is transmit buffer space on
++       * the ACX.  This can't guarantee there is enough space for the packet
++       * since we don't yet know how big it is, but it will prevent at least some
++       * annoyances.
++       */
++      if (!adev->acx_txbuf_blocks_free) {
++        txdesc = NULL;
++        goto end;
++      }
++
++      head = adev->tx_head;
++      /*
++       * txdesc points to ACX memory
++       */
++      txdesc = get_txdesc(adev, head);
++      ctl8 = read_slavemem8 (adev, (u32) &(txdesc->Ctl_8));
++
++      /* 
++       * If we don't own the buffer (HOSTOWN) it is certainly not free; however,
++       * we may have previously thought we had enough memory to send
++       * a packet, allocated the buffer then gave up when we found not enough
++       * transmit buffer space on the ACX. In that case, HOSTOWN and
++       * ACXDONE will both be set.
++       */
++      if (unlikely(DESC_CTL_HOSTOWN != (ctl8 & DESC_CTL_HOSTOWN))) {
++              /* whoops, descr at current index is not free, so probably
++               * ring buffer already full */
++                printk("acx: BUG: tx_head:%d Ctl8:0x%02X - failed to find "
++                        "free txdesc\n", head, ctl8);
++              txdesc = NULL;
++              goto end;
++      }
++
++      /* Needed in case txdesc won't be eventually submitted for tx */
++      write_slavemem8 (adev, (u32) &(txdesc->Ctl_8), DESC_CTL_ACXDONE_HOSTOWN);
++
++      adev->tx_free--;
++      log(L_BUFT, "tx: got desc %u, %u remain\n",
++                      head, adev->tx_free);
++      /* Keep a few free descs between head and tail of tx ring.
++      ** It is not absolutely needed, just feels safer */
++      if (adev->tx_free < TX_STOP_QUEUE) {
++              log(L_BUF, "stop queue (%u tx desc left)\n",
++                              adev->tx_free);
++              acx_stop_queue(adev->ndev, NULL);
++      }
++
++      /* returning current descriptor, so advance to next free one */
++      adev->tx_head = (head + 1) % TX_CNT;
++end:
++      FN_EXIT0;
++
++      return (tx_t*)txdesc;
++}
++
++
++/***************************************************************
++** acxmem_l_dealloc_tx
++** Clears out a previously allocatedvoid acxmem_l_dealloc_tx(tx_t *tx_opaque);
++ transmit descriptor.  The ACX
++** can get confused if we skip transmit descriptors in the queue,
++** so when we don't need a descriptor return it to its original
++** state and move the queue head pointer back.
++**
++*/
++void
++acxmem_l_dealloc_tx(acx_device_t *adev, tx_t *tx_opaque)
++{
++  /*
++   * txdesc is the address of the descriptor on the ACX.
++   */
++  txdesc_t *txdesc = (txdesc_t*)tx_opaque;
++  txdesc_t tmptxdesc;
++  int index;
++
++  memset (&tmptxdesc, 0, sizeof(tmptxdesc));
++  tmptxdesc.Ctl_8 = DESC_CTL_HOSTOWN | DESC_CTL_FIRSTFRAG;
++  tmptxdesc.u.r1.rate = 0x0a;
++
++  /*
++   * Clear out all of the transmit descriptor except for the next pointer
++   */
++  copy_to_slavemem (adev, (u32) &(txdesc->HostMemPtr),
++                  (u8 *) &(tmptxdesc.HostMemPtr),
++                  sizeof (tmptxdesc) - sizeof(tmptxdesc.pNextDesc));
++  
++  /*
++   * This is only called immediately after we've allocated, so we should
++   * be able to set the head back to this descriptor.
++   */
++  index = ((u8*) txdesc - (u8*)adev->txdesc_start) / adev->txdesc_size;
++  printk ("acx_dealloc: moving head from %d to %d\n", adev->tx_head, index);
++  adev->tx_head = index;
++}
++
++
++/***********************************************************************
++*/
++void*
++acxmem_l_get_txbuf(acx_device_t *adev, tx_t* tx_opaque)
++{
++      return get_txhostdesc(adev, (txdesc_t*)tx_opaque)->data;
++}
++
++
++/***********************************************************************
++** acxmem_l_tx_data
++**
++** Can be called from IRQ (rx -> (AP bridging or mgmt response) -> tx).
++** Can be called from acx_i_start_xmit (data frames from net core).
++**
++** FIXME: in case of fragments, should loop over the number of
++** pre-allocated tx descrs, properly setting up transfer data and
++** CTL_xxx flags according to fragment number.
++*/
++void
++acxmem_update_queue_indicator (acx_device_t *adev, int txqueue)
++{
++#ifdef USING_MORE_THAN_ONE_TRANSMIT_QUEUE
++  u32 indicator;
++  unsigned long flags;
++  int count;
++
++  /*
++   * Can't handle an interrupt while we're fiddling with the ACX's lock,
++   * according to TI.  The ACX is supposed to hold fw_lock for at most
++   * 500ns.
++   */
++  local_irq_save (flags);
++
++  /*
++   * Wait for ACX to release the lock (at most 500ns).
++   */
++  count = 0;
++  while (read_slavemem16 (adev, (u32) &(adev->acx_queue_indicator->fw_lock))
++       && (count++ < 50)) {
++    ndelay (10);
++  }
++  if (count < 50) {
++
++    /*
++     * Take out the host lock - anything non-zero will work, so don't worry about
++     * be/le
++     */
++    write_slavemem16 (adev, (u32) &(adev->acx_queue_indicator->host_lock), 1);
++
++    /*
++     * Avoid a race condition
++     */
++    count = 0;
++    while (read_slavemem16 (adev, (u32) &(adev->acx_queue_indicator->fw_lock))
++         && (count++ < 50)) {
++      ndelay (10);
++    }
++
++    if (count < 50) {
++      /*
++       * Mark the queue active
++       */
++      indicator = read_slavemem32 (adev, (u32) &(adev->acx_queue_indicator->indicator));
++      indicator |= cpu_to_le32 (1 << txqueue);
++      write_slavemem32 (adev, (u32) &(adev->acx_queue_indicator->indicator), indicator);
++    }
++
++    /*
++     * Release the host lock
++     */
++    write_slavemem16 (adev, (u32) &(adev->acx_queue_indicator->host_lock), 0);
++
++  }
++
++  /*
++   * Restore interrupts
++   */
++  local_irq_restore (flags);
++#endif
++}
++
++void
++acxmem_l_tx_data(acx_device_t *adev, tx_t* tx_opaque, int len)
++{
++  /*
++   * txdesc is the address on the ACX
++   */
++      txdesc_t *txdesc = (txdesc_t*)tx_opaque;
++      txhostdesc_t *hostdesc1, *hostdesc2;
++      client_t *clt;
++      u16 rate_cur;
++      u8 Ctl_8, Ctl2_8;
++      u32 addr;
++
++      FN_ENTER;
++      /* fw doesn't tx such packets anyhow */
++      if (unlikely(len < WLAN_HDR_A3_LEN))
++              goto end;
++
++      hostdesc1 = get_txhostdesc(adev, txdesc);
++      /* modify flag status in separate variable to be able to write it back
++       * in one big swoop later (also in order to have less device memory
++       * accesses) */
++      Ctl_8 = read_slavemem8 (adev, (u32) &(txdesc->Ctl_8));
++      Ctl2_8 = 0; /* really need to init it to 0, not txdesc->Ctl2_8, it seems */
++
++      hostdesc2 = hostdesc1 + 1;
++
++      /* DON'T simply set Ctl field to 0 here globally,
++       * it needs to maintain a consistent flag status (those are state flags!!),
++       * otherwise it may lead to severe disruption. Only set or reset particular
++       * flags at the exact moment this is needed... */
++
++      /* let chip do RTS/CTS handshaking before sending
++       * in case packet size exceeds threshold */
++      if (len > adev->rts_threshold)
++              SET_BIT(Ctl2_8, DESC_CTL2_RTS);
++      else
++              CLEAR_BIT(Ctl2_8, DESC_CTL2_RTS);
++
++      switch (adev->mode) {
++      case ACX_MODE_0_ADHOC:
++      case ACX_MODE_3_AP:
++              clt = acx_l_sta_list_get(adev, ((wlan_hdr_t*)hostdesc1->data)->a1);
++              break;
++      case ACX_MODE_2_STA:
++              clt = adev->ap_client;
++              break;
++#if 0
++/* testing was done on acx111: */
++      case ACX_MODE_MONITOR:
++              SET_BIT(Ctl2_8, 0
++/* sends CTS to self before packet */
++                      + DESC_CTL2_SEQ         /* don't increase sequence field */
++/* not working (looks like good fcs is still added) */
++                      + DESC_CTL2_FCS         /* don't add the FCS */
++/* not tested */
++                      + DESC_CTL2_MORE_FRAG
++/* not tested */
++                      + DESC_CTL2_RETRY       /* don't increase retry field */
++/* not tested */
++                      + DESC_CTL2_POWER       /* don't increase power mgmt. field */
++/* no effect */
++                      + DESC_CTL2_WEP         /* encrypt this frame */
++/* not tested */
++                      + DESC_CTL2_DUR         /* don't increase duration field */
++                      );
++              /* fallthrough */
++#endif
++      default: /* ACX_MODE_OFF, ACX_MODE_MONITOR */
++              clt = NULL;
++              break;
++      }
++
++      rate_cur = clt ? clt->rate_cur : adev->rate_bcast;
++      if (unlikely(!rate_cur)) {
++              printk("acx: driver bug! bad ratemask\n");
++              goto end;
++      }
++
++      /* used in tx cleanup routine for auto rate and accounting: */
++      put_txcr(adev, txdesc, clt, rate_cur);
++
++      write_slavemem16 (adev, (u32) &(txdesc->total_length), cpu_to_le16(len));
++      hostdesc2->length = cpu_to_le16(len - WLAN_HDR_A3_LEN);
++      if (IS_ACX111(adev)) {
++              /* note that if !txdesc->do_auto, txrate->cur
++              ** has only one nonzero bit */
++              txdesc->u.r2.rate111 = cpu_to_le16(
++                      rate_cur
++                      /* WARNING: I was never able to make it work with prism54 AP.
++                      ** It was falling down to 1Mbit where shortpre is not applicable,
++                      ** and not working at all at "5,11 basic rates only" setting.
++                      ** I even didn't see tx packets in radio packet capture.
++                      ** Disabled for now --vda */
++                      /*| ((clt->shortpre && clt->cur!=RATE111_1) ? RATE111_SHORTPRE : 0) */
++                      );
++#ifdef TODO_FIGURE_OUT_WHEN_TO_SET_THIS
++                      /* should add this to rate111 above as necessary */
++                      | (clt->pbcc511 ? RATE111_PBCC511 : 0)
++#endif
++              hostdesc1->length = cpu_to_le16(len);
++      } else { /* ACX100 */
++              u8 rate_100 = clt ? clt->rate_100 : adev->rate_bcast100;
++              write_slavemem8 (adev, (u32) &(txdesc->u.r1.rate), rate_100);
++#ifdef TODO_FIGURE_OUT_WHEN_TO_SET_THIS
++              if (clt->pbcc511) {
++                      if (n == RATE100_5 || n == RATE100_11)
++                              n |= RATE100_PBCC511;
++              }
++
++              if (clt->shortpre && (clt->cur != RATE111_1))
++                      SET_BIT(Ctl_8, DESC_CTL_SHORT_PREAMBLE); /* set Short Preamble */
++#endif
++              /* set autodma and reclaim and 1st mpdu */
++              SET_BIT(Ctl_8, DESC_CTL_FIRSTFRAG);
++
++#if ACX_FRAGMENTATION
++              /* SET_BIT(Ctl2_8, DESC_CTL2_MORE_FRAG); cannot set it unconditionally, needs to be set for all non-last fragments */
++#endif
++              hostdesc1->length = cpu_to_le16(WLAN_HDR_A3_LEN);
++
++              /*
++               * Since we're not using autodma copy the packet data to the acx now.
++               * Even host descriptors point to the packet header, and the odd indexed
++               * descriptor following points to the packet data.
++               *
++               * The first step is to find free memory in the ACX transmit buffers.
++               * They don't necessarily map one to one with the transmit queue entries,
++               * so search through them starting just after the last one used.
++               */
++              addr = allocate_acx_txbuf_space (adev, len);
++              if (addr) {
++                chaincopy_to_slavemem (adev, addr, hostdesc1->data, len);
++              }
++              else {
++                /*
++                 * Bummer.  We thought we might have enough room in the transmit
++                 * buffers to send this packet, but it turns out we don't.  alloc_tx
++                 * has already marked this transmit descriptor as HOSTOWN and ACXDONE,
++                 * which means the ACX will hang when it gets to this descriptor unless
++                 * we do something about it.  Having a bubble in the transmit queue just
++                 * doesn't seem to work, so we have to reset this transmit queue entry's
++                 * state to its original value and back up our head pointer to point
++                 * back to this entry.
++                 */
++                hostdesc1->length = 0;
++                hostdesc2->length = 0;
++                write_slavemem16 (adev, (u32) &(txdesc->total_length), 0);
++                write_slavemem8 (adev, (u32) &(txdesc->Ctl_8), DESC_CTL_HOSTOWN | DESC_CTL_FIRSTFRAG);
++                adev->tx_head  = ((u8*) txdesc - (u8*) adev->txdesc_start) / adev->txdesc_size;
++                goto end;
++              }
++              /*
++               * Tell the ACX where the packet is.
++               */
++              write_slavemem32 (adev, (u32) &(txdesc->AcxMemPtr), addr);
++
++      }
++      /* don't need to clean ack/rts statistics here, already
++       * done on descr cleanup */
++
++      /* clears HOSTOWN and ACXDONE bits, thus telling that the descriptors
++       * are now owned by the acx100; do this as LAST operation */
++      CLEAR_BIT(Ctl_8, DESC_CTL_ACXDONE_HOSTOWN);
++      /* flush writes before we release hostdesc to the adapter here */
++      //wmb();
++
++      /* write back modified flags */
++      /*
++       * At this point Ctl_8 should just be FIRSTFRAG
++       */
++      write_slavemem8 (adev, (u32) &(txdesc->Ctl2_8),Ctl2_8);
++      write_slavemem8 (adev, (u32) &(txdesc->Ctl_8), Ctl_8);
++      /* unused: txdesc->tx_time = cpu_to_le32(jiffies); */
++
++      /*
++       * Update the queue indicator to say there's data on the first queue.
++       */
++      acxmem_update_queue_indicator (adev, 0);
++
++      /* flush writes before we tell the adapter that it's its turn now */
++      mmiowb();
++      write_reg16(adev, IO_ACX_INT_TRIG, INT_TRIG_TXPRC);
++      write_flush(adev);
++
++      /* log the packet content AFTER sending it,
++       * in order to not delay sending any further than absolutely needed
++       * Do separate logs for acx100/111 to have human-readable rates */
++      if (unlikely(acx_debug & (L_XFER|L_DATA))) {
++              u16 fc = ((wlan_hdr_t*)hostdesc1->data)->fc;
++              if (IS_ACX111(adev))
++                      printk("tx: pkt (%s): len %d "
++                              "rate %04X%s status %u\n",
++                              acx_get_packet_type_string(le16_to_cpu(fc)), len,
++                              le16_to_cpu(txdesc->u.r2.rate111),
++                              (le16_to_cpu(txdesc->u.r2.rate111) & RATE111_SHORTPRE) ? "(SPr)" : "",
++                              adev->status);
++              else
++                      printk("tx: pkt (%s): len %d rate %03u%s status %u\n",
++                              acx_get_packet_type_string(fc), len,
++                              read_slavemem8 (adev, (u32) &(txdesc->u.r1.rate)),
++                              (Ctl_8 & DESC_CTL_SHORT_PREAMBLE) ? "(SPr)" : "",
++                              adev->status);
++
++              if (acx_debug & L_DATA) {
++                      printk("tx: 802.11 [%d]: ", len);
++                      acx_dump_bytes(hostdesc1->data, len);
++              }
++      }
++end:
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++** acxmem_l_clean_txdesc
++**
++** This function resets the txdescs' status when the ACX100
++** signals the TX done IRQ (txdescs have been processed), starting with
++** the pool index of the descriptor which we would use next,
++** in order to make sure that we can be as fast as possible
++** in filling new txdescs.
++** Everytime we get called we know where the next packet to be cleaned is.
++*/
++
++#if !ACX_DEBUG
++static inline void log_txbuffer(const acx_device_t *adev) {}
++#else
++static void
++log_txbuffer(acx_device_t *adev)
++{
++      txdesc_t *txdesc;
++      int i;
++      u8 Ctl_8;
++
++      /* no FN_ENTER here, we don't want that */
++      /* no locks here, since it's entirely non-critical code */
++      txdesc = adev->txdesc_start;
++      if (unlikely(!txdesc)) return;
++      printk("tx: desc->Ctl8's:");
++      for (i = 0; i < TX_CNT; i++) {
++        Ctl_8 = read_slavemem8 (adev, (u32) &(txdesc->Ctl_8));
++              printk(" %02X", Ctl_8);
++              txdesc = advance_txdesc(adev, txdesc, 1);
++      }
++      printk("\n");
++}
++#endif
++
++
++static void
++handle_tx_error(acx_device_t *adev, u8 error, unsigned int finger)
++{
++      const char *err = "unknown error";
++
++      /* hmm, should we handle this as a mask
++       * of *several* bits?
++       * For now I think only caring about
++       * individual bits is ok... */
++      switch (error) {
++      case 0x01:
++              err = "no Tx due to error in other fragment";
++              adev->wstats.discard.fragment++;
++              break;
++      case 0x02:
++              err = "Tx aborted";
++              adev->stats.tx_aborted_errors++;
++              break;
++      case 0x04:
++              err = "Tx desc wrong parameters";
++              adev->wstats.discard.misc++;
++              break;
++      case 0x08:
++              err = "WEP key not found";
++              adev->wstats.discard.misc++;
++              break;
++      case 0x10:
++              err = "MSDU lifetime timeout? - try changing "
++                              "'iwconfig retry lifetime XXX'";
++              adev->wstats.discard.misc++;
++              break;
++      case 0x20:
++              err = "excessive Tx retries due to either distance "
++                      "too high or unable to Tx or Tx frame error - "
++                      "try changing 'iwconfig txpower XXX' or "
++                      "'sens'itivity or 'retry'";
++              adev->wstats.discard.retries++;
++              /* Tx error 0x20 also seems to occur on
++               * overheating, so I'm not sure whether we
++               * actually want to do aggressive radio recalibration,
++               * since people maybe won't notice then that their hardware
++               * is slowly getting cooked...
++               * Or is it still a safe long distance from utter
++               * radio non-functionality despite many radio recalibs
++               * to final destructive overheating of the hardware?
++               * In this case we really should do recalib here...
++               * I guess the only way to find out is to do a
++               * potentially fatal self-experiment :-\
++               * Or maybe only recalib in case we're using Tx
++               * rate auto (on errors switching to lower speed
++               * --> less heat?) or 802.11 power save mode?
++               *
++               * ok, just do it. */
++              if (++adev->retry_errors_msg_ratelimit % 4 == 0) {
++                      if (adev->retry_errors_msg_ratelimit <= 20) {
++                              printk("%s: several excessive Tx "
++                                      "retry errors occurred, attempting "
++                                      "to recalibrate radio. Radio "
++                                      "drift might be caused by increasing "
++                                      "card temperature, please check the card "
++                                      "before it's too late!\n",
++                                      adev->ndev->name);
++                              if (adev->retry_errors_msg_ratelimit == 20)
++                                      printk("disabling above message\n");
++                      }
++
++                      acx_schedule_task(adev, ACX_AFTER_IRQ_CMD_RADIO_RECALIB);
++              }
++              break;
++      case 0x40:
++              err = "Tx buffer overflow";
++              adev->stats.tx_fifo_errors++;
++              break;
++      case 0x80:
++              err = "DMA error";
++              adev->wstats.discard.misc++;
++              break;
++      }
++      adev->stats.tx_errors++;
++      if (adev->stats.tx_errors <= 20)
++              printk("%s: tx error 0x%02X, buf %02u! (%s)\n",
++                              adev->ndev->name, error, finger, err);
++      else
++              printk("%s: tx error 0x%02X, buf %02u!\n",
++                              adev->ndev->name, error, finger);
++}
++
++
++unsigned int
++acxmem_l_clean_txdesc(acx_device_t *adev)
++{
++      txdesc_t *txdesc;
++      unsigned finger;
++      int num_cleaned;
++      u16 r111;
++      u8 error, ack_failures, rts_failures, rts_ok, r100, Ctl_8;
++      u32 acxmem;
++      txdesc_t tmptxdesc;
++
++      FN_ENTER;
++
++      /*
++       * Set up a template descriptor for re-initialization.  The only
++       * things that get set are Ctl_8 and the rate, and the rate defaults
++       * to 1Mbps.
++       */
++      memset (&tmptxdesc, 0, sizeof (tmptxdesc));
++      tmptxdesc.Ctl_8 = DESC_CTL_HOSTOWN | DESC_CTL_FIRSTFRAG;
++      tmptxdesc.u.r1.rate = 0x0a;
++
++      if (unlikely(acx_debug & L_DEBUG))
++              log_txbuffer(adev);
++
++      log(L_BUFT, "tx: cleaning up bufs from %u\n", adev->tx_tail);
++
++      /* We know first descr which is not free yet. We advance it as far
++      ** as we see correct bits set in following descs (if next desc
++      ** is NOT free, we shouldn't advance at all). We know that in
++      ** front of tx_tail may be "holes" with isolated free descs.
++      ** We will catch up when all intermediate descs will be freed also */
++
++      finger = adev->tx_tail;
++      num_cleaned = 0;
++      while (likely(finger != adev->tx_head)) {
++              txdesc = get_txdesc(adev, finger);
++
++              /* If we allocated txdesc on tx path but then decided
++              ** to NOT use it, then it will be left as a free "bubble"
++              ** in the "allocated for tx" part of the ring.
++              ** We may meet it on the next ring pass here. */
++
++              /* stop if not marked as "tx finished" and "host owned" */
++              Ctl_8 = read_slavemem8 (adev, (u32) &(txdesc->Ctl_8));
++              if ((Ctl_8 & DESC_CTL_ACXDONE_HOSTOWN)
++                                      != DESC_CTL_ACXDONE_HOSTOWN) {
++                      if (unlikely(!num_cleaned)) { /* maybe remove completely */
++                              log(L_BUFT, "clean_txdesc: tail isn't free. "
++                                      "tail:%d head:%d\n",
++                                      adev->tx_tail, adev->tx_head);
++                      }
++                      break;
++              }
++
++              /* remember desc values... */
++              error = read_slavemem8 (adev, (u32) &(txdesc->error));
++              ack_failures = read_slavemem8 (adev, (u32) &(txdesc->ack_failures));
++              rts_failures = read_slavemem8 (adev, (u32) &(txdesc->u.rts.rts_failures));
++              rts_ok = read_slavemem8 (adev, (u32) &(txdesc->u.rts.rts_ok));
++              r100 = read_slavemem8 (adev, (u32) &(txdesc->u.r1.rate));
++              r111 = le16_to_cpu(read_slavemem16 (adev, (u32) &(txdesc->u.r2.rate111)));
++
++              /* need to check for certain error conditions before we
++               * clean the descriptor: we still need valid descr data here */
++              if (unlikely(0x30 & error)) {
++                      /* only send IWEVTXDROP in case of retry or lifetime exceeded;
++                       * all other errors mean we screwed up locally */
++                      union iwreq_data wrqu;
++                      wlan_hdr_t *hdr;
++                      txhostdesc_t *hostdesc;
++
++                      hostdesc = get_txhostdesc(adev, txdesc);
++                      hdr = (wlan_hdr_t *)hostdesc->data;
++                      MAC_COPY(wrqu.addr.sa_data, hdr->a1);
++                      wireless_send_event(adev->ndev, IWEVTXDROP, &wrqu, NULL);
++              }
++
++              /*
++               * Free up the transmit data buffers
++               */
++              acxmem = read_slavemem32 (adev, (u32) &(txdesc->AcxMemPtr));
++              if (acxmem) {
++                reclaim_acx_txbuf_space (adev, acxmem);
++              }
++
++              /* ...and free the desc by clearing all the fields 
++                 except the next pointer */
++              copy_to_slavemem (adev,
++                                (u32) &(txdesc->HostMemPtr), 
++                                (u8 *) &(tmptxdesc.HostMemPtr),
++                                sizeof (tmptxdesc) - sizeof(tmptxdesc.pNextDesc)
++                                );
++
++              adev->tx_free++;
++              num_cleaned++;
++
++              if ((adev->tx_free >= TX_START_QUEUE)
++               && (adev->status == ACX_STATUS_4_ASSOCIATED)
++               && (acx_queue_stopped(adev->ndev))
++              ) {
++                      log(L_BUF, "tx: wake queue (avail. Tx desc %u)\n",
++                                      adev->tx_free);
++                      acx_wake_queue(adev->ndev, NULL);
++              }
++
++              /* do error checking, rate handling and logging
++               * AFTER having done the work, it's faster */
++
++              /* do rate handling */
++              if (adev->rate_auto) {
++                      struct client *clt = get_txc(adev, txdesc);
++                      if (clt) {
++                              u16 cur = get_txr(adev, txdesc);
++                              if (clt->rate_cur == cur) {
++                                      acx_l_handle_txrate_auto(adev, clt,
++                                              cur, /* intended rate */
++                                              r100, r111, /* actually used rate */
++                                              (error & 0x30), /* was there an error? */
++                                              TX_CNT + TX_CLEAN_BACKLOG - adev->tx_free);
++                              }
++                      }
++              }
++
++              if (unlikely(error))
++                      handle_tx_error(adev, error, finger);
++
++              if (IS_ACX111(adev))
++                      log(L_BUFT, "tx: cleaned %u: !ACK=%u !RTS=%u RTS=%u r111=%04X\n",
++                              finger, ack_failures, rts_failures, rts_ok, r111);
++              else
++                      log(L_BUFT, "tx: cleaned %u: !ACK=%u !RTS=%u RTS=%u rate=%u\n",
++                              finger, ack_failures, rts_failures, rts_ok, r100);
++
++              /* update pointer for descr to be cleaned next */
++              finger = (finger + 1) % TX_CNT;
++      }
++
++      /* remember last position */
++      adev->tx_tail = finger;
++/* end: */
++      FN_EXIT1(num_cleaned);
++      return num_cleaned;
++}
++
++/* clean *all* Tx descriptors, and regardless of their previous state.
++ * Used for brute-force reset handling. */
++void
++acxmem_l_clean_txdesc_emergency(acx_device_t *adev)
++{
++      txdesc_t *txdesc;
++      int i;
++      u32 acxmem;
++
++      FN_ENTER;
++
++      for (i = 0; i < TX_CNT; i++) {
++              txdesc = get_txdesc(adev, i);
++
++              /* free it */
++              write_slavemem8 (adev, (u32) &(txdesc->ack_failures), 0);
++              write_slavemem8 (adev, (u32) &(txdesc->u.rts.rts_failures), 0);
++              write_slavemem8 (adev, (u32) &(txdesc->u.rts.rts_ok), 0);
++              write_slavemem8 (adev, (u32) &(txdesc->error), 0);
++              write_slavemem8 (adev, (u32) &(txdesc->Ctl_8), DESC_CTL_HOSTOWN);
++
++              /*
++               * Clean up the memory allocated on the ACX for this transmit descriptor.
++               */
++              acxmem = read_slavemem32 (adev, (u32) &(txdesc->AcxMemPtr));
++              if (acxmem) {
++                reclaim_acx_txbuf_space (adev, acxmem);
++              }               
++              
++              write_slavemem32 (adev, (u32) &(txdesc->AcxMemPtr), 0);
++      }
++
++      adev->tx_free = TX_CNT;
++
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++** acxmem_s_create_tx_host_desc_queue
++*/
++
++static void*
++allocate(acx_device_t *adev, size_t size, dma_addr_t *phy, const char *msg)
++{
++      void *ptr;
++        ptr = kmalloc (size, GFP_KERNEL);
++      /*
++       * The ACX can't use the physical address, so we'll have to fake it
++       * later and it might be handy to have the virtual address.
++       */
++      *phy = (dma_addr_t) NULL;
++
++      if (ptr) {
++              log(L_DEBUG, "%s sz=%d adr=0x%p phy=0x%08llx\n",
++                              msg, (int)size, ptr, (unsigned long long)*phy);
++              memset(ptr, 0, size);
++              return ptr;
++      }
++      printk(KERN_ERR "acx: %s allocation FAILED (%d bytes)\n",
++                                      msg, (int)size);
++      return NULL;
++}
++
++
++/*
++ * In the generic slave memory access mode, most of the stuff in
++ * the txhostdesc_t is unused.  It's only here because the rest of
++ * the ACX driver expects it to be since the PCI version uses indirect
++ * host memory organization with DMA.  Since we're not using DMA the
++ * only use we have for the host descriptors is to store the packets
++ * on the way out.
++ */
++static int
++acxmem_s_create_tx_host_desc_queue(acx_device_t *adev)
++{
++      txhostdesc_t *hostdesc;
++      u8 *txbuf;
++      int i;
++
++      FN_ENTER;
++
++      /* allocate TX buffer */
++      adev->txbuf_area_size = TX_CNT * WLAN_A4FR_MAXLEN_WEP_FCS;
++
++      adev->txbuf_start = allocate(adev, adev->txbuf_area_size,
++                                   &adev->txbuf_startphy, "txbuf_start");
++      if (!adev->txbuf_start)
++        goto fail;
++
++      /* allocate the TX host descriptor queue pool */
++      adev->txhostdesc_area_size = TX_CNT * 2*sizeof(*hostdesc);
++
++      adev->txhostdesc_start = allocate(adev, adev->txhostdesc_area_size,
++                                        &adev->txhostdesc_startphy, "txhostdesc_start");
++      if (!adev->txhostdesc_start)
++        goto fail;
++
++      /* check for proper alignment of TX host descriptor pool */
++      if ((long) adev->txhostdesc_start & 3) {
++              printk("acx: driver bug: dma alloc returns unaligned address\n");
++              goto fail;
++      }
++
++      hostdesc = adev->txhostdesc_start;
++      txbuf = adev->txbuf_start;
++
++#if 0
++/* Each tx buffer is accessed by hardware via
++** txdesc -> txhostdesc(s) -> txbuffer(s).
++** We use only one txhostdesc per txdesc, but it looks like
++** acx111 is buggy: it accesses second txhostdesc
++** (via hostdesc.desc_phy_next field) even if
++** txdesc->length == hostdesc->length and thus
++** entire packet was placed into first txhostdesc.
++** Due to this bug acx111 hangs unless second txhostdesc
++** has le16_to_cpu(hostdesc.length) = 3 (or larger)
++** Storing NULL into hostdesc.desc_phy_next
++** doesn't seem to help.
++**
++** Update: although it worked on Xterasys XN-2522g
++** with len=3 trick, WG311v2 is even more bogus, doesn't work.
++** Keeping this code (#ifdef'ed out) for documentational purposes.
++*/
++      for (i = 0; i < TX_CNT*2; i++) {
++              hostdesc_phy += sizeof(*hostdesc);
++              if (!(i & 1)) {
++                      hostdesc->data_phy = cpu2acx(txbuf_phy);
++                      /* hostdesc->data_offset = ... */
++                      /* hostdesc->reserved = ... */
++                      hostdesc->Ctl_16 = cpu_to_le16(DESC_CTL_HOSTOWN);
++                      /* hostdesc->length = ... */
++                      hostdesc->desc_phy_next = cpu2acx(hostdesc_phy);
++                      hostdesc->pNext = ptr2acx(NULL);
++                      /* hostdesc->Status = ... */
++                      /* below: non-hardware fields */
++                      hostdesc->data = txbuf;
++
++                      txbuf += WLAN_A4FR_MAXLEN_WEP_FCS;
++                      txbuf_phy += WLAN_A4FR_MAXLEN_WEP_FCS;
++              } else {
++                      /* hostdesc->data_phy = ... */
++                      /* hostdesc->data_offset = ... */
++                      /* hostdesc->reserved = ... */
++                      /* hostdesc->Ctl_16 = ... */
++                      hostdesc->length = cpu_to_le16(3); /* bug workaround */
++                      /* hostdesc->desc_phy_next = ... */
++                      /* hostdesc->pNext = ... */
++                      /* hostdesc->Status = ... */
++                      /* below: non-hardware fields */
++                      /* hostdesc->data = ... */
++              }
++              hostdesc++;
++      }
++#endif
++/* We initialize two hostdescs so that they point to adjacent
++** memory areas. Thus txbuf is really just a contiguous memory area */
++      for (i = 0; i < TX_CNT*2; i++) {
++              /* ->data is a non-hardware field: */
++              hostdesc->data = txbuf;
++
++              if (!(i & 1)) {
++                      txbuf += WLAN_HDR_A3_LEN;
++              } else {
++                      txbuf += WLAN_A4FR_MAXLEN_WEP_FCS - WLAN_HDR_A3_LEN;
++              }
++              hostdesc++;
++      }
++      hostdesc--;
++
++      FN_EXIT1(OK);
++      return OK;
++fail:
++      printk("acx: create_tx_host_desc_queue FAILED\n");
++      /* dealloc will be done by free function on error case */
++      FN_EXIT1(NOT_OK);
++      return NOT_OK;
++}
++
++
++/***************************************************************
++** acxmem_s_create_rx_host_desc_queue
++*/
++/* the whole size of a data buffer (header plus data body)
++ * plus 32 bytes safety offset at the end */
++#define RX_BUFFER_SIZE (sizeof(rxbuffer_t) + 32)
++
++static int
++acxmem_s_create_rx_host_desc_queue(acx_device_t *adev)
++{
++      rxhostdesc_t *hostdesc;
++      rxbuffer_t *rxbuf;
++      int i;
++
++      FN_ENTER;
++
++      /* allocate the RX host descriptor queue pool */
++      adev->rxhostdesc_area_size = RX_CNT * sizeof(*hostdesc);
++
++      adev->rxhostdesc_start = allocate(adev, adev->rxhostdesc_area_size,
++                                        &adev->rxhostdesc_startphy, "rxhostdesc_start");
++      if (!adev->rxhostdesc_start)
++        goto fail;
++
++      /* check for proper alignment of RX host descriptor pool */
++      if ((long) adev->rxhostdesc_start & 3) {
++              printk("acx: driver bug: dma alloc returns unaligned address\n");
++              goto fail;
++      }
++
++      /* allocate Rx buffer pool which will be used by the acx
++       * to store the whole content of the received frames in it */
++      adev->rxbuf_area_size = RX_CNT * RX_BUFFER_SIZE;
++
++      adev->rxbuf_start = allocate(adev, adev->rxbuf_area_size,
++                                   &adev->rxbuf_startphy, "rxbuf_start");
++      if (!adev->rxbuf_start)
++        goto fail;
++
++      rxbuf = adev->rxbuf_start;
++      hostdesc = adev->rxhostdesc_start;
++
++      /* don't make any popular C programming pointer arithmetic mistakes
++       * here, otherwise I'll kill you...
++       * (and don't dare asking me why I'm warning you about that...) */
++      for (i = 0; i < RX_CNT; i++) {
++              hostdesc->data = rxbuf;
++              hostdesc->length = cpu_to_le16(RX_BUFFER_SIZE);
++              rxbuf++;
++              hostdesc++;
++      }
++      hostdesc--;
++      FN_EXIT1(OK);
++      return OK;
++fail:
++      printk("acx: create_rx_host_desc_queue FAILED\n");
++      /* dealloc will be done by free function on error case */
++      FN_EXIT1(NOT_OK);
++      return NOT_OK;
++}
++
++
++/***************************************************************
++** acxmem_s_create_hostdesc_queues
++*/
++int
++acxmem_s_create_hostdesc_queues(acx_device_t *adev)
++{
++      int result;
++      result = acxmem_s_create_tx_host_desc_queue(adev);
++      if (OK != result) return result;
++      result = acxmem_s_create_rx_host_desc_queue(adev);
++      return result;
++}
++
++
++/***************************************************************
++** acxmem_create_tx_desc_queue
++*/
++static void
++acxmem_create_tx_desc_queue(acx_device_t *adev, u32 tx_queue_start)
++{
++      txdesc_t *txdesc;
++      u32 clr;
++      int i;
++
++      FN_ENTER;
++
++      if (IS_ACX100(adev))
++              adev->txdesc_size = sizeof(*txdesc);
++      else
++              /* the acx111 txdesc is 4 bytes larger */
++              adev->txdesc_size = sizeof(*txdesc) + 4;
++
++      /*
++       * This refers to an ACX address, not one of ours
++       */
++      adev->txdesc_start = (txdesc_t *) tx_queue_start;
++
++      log(L_DEBUG, "adev->txdesc_start=%p\n",
++                      adev->txdesc_start);
++
++      adev->tx_free = TX_CNT;
++      /* done by memset: adev->tx_head = 0; */
++      /* done by memset: adev->tx_tail = 0; */
++      txdesc = adev->txdesc_start;
++
++      if (IS_ACX111(adev)) {
++              /* ACX111 has a preinitialized Tx buffer! */
++              /* loop over whole send pool */
++              /* FIXME: do we have to do the hostmemptr stuff here?? */
++              for (i = 0; i < TX_CNT; i++) {
++                      txdesc->Ctl_8 = DESC_CTL_HOSTOWN;
++                      /* reserve two (hdr desc and payload desc) */
++                      txdesc = advance_txdesc(adev, txdesc, 1);
++              }
++      } else {
++              /* ACX100 Tx buffer needs to be initialized by us */
++              /* clear whole send pool. sizeof is safe here (we are acx100) */
++
++              /*
++               * adev->txdesc_start refers to device memory, so we can't write
++               * directly to it.
++               */
++              clr = (u32) adev->txdesc_start;
++              while (clr < (u32) adev->txdesc_start + (TX_CNT * sizeof(*txdesc))) {
++                write_slavemem32 (adev, clr, 0);
++                clr += 4;
++              }
++
++              /* loop over whole send pool */
++              for (i = 0; i < TX_CNT; i++) {
++                      log(L_DEBUG, "configure card tx descriptor: 0x%p, "
++                              "size: 0x%X\n", txdesc, adev->txdesc_size);
++
++                      /* initialise ctl */
++                      /*
++                       * No auto DMA here
++                       */
++                      write_slavemem8 (adev, (u32) &(txdesc->Ctl_8),
++                                      (u8) (DESC_CTL_HOSTOWN | DESC_CTL_FIRSTFRAG));
++                      /* done by memset(0): txdesc->Ctl2_8 = 0; */
++
++                      /* point to next txdesc */
++                      write_slavemem32 (adev, (u32) &(txdesc->pNextDesc),
++                                        (u32) cpu_to_le32 ((u8 *) txdesc + adev->txdesc_size));
++
++                      /* go to the next one */
++                      /* ++ is safe here (we are acx100) */
++                      txdesc++;
++              }
++              /* go back to the last one */
++              txdesc--;
++              /* and point to the first making it a ring buffer */
++              write_slavemem32 (adev, (u32) &(txdesc->pNextDesc),
++                                (u32) cpu_to_le32 (tx_queue_start));
++      }
++      FN_EXIT0;
++}
++
++
++/***************************************************************
++** acxmem_create_rx_desc_queue
++*/
++static void
++acxmem_create_rx_desc_queue(acx_device_t *adev, u32 rx_queue_start)
++{
++      rxdesc_t *rxdesc;
++      u32 mem_offs;
++      int i;
++
++      FN_ENTER;
++
++      /* done by memset: adev->rx_tail = 0; */
++
++      /* ACX111 doesn't need any further config: preconfigures itself.
++       * Simply print ring buffer for debugging */
++      if (IS_ACX111(adev)) {
++              /* rxdesc_start already set here */
++
++              adev->rxdesc_start = (rxdesc_t *) rx_queue_start;
++
++              rxdesc = adev->rxdesc_start;
++              for (i = 0; i < RX_CNT; i++) {
++                      log(L_DEBUG, "rx descriptor %d @ 0x%p\n", i, rxdesc);
++                      rxdesc = adev->rxdesc_start = (rxdesc_t *)
++                        acx2cpu(rxdesc->pNextDesc);
++              }
++      } else {
++              /* we didn't pre-calculate rxdesc_start in case of ACX100 */
++              /* rxdesc_start should be right AFTER Tx pool */
++              adev->rxdesc_start = (rxdesc_t *)
++                      ((u8 *) adev->txdesc_start + (TX_CNT * sizeof(txdesc_t)));
++              /* NB: sizeof(txdesc_t) above is valid because we know
++              ** we are in if (acx100) block. Beware of cut-n-pasting elsewhere!
++              ** acx111's txdesc is larger! */
++
++              mem_offs = (u32) adev->rxdesc_start;
++              while (mem_offs < (u32) adev->rxdesc_start + (RX_CNT * sizeof (*rxdesc))) {
++                write_slavemem32 (adev, mem_offs, 0);
++                mem_offs += 4;
++              }
++
++              /* loop over whole receive pool */
++              rxdesc = adev->rxdesc_start;
++              for (i = 0; i < RX_CNT; i++) {
++                      log(L_DEBUG, "rx descriptor @ 0x%p\n", rxdesc);
++                      /* point to next rxdesc */
++                      write_slavemem32 (adev, (u32) &(rxdesc->pNextDesc),
++                                        (u32) cpu_to_le32 ((u8 *) rxdesc + sizeof(*rxdesc)));
++                      /* go to the next one */
++                      rxdesc++;
++              }
++              /* go to the last one */
++              rxdesc--;
++
++              /* and point to the first making it a ring buffer */
++              write_slavemem32 (adev, (u32) &(rxdesc->pNextDesc),
++                                (u32) cpu_to_le32 (rx_queue_start));
++      }
++      FN_EXIT0;
++}
++
++
++/***************************************************************
++** acxmem_create_desc_queues
++*/
++void
++acxmem_create_desc_queues(acx_device_t *adev, u32 tx_queue_start, u32 rx_queue_start)
++{
++  u32 *p;
++  int i;
++
++      acxmem_create_tx_desc_queue(adev, tx_queue_start);
++      acxmem_create_rx_desc_queue(adev, rx_queue_start);
++      p = (u32 *) adev->acx_queue_indicator;
++      for (i = 0; i < 4; i++) {
++        write_slavemem32 (adev, (u32) p, 0);
++        p++;
++      }
++}
++
++
++/***************************************************************
++** acxmem_s_proc_diag_output
++*/
++char*
++acxmem_s_proc_diag_output(char *p, acx_device_t *adev)
++{
++      const char *rtl, *thd, *ttl;
++      txdesc_t *txdesc;
++      u8 Ctl_8;
++      rxdesc_t *rxdesc;
++      int i;
++      u32 tmp;
++      txdesc_t txd;
++      u8 buf[0x200];
++      int j, k;
++
++      FN_ENTER;
++
++#if DUMP_MEM_DURING_DIAG > 0
++      dump_acxmem (adev, 0, 0x10000);
++      panic ("dump finished");
++#endif
++      
++      p += sprintf(p, "** Rx buf **\n");
++      rxdesc = adev->rxdesc_start;
++      if (rxdesc) for (i = 0; i < RX_CNT; i++) {
++              rtl = (i == adev->rx_tail) ? " [tail]" : "";
++              Ctl_8 = read_slavemem8 (adev, (u32) &(rxdesc->Ctl_8));
++              if (Ctl_8 & DESC_CTL_HOSTOWN)
++                      p += sprintf(p, "%02u (%02x) FULL%s\n", i, Ctl_8, rtl);
++              else
++                      p += sprintf(p, "%02u (%02x) empty%s\n", i, Ctl_8, rtl);
++              rxdesc++;
++      }
++      p += sprintf(p, "** Tx buf (free %d, Linux netqueue %s) **\n", adev->tx_free,
++                              acx_queue_stopped(adev->ndev) ? "STOPPED" : "running");
++      
++      p += sprintf(p, "** Tx buf %d blocks total, %d available, free list head %04x\n",
++                   adev->acx_txbuf_numblocks, adev->acx_txbuf_blocks_free, adev->acx_txbuf_free);
++      txdesc = adev->txdesc_start;
++      if (txdesc) {
++        for (i = 0; i < TX_CNT; i++) {
++          thd = (i == adev->tx_head) ? " [head]" : "";
++          ttl = (i == adev->tx_tail) ? " [tail]" : "";
++          copy_from_slavemem (adev, (u8 *) &txd, (u32) txdesc, sizeof (txd));
++          Ctl_8 = read_slavemem8 (adev, (u32) &(txdesc->Ctl_8));
++          if (Ctl_8 & DESC_CTL_ACXDONE)
++            p += sprintf(p, "%02u ready to free (%02X)%s%s", i, Ctl_8, thd, ttl);
++          else if (Ctl_8 & DESC_CTL_HOSTOWN)
++            p += sprintf(p, "%02u available     (%02X)%s%s", i, Ctl_8, thd, ttl);
++          else
++            p += sprintf(p, "%02u busy          (%02X)%s%s", i, Ctl_8, thd, ttl);
++          tmp = read_slavemem32 (adev, (u32) &(txdesc->AcxMemPtr));
++          if (tmp) {
++            p += sprintf (p, " %04x", tmp);
++            while ((tmp = read_slavemem32 (adev, (u32) tmp)) != 0x02000000) {
++              tmp <<= 5;
++              p += sprintf (p, " %04x", tmp);
++            }
++          }
++          p += sprintf (p, "\n");
++          p += sprintf (p, "  %04x: %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %02x %02x %02x %02x\n"
++                           "%02x %02x %02x %02x %04x\n",
++                        (u32) txdesc,
++                        txd.pNextDesc.v, txd.HostMemPtr.v, txd.AcxMemPtr.v, txd.tx_time,
++                        txd.total_length, txd.Reserved,
++                        txd.dummy[0], txd.dummy[1], txd.dummy[2], txd.dummy[3],
++                        txd.Ctl_8, txd.Ctl2_8, txd.error, txd.ack_failures,
++                        txd.u.rts.rts_failures, txd.u.rts.rts_ok, txd.u.r1.rate, txd.u.r1.queue_ctrl,
++                        txd.queue_info
++                        );
++          if (txd.AcxMemPtr.v) {
++            copy_from_slavemem (adev, buf, txd.AcxMemPtr.v, sizeof (buf));
++            for (j = 0; (j < txd.total_length) && (j<(sizeof(buf)-4)); j+=16) {
++              p += sprintf (p, "    ");
++              for (k = 0; (k < 16) && (j+k < txd.total_length); k++) {
++                p += sprintf (p, " %02x", buf[j+k+4]);
++              }
++              p += sprintf (p, "\n");
++            }
++          }
++          txdesc = advance_txdesc(adev, txdesc, 1);
++        }
++      }
++      
++      p += sprintf(p,
++              "\n"
++              "** Generic slave data **\n"
++                "irq_mask 0x%04x irq_status 0x%04x irq on acx 0x%04x\n"
++              "txbuf_start 0x%p, txbuf_area_size %u\n"
++              "txdesc_size %u, txdesc_start 0x%p\n"
++              "txhostdesc_start 0x%p, txhostdesc_area_size %u\n"
++              "txbuf start 0x%04x, txbuf size %d\n"
++              "rxdesc_start 0x%p\n"
++              "rxhostdesc_start 0x%p, rxhostdesc_area_size %u\n"
++              "rxbuf_start 0x%p, rxbuf_area_size %u\n",
++              adev->irq_mask, adev->irq_status, read_reg32(adev, IO_ACX_IRQ_STATUS_NON_DES),
++              adev->txbuf_start, adev->txbuf_area_size,
++              adev->txdesc_size, adev->txdesc_start,
++              adev->txhostdesc_start, adev->txhostdesc_area_size,
++                adev->acx_txbuf_start, adev->acx_txbuf_numblocks * adev->memblocksize,
++              adev->rxdesc_start,
++              adev->rxhostdesc_start, adev->rxhostdesc_area_size,
++              adev->rxbuf_start, adev->rxbuf_area_size);
++      FN_EXIT0;
++      return p;
++}
++
++
++/***********************************************************************
++*/
++int
++acxmem_proc_eeprom_output(char *buf, acx_device_t *adev)
++{
++      char *p = buf;
++      int i;
++
++      FN_ENTER;
++
++      for (i = 0; i < 0x400; i++) {
++              acxmem_read_eeprom_byte(adev, i, p++);
++      }
++
++      FN_EXIT1(p - buf);
++      return p - buf;
++}
++
++
++/***********************************************************************
++*/
++void
++acxmem_set_interrupt_mask(acx_device_t *adev)
++{
++      if (IS_ACX111(adev)) {
++              adev->irq_mask = (u16) ~(0
++                              | HOST_INT_RX_DATA       
++                              | HOST_INT_TX_COMPLETE
++                              /* | HOST_INT_TX_XFER        */
++                              /* | HOST_INT_RX_COMPLETE    */
++                              /* | HOST_INT_DTIM           */
++                              /* | HOST_INT_BEACON         */
++                              /* | HOST_INT_TIMER          */
++                              /* | HOST_INT_KEY_NOT_FOUND  */
++                              | HOST_INT_IV_ICV_FAILURE
++                              | HOST_INT_CMD_COMPLETE
++                              | HOST_INT_INFO
++                              | HOST_INT_OVERFLOW    
++                              /* | HOST_INT_PROCESS_ERROR  */
++                              | HOST_INT_SCAN_COMPLETE
++                              | HOST_INT_FCS_THRESHOLD
++                              | HOST_INT_UNKNOWN
++                              );
++              /* Or else acx100 won't signal cmd completion, right? */
++              adev->irq_mask_off = (u16)~( HOST_INT_CMD_COMPLETE ); /* 0xfdff */
++      } else {
++              adev->irq_mask = (u16) ~(0
++                              | HOST_INT_RX_DATA 
++                              | HOST_INT_TX_COMPLETE
++                              /* | HOST_INT_TX_XFER        */
++                              /* | HOST_INT_RX_COMPLETE    */
++                              /* | HOST_INT_DTIM           */
++                              /* | HOST_INT_BEACON         */
++                              /* | HOST_INT_TIMER          */
++                              /* | HOST_INT_KEY_NOT_FOUND  */
++                              /* | HOST_INT_IV_ICV_FAILURE */
++                              | HOST_INT_CMD_COMPLETE
++                              | HOST_INT_INFO
++                              /* | HOST_INT_OVERFLOW       */
++                              /* | HOST_INT_PROCESS_ERROR  */
++                              | HOST_INT_SCAN_COMPLETE
++                              /* | HOST_INT_FCS_THRESHOLD  */
++                              /* | HOST_INT_BEACON_MISSED        */
++                              );
++              adev->irq_mask_off = (u16)~( HOST_INT_UNKNOWN ); /* 0x7fff */
++      }
++}
++
++
++/***********************************************************************
++*/
++int
++acx100mem_s_set_tx_level(acx_device_t *adev, u8 level_dbm)
++{
++      struct acx111_ie_tx_level tx_level;
++
++      /* since it can be assumed that at least the Maxim radio has a
++       * maximum power output of 20dBm and since it also can be
++       * assumed that these values drive the DAC responsible for
++       * setting the linear Tx level, I'd guess that these values
++       * should be the corresponding linear values for a dBm value,
++       * in other words: calculate the values from that formula:
++       * Y [dBm] = 10 * log (X [mW])
++       * then scale the 0..63 value range onto the 1..100mW range (0..20 dBm)
++       * and you're done...
++       * Hopefully that's ok, but you never know if we're actually
++       * right... (especially since Windows XP doesn't seem to show
++       * actual Tx dBm values :-P) */
++
++      /* NOTE: on Maxim, value 30 IS 30mW, and value 10 IS 10mW - so the
++       * values are EXACTLY mW!!! Not sure about RFMD and others,
++       * though... */
++      static const u8 dbm2val_maxim[21] = {
++              63, 63, 63, 62,
++              61, 61, 60, 60,
++              59, 58, 57, 55,
++              53, 50, 47, 43,
++              38, 31, 23, 13,
++              0
++      };
++      static const u8 dbm2val_rfmd[21] = {
++               0,  0,  0,  1,
++               2,  2,  3,  3,
++               4,  5,  6,  8,
++              10, 13, 16, 20,
++              25, 32, 41, 50,
++              63
++      };
++      const u8 *table;
++
++      switch (adev->radio_type) {
++      case RADIO_MAXIM_0D:
++              table = &dbm2val_maxim[0];
++              break;
++      case RADIO_RFMD_11:
++      case RADIO_RALINK_15:
++              table = &dbm2val_rfmd[0];
++              break;
++      default:
++              printk("%s: unknown/unsupported radio type, "
++                      "cannot modify tx power level yet!\n",
++                              adev->ndev->name);
++              return NOT_OK;
++      }
++      /*
++       * The hx4700 EEPROM, at least, only supports 1 power setting.  The configure
++       * routine matches the PA bias with the gain, so just use its default value.
++       * The values are: 0x2b for the gain and 0x03 for the PA bias.  The firmware
++       * writes the gain level to the Tx gain control DAC and the PA bias to the Maxim
++       * radio's PA bias register.  The firmware limits itself to 0 - 64 when writing to the
++       * gain control DAC.
++       *
++       * Physically between the ACX and the radio, higher Tx gain control DAC values result
++       * in less power output; 0 volts to the Maxim radio results in the highest output power
++       * level, which I'm assuming matches up with 0 in the Tx Gain DAC register.
++       *
++       * Although there is only the 1 power setting, one of the radio firmware functions adjusts
++       * the transmit power level up and down.  That function is called by the ACX FIQ handler
++       * under certain conditions.
++       */
++      tx_level.level = 1;
++      //return acx_s_configure(adev, &tx_level, ACX1xx_IE_DOT11_TX_POWER_LEVEL);
++
++      printk("%s: changing radio power level to %u dBm (%u)\n",
++                      adev->ndev->name, level_dbm, table[level_dbm]);
++      acxmem_s_write_phy_reg(adev, 0x11, table[level_dbm]);
++
++      return 0;
++}
++
++void acxmem_e_release(struct device *dev) {
++}
++
++/***********************************************************************
++** acx_cs part
++**
++** called by pcmcia card service
++*/
++
++/*
++   The event() function is this driver's Card Services event handler.
++   It will be called by Card Services when an appropriate card status
++   event is received.  The config() and release() entry points are
++   used to configure or release a socket, in response to card
++   insertion and ejection events.  They are invoked from the acx_cs
++   event handler. 
++*/
++
++static int acx_cs_config(struct pcmcia_device *link);
++static void acx_cs_release(struct pcmcia_device *link);
++
++/*
++   The attach() and detach() entry points are used to create and destroy
++   "instances" of the driver, where each instance represents everything
++   needed to manage one actual PCMCIA card.
++*/
++
++static void acx_cs_detach(struct pcmcia_device *p_dev);
++
++/*
++   You'll also need to prototype all the functions that will actually
++   be used to talk to your device.  See 'pcmem_cs' for a good example
++   of a fully self-sufficient driver; the other drivers rely more or
++   less on other parts of the kernel.
++*/
++
++/*
++   A linked list of "instances" of the  acxnet device.  Each actual
++   PCMCIA card corresponds to one device instance, and is described
++   by one struct pcmcia_device structure (defined in ds.h).
++
++   You may not want to use a linked list for this -- for example, the
++   memory card driver uses an array of struct pcmcia_device pointers, where minor
++   device numbers are used to derive the corresponding array index.
++*/
++
++/*
++   A driver needs to provide a dev_node_t structure for each device
++   on a card.  In some cases, there is only one device per card (for
++   example, ethernet cards, modems).  In other cases, there may be
++   many actual or logical devices (SCSI adapters, memory cards with
++   multiple partitions).  The dev_node_t structures need to be kept
++   in a linked list starting at the 'dev' field of a struct pcmcia_device
++   structure.  We allocate them in the card's private data structure,
++   because they generally shouldn't be allocated dynamically.
++
++   In this case, we also provide a flag to indicate if a device is
++   "stopped" due to a power management event, or card ejection.  The
++   device IO routines can use a flag like this to throttle IO to a
++   card that is not ready to accept it.
++*/
++   
++
++/*======================================================================
++  
++  acx_attach() creates an "instance" of the driver, allocating
++  local data structures for one device.  The device is registered
++  with Card Services.
++  
++  The dev_link structure is initialized, but we don't actually
++  configure the card at this point -- we wait until we receive a
++  card insertion event.
++  
++  ======================================================================*/
++
++static int acx_cs_probe(struct pcmcia_device *link)
++{
++      local_info_t *local;
++      struct net_device *ndev;
++
++      DEBUG(0, "acx_attach()\n");
++
++        ndev = alloc_netdev(sizeof(acx_device_t), "wlan%d", dummy_netdev_init);
++        if (!ndev) {
++                printk("acx: no memory for netdevice struct\n");
++                return -ENOMEM;
++        }
++
++        /* Interrupt setup */
++        link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
++        link->irq.IRQInfo1 = IRQ_LEVEL_ID;
++        link->irq.Handler = acxmem_i_interrupt;
++        link->irq.Instance = ndev;
++
++      /*
++        General socket configuration defaults can go here.  In this
++        client, we assume very little, and rely on the CIS for almost
++        everything.  In most clients, many details (i.e., number, sizes,
++        and attributes of IO windows) are fixed by the nature of the
++        device, and can be hard-wired here.
++      */
++      link->conf.Attributes = CONF_ENABLE_IRQ;
++      link->conf.IntType = INT_MEMORY_AND_IO;
++      link->conf.Present = PRESENT_OPTION | PRESENT_COPY;
++      
++      /* Allocate space for private device-specific data */
++      local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
++      if (!local) {
++              printk(KERN_ERR "acx_cs: no memory for new device\n");
++              return -ENOMEM;
++      }
++      local->ndev = ndev;
++      
++      link->priv = local;
++
++      return acx_cs_config(link);
++} /* acx_attach */
++
++/*======================================================================
++  
++  This deletes a driver "instance".  The device is de-registered
++  with Card Services.  If it has been released, all local data
++  structures are freed.  Otherwise, the structures will be freed
++  when the device is released.
++  
++  ======================================================================*/
++
++static void acx_cs_detach(struct pcmcia_device *link)
++{
++      DEBUG(0, "acx_detach(0x%p)\n", link);
++
++
++      if ( ((local_info_t*)link->priv)->ndev ) {
++              acxmem_e_close( ((local_info_t*)link->priv)->ndev );
++      }
++
++      acx_cs_release(link);
++
++      ((local_info_t*)link->priv)->ndev = NULL;
++
++      kfree(link->priv);
++} /* acx_detach */
++
++/*======================================================================
++  
++  acx_config() is scheduled to run after a CARD_INSERTION event
++  is received, to configure the PCMCIA socket, and to make the
++  device available to the system.
++  
++  ======================================================================*/
++
++#define CS_CHECK(fn, ret) \
++do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
++
++static int acx_cs_config(struct pcmcia_device *link)
++{
++      tuple_t tuple;
++      cisparse_t parse;
++      local_info_t *local = link->priv;
++      int last_fn, last_ret;
++      u_char buf[64];
++      win_req_t req;
++      memreq_t map;
++//    int i;
++//        acx_device_t *adev;
++
++//    adev = (acx_device_t *)link->priv;
++
++      DEBUG(0, "acx_cs_config(0x%p)\n", link);
++
++      /*
++        In this loop, we scan the CIS for configuration table entries,
++        each of which describes a valid card configuration, including
++        voltage, IO window, memory window, and interrupt settings.
++        
++        We make no assumptions about the card to be configured: we use
++        just the information available in the CIS.  In an ideal world,
++        this would work for any PCMCIA card, but it requires a complete
++        and accurate CIS.  In practice, a driver usually "knows" most of
++        these things without consulting the CIS, and most client drivers
++        will only use the CIS to fill in implementation-defined details.
++      */
++    tuple.Attributes = 0;
++    tuple.TupleData = (cisdata_t *)buf;
++    tuple.TupleDataMax = sizeof(buf);
++    tuple.TupleOffset = 0;
++    tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
++
++    /* don't trust the CIS on this; Linksys got it wrong */
++    //link->conf.Present = 0x63;
++
++    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
++        while (1) {
++                cistpl_cftable_entry_t dflt = { 0 };
++                cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
++                if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
++                                pcmcia_parse_tuple(link, &tuple, &parse) != 0)
++                        goto next_entry;
++
++                if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;
++                if (cfg->index == 0) goto next_entry;
++                link->conf.ConfigIndex = cfg->index;
++
++                /* Does this card need audio output? */
++                if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
++                        link->conf.Attributes |= CONF_ENABLE_SPKR;
++                        link->conf.Status = CCSR_AUDIO_ENA;
++                }
++
++                /* Use power settings for Vcc and Vpp if present */
++                /*  Note that the CIS values need to be rescaled */
++                if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
++                        link->conf.Vpp =
++                                cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
++                else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM))
++                        link->conf.Vpp =
++                                dflt.vpp1.param[CISTPL_POWER_VNOM]/10000;
++
++                /* Do we need to allocate an interrupt? */
++                if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1)
++                        link->conf.Attributes |= CONF_ENABLE_IRQ;
++                if ((cfg->mem.nwin > 0) || (dflt.mem.nwin > 0)) {
++                        cistpl_mem_t *mem =
++                                (cfg->mem.nwin) ? &cfg->mem : &dflt.mem;
++//                        req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_AM|WIN_ENABLE|WIN_USE_WAIT;
++                      req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE|WIN_USE_WAIT;
++                        req.Base = mem->win[0].host_addr;
++                        req.Size = mem->win[0].len;
++                        req.Size=0x1000;
++                        req.AccessSpeed = 0;
++                        if (pcmcia_request_window(&link, &req, &link->win) != 0)
++                                goto next_entry;
++                        map.Page = 0; map.CardOffset = mem->win[0].card_addr;
++                        if (pcmcia_map_mem_page(link->win, &map) != 0)
++                                goto next_entry;
++                        else
++                           printk(KERN_INFO "MEMORY WINDOW FOUND!!!\n");
++                }
++                /* If we got this far, we're cool! */
++                break;
++
++        next_entry:
++                CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
++        }
++
++       if (link->conf.Attributes & CONF_ENABLE_IRQ) {
++                printk(KERN_INFO "requesting Irq...\n");
++                CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
++       }
++
++        /*
++          This actually configures the PCMCIA socket -- setting up
++          the I/O windows and the interrupt mapping, and putting the
++          card and host interface into "Memory and IO" mode.
++        */
++        CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
++      DEBUG(0,"RequestConfiguration OK\n");
++
++
++          memwin.Base=req.Base;
++          memwin.Size=req.Size;
++
++      acx_init_netdev(local->ndev, &link->dev, memwin.Base, memwin.Size, link->irq.AssignedIRQ);
++
++#if 1 
++      /*
++        At this point, the dev_node_t structure(s) need to be
++        initialized and arranged in a linked list at link->dev_node.
++      */
++      strcpy(local->node.dev_name, local->ndev->name );
++      local->node.major = local->node.minor = 0;
++      link->dev_node = &local->node;
++      
++      /* Finally, report what we've done */
++      printk(KERN_INFO "%s: index 0x%02x: ",
++             local->ndev->name, link->conf.ConfigIndex);
++#endif
++      if (link->conf.Attributes & CONF_ENABLE_IRQ)
++              printk("irq %d", link->irq.AssignedIRQ);
++      if (link->io.NumPorts1)
++              printk(", io 0x%04x-0x%04x", link->io.BasePort1,
++                     link->io.BasePort1+link->io.NumPorts1-1);
++      if (link->io.NumPorts2)
++              printk(" & 0x%04x-0x%04x", link->io.BasePort2,
++                     link->io.BasePort2+link->io.NumPorts2-1);
++      if (link->win)
++              printk(", mem 0x%06lx-0x%06lx\n", req.Base,
++                     req.Base+req.Size-1);
++      return 0;
++
++ cs_failed:
++      cs_error(link, last_fn, last_ret);
++      acx_cs_release(link);
++      return -ENODEV;
++} /* acx_config */
++
++/*======================================================================
++  
++  After a card is removed, acx_release() will unregister the
++  device, and release the PCMCIA configuration.  If the device is
++  still open, this will be postponed until it is closed.
++  
++  ======================================================================*/
++
++static void acx_cs_release(struct pcmcia_device *link)
++{
++      DEBUG(0, "acx_release(0x%p)\n", link);
++      acxmem_e_remove(link);
++      pcmcia_disable_device(link);
++}
++
++static int acx_cs_suspend(struct pcmcia_device *link)
++{
++      local_info_t *local = link->priv;
++
++      pm_message_t state;
++      acxmem_e_suspend ( local->ndev, state);
++      /* Already done in suspend
++       * netif_device_detach(local->ndev); */
++
++      return 0;
++}
++
++static int acx_cs_resume(struct pcmcia_device *link)
++{
++      local_info_t *local = link->priv;
++      
++      FN_ENTER;
++      resume_ndev = local->ndev;
++
++      schedule_work( &fw_resume_work );
++      
++      /* Already done in suspend
++      if (link->open) {
++        // do we need reset for ACX, if so what function nane is ?
++              //reset_acx_card(local->eth_dev);
++              netif_device_attach(local->ndev);
++      } */
++      
++      FN_EXIT0;
++      return 0;
++}
++
++static struct pcmcia_device_id acx_ids[] = {
++      PCMCIA_DEVICE_MANF_CARD(0x0097, 0x8402),
++        PCMCIA_DEVICE_MANF_CARD(0x0250, 0xb001),
++      PCMCIA_DEVICE_NULL,
++};
++MODULE_DEVICE_TABLE(pcmcia, acx_ids);
++
++static struct pcmcia_driver acx_driver = {
++      .owner          = THIS_MODULE,
++      .drv            = {
++              .name   = "acx_cs",
++      },
++      .probe          = acx_cs_probe,
++      .remove         = acx_cs_detach,
++      .id_table = acx_ids,
++      .suspend        = acx_cs_suspend,
++      .resume         = acx_cs_resume,
++};
++
++int acx_cs_init(void)
++{
++        /* return success if at least one succeeded */
++      DEBUG(0, "acxcs_init()\n");
++      return pcmcia_register_driver(&acx_driver);
++}
++
++void acx_cs_cleanup(void)
++{
++      pcmcia_unregister_driver(&acx_driver);
++}
++
++/*
++    This program is free software; you can redistribute it and/or
++    modify it under the terms of the GNU General Public License
++    as published by the Free Software Foundation; either version 2
++    of the License, or (at your option) any later version.
++
++    This program is distributed in the hope that it will be useful,
++    but WITHOUT ANY WARRANTY; without even the implied warranty of
++    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++    GNU General Public License for more details.
++
++    In addition:
++
++    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. The name of the author may not be used to endorse or promote
++       products derived from this software without specific prior written
++       permission.
++
++    THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
++    IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++    ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
++    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
++    SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++    STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
++    IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
++    POSSIBILITY OF SUCH DAMAGE.    
++*/
++
++MODULE_DESCRIPTION( "ACX Cardbus Driver" );
++MODULE_LICENSE( "GPL" );
++
+Index: linux-2.6.22/drivers/net/wireless/acx/htcsable_acx.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/drivers/net/wireless/acx/htcsable_acx.c       2007-08-23 18:34:19.000000000 +0200
+@@ -0,0 +1,118 @@
++/*
++ * WLAN (TI TNETW1100B) support in the HTC Sable
++ *
++ * Copyright (c) 2006 SDG Systems, LLC
++ *
++ * 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.
++ *
++ * 28-March-2006          Todd Blumer <todd@sdgsystems.com>
++ */
++
++
++#include <linux/kernel.h>
++#include <linux/platform_device.h>
++#include <linux/delay.h>
++
++#include <asm/hardware.h>
++
++#include <asm/arch/pxa-regs.h>
++#include <linux/mfd/asic3_base.h>
++#include <asm/arch/htcsable-gpio.h>
++#include <asm/arch/htcsable-asic.h>
++#include <asm/io.h>
++
++#include "acx_hw.h"
++
++#define WLAN_BASE     PXA_CS2_PHYS
++
++/*
++off: b15 c8 d3
++on: d3 c8 b5 b5-
++*/
++
++#define GPIO_NR_HTCSABLE_ACX111 111
++
++static int
++htcsable_wlan_stop( void );
++
++static int
++htcsable_wlan_start( void )
++{
++      printk( "htcsable_wlan_start\n" );
++
++  /*asic3_set_gpio_out_c(&htcsable_asic3.dev, 1<<GPIOC_ACX_RESET, 0);*/
++  asic3_set_gpio_out_c(&htcsable_asic3.dev, 1<<GPIOC_ACX_PWR_3, 1<<GPIOC_ACX_PWR_3); /* related to acx */
++  SET_HTCSABLE_GPIO(ACX111, 1);
++      asic3_set_gpio_out_b(&htcsable_asic3.dev, 1<<GPIOB_ACX_PWR_1, 1<<GPIOB_ACX_PWR_1);
++      asic3_set_gpio_out_d(&htcsable_asic3.dev, 1<<GPIOD_ACX_PWR_2, 1<<GPIOD_ACX_PWR_2);
++  mdelay(260);
++  asic3_set_gpio_out_c(&htcsable_asic3.dev, 1<<GPIOC_ACX_RESET, 1<<GPIOC_ACX_RESET);
++
++      return 0;
++}
++
++static int
++htcsable_wlan_stop( void )
++{
++      printk( "htcsable_wlan_stop\n" );
++      asic3_set_gpio_out_b(&htcsable_asic3.dev, 1<<GPIOB_ACX_PWR_1, 0);
++      asic3_set_gpio_out_c(&htcsable_asic3.dev, 1<<GPIOC_ACX_RESET, 0);
++      asic3_set_gpio_out_d(&htcsable_asic3.dev, 1<<GPIOD_ACX_PWR_2, 0);
++  SET_HTCSABLE_GPIO(ACX111, 0); /* not necessary to power down this one? */
++      asic3_set_gpio_out_c(&htcsable_asic3.dev, 1<<GPIOC_ACX_PWR_3, 0); /* not necessary to power down this one? */
++
++      return 0;
++}
++
++static struct resource acx_resources[] = {
++      [0] = {
++              .start  = WLAN_BASE,
++              .end    = WLAN_BASE + 0x20,
++              .flags  = IORESOURCE_MEM,
++      },
++      [1] = {
++//            .start  = asic3_irq_base(&htcsable_asic3.dev) + ASIC3_GPIOC_IRQ_BASE+GPIOC_WIFI_IRQ_N,
++//            .end    = asic3_irq_base(&htcsable_asic3.dev) + ASIC3_GPIOC_IRQ_BASE+GPIOC_WIFI_IRQ_N,
++              .flags  = IORESOURCE_IRQ,
++      },
++};
++
++static struct acx_hardware_data acx_data = {
++      .start_hw       = htcsable_wlan_start,
++      .stop_hw        = htcsable_wlan_stop,
++};
++
++static struct platform_device acx_device = {
++      .name   = "acx-mem",
++      .dev    = {
++              .platform_data = &acx_data,
++      },
++      .num_resources  = ARRAY_SIZE( acx_resources ),
++      .resource       = acx_resources,
++};
++
++static int __init
++htcsable_wlan_init( void )
++{
++      printk( "htcsable_wlan_init: acx-mem platform_device_register\n" );
++      acx_device.resource[1].start = asic3_irq_base(&htcsable_asic3.dev) + ASIC3_GPIOB_IRQ_BASE+GPIOB_ACX_IRQ_N;
++      acx_device.resource[1].end = asic3_irq_base(&htcsable_asic3.dev) + ASIC3_GPIOB_IRQ_BASE+GPIOB_ACX_IRQ_N;
++      return platform_device_register( &acx_device );
++}
++
++
++static void __exit
++htcsable_wlan_exit( void )
++{
++      platform_device_unregister( &acx_device );
++}
++
++module_init( htcsable_wlan_init );
++module_exit( htcsable_wlan_exit );
++
++MODULE_AUTHOR( "Todd Blumer <todd@sdgsystems.com>" );
++MODULE_DESCRIPTION( "WLAN driver for HTC Sable" );
++MODULE_LICENSE( "GPL" );
++
+Index: linux-2.6.22/drivers/net/wireless/acx/htcuniversal_acx.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/drivers/net/wireless/acx/htcuniversal_acx.c   2007-08-23 18:34:19.000000000 +0200
+@@ -0,0 +1,108 @@
++/*
++ * WLAN (TI TNETW1100B) support in the HTC Universal
++ *
++ * Copyright (c) 2006 SDG Systems, LLC
++ *
++ * 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.
++ *
++ * 28-March-2006          Todd Blumer <todd@sdgsystems.com>
++ */
++
++
++#include <linux/kernel.h>
++#include <linux/platform_device.h>
++#include <linux/delay.h>
++
++#include <asm/hardware.h>
++
++#include <asm/arch/pxa-regs.h>
++#include <linux/soc/asic3_base.h>
++#include <asm/arch/htcuniversal-gpio.h>
++#include <asm/arch/htcuniversal-asic.h>
++#include <asm/io.h>
++
++#include "acx_hw.h"
++
++#define WLAN_BASE     PXA_CS2_PHYS
++
++
++static int
++htcuniversal_wlan_start( void )
++{
++      htcuniversal_egpio_enable(1<<EGPIO6_WIFI_ON);
++      asic3_set_gpio_out_c(&htcuniversal_asic3.dev, 1<<GPIOC_WIFI_PWR1_ON, 1<<GPIOC_WIFI_PWR1_ON);
++      asic3_set_gpio_out_d(&htcuniversal_asic3.dev, 1<<GPIOD_WIFI_PWR3_ON, 1<<GPIOD_WIFI_PWR3_ON);
++      asic3_set_gpio_out_d(&htcuniversal_asic3.dev, 1<<GPIOD_WIFI_PWR2_ON, 1<<GPIOD_WIFI_PWR2_ON);
++      mdelay(100);
++
++      asic3_set_gpio_out_c(&htcuniversal_asic3.dev, 1<<GPIOC_WIFI_RESET, 0);
++      mdelay(100);
++      asic3_set_gpio_out_c(&htcuniversal_asic3.dev, 1<<GPIOC_WIFI_RESET, 1<<GPIOC_WIFI_RESET);
++      mdelay(100);
++      return 0;
++}
++
++static int
++htcuniversal_wlan_stop( void )
++{
++      asic3_set_gpio_out_c(&htcuniversal_asic3.dev, 1<<GPIOC_WIFI_RESET, 0);
++
++      htcuniversal_egpio_disable(1<<EGPIO6_WIFI_ON);
++      asic3_set_gpio_out_c(&htcuniversal_asic3.dev, 1<<GPIOC_WIFI_PWR1_ON, 0);
++      asic3_set_gpio_out_d(&htcuniversal_asic3.dev, 1<<GPIOD_WIFI_PWR2_ON, 0);
++      asic3_set_gpio_out_d(&htcuniversal_asic3.dev, 1<<GPIOD_WIFI_PWR3_ON, 0);
++      return 0;
++}
++
++static struct resource acx_resources[] = {
++      [0] = {
++              .start  = WLAN_BASE,
++              .end    = WLAN_BASE + 0x20,
++              .flags  = IORESOURCE_MEM,
++      },
++      [1] = {
++//            .start  = asic3_irq_base(&htcuniversal_asic3.dev) + ASIC3_GPIOC_IRQ_BASE+GPIOC_WIFI_IRQ_N,
++//            .end    = asic3_irq_base(&htcuniversal_asic3.dev) + ASIC3_GPIOC_IRQ_BASE+GPIOC_WIFI_IRQ_N,
++              .flags  = IORESOURCE_IRQ,
++      },
++};
++
++static struct acx_hardware_data acx_data = {
++      .start_hw       = htcuniversal_wlan_start,
++      .stop_hw        = htcuniversal_wlan_stop,
++};
++
++static struct platform_device acx_device = {
++      .name   = "acx-mem",
++      .dev    = {
++              .platform_data = &acx_data,
++      },
++      .num_resources  = ARRAY_SIZE( acx_resources ),
++      .resource       = acx_resources,
++};
++
++static int __init
++htcuniversal_wlan_init( void )
++{
++      printk( "htcuniversal_wlan_init: acx-mem platform_device_register\n" );
++      acx_device.resource[1].start = asic3_irq_base(&htcuniversal_asic3.dev) + ASIC3_GPIOC_IRQ_BASE+GPIOC_WIFI_IRQ_N;
++      acx_device.resource[1].end = asic3_irq_base(&htcuniversal_asic3.dev) + ASIC3_GPIOC_IRQ_BASE+GPIOC_WIFI_IRQ_N;
++      return platform_device_register( &acx_device );
++}
++
++
++static void __exit
++htcuniversal_wlan_exit( void )
++{
++      platform_device_unregister( &acx_device );
++}
++
++module_init( htcuniversal_wlan_init );
++module_exit( htcuniversal_wlan_exit );
++
++MODULE_AUTHOR( "Todd Blumer <todd@sdgsystems.com>" );
++MODULE_DESCRIPTION( "WLAN driver for HTC Universal" );
++MODULE_LICENSE( "GPL" );
++
+Index: linux-2.6.22/drivers/net/wireless/acx/hx4700_acx.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/drivers/net/wireless/acx/hx4700_acx.c 2007-08-23 18:34:19.000000000 +0200
+@@ -0,0 +1,108 @@
++/*
++ * WLAN (TI TNETW1100B) support in the hx470x.
++ *
++ * Copyright (c) 2006 SDG Systems, LLC
++ *
++ * 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.
++ *
++ * 28-March-2006          Todd Blumer <todd@sdgsystems.com>
++ */
++
++
++#include <linux/kernel.h>
++#include <linux/platform_device.h>
++#include <linux/delay.h>
++#include <linux/leds.h>
++
++#include <asm/hardware.h>
++
++#include <asm/arch/pxa-regs.h>
++#include <asm/arch/hx4700-gpio.h>
++#include <asm/arch/hx4700-core.h>
++#include <asm/io.h>
++
++#include "acx_hw.h"
++
++#define WLAN_OFFSET   0x1000000
++#define WLAN_BASE     (PXA_CS5_PHYS+WLAN_OFFSET)
++
++
++static int
++hx4700_wlan_start( void )
++{
++      SET_HX4700_GPIO( WLAN_RESET_N, 0 );
++      mdelay(5);
++      hx4700_egpio_enable( EGPIO0_VCC_3V3_EN );
++      mdelay(100);
++      hx4700_egpio_enable( EGPIO7_VCC_3V3_WL_EN );
++      mdelay(150);
++      hx4700_egpio_enable( EGPIO1_WL_VREG_EN | EGPIO2_VCC_2V1_WL_EN |
++                             EGPIO6_WL1V8_EN );
++      mdelay(10);
++      SET_HX4700_GPIO( WLAN_RESET_N, 1 );
++      mdelay(50);
++      led_trigger_event_shared(hx4700_radio_trig, LED_FULL);
++      return 0;
++}
++
++static int
++hx4700_wlan_stop( void )
++{
++      hx4700_egpio_disable( EGPIO0_VCC_3V3_EN | EGPIO1_WL_VREG_EN |
++                              EGPIO7_VCC_3V3_WL_EN | EGPIO2_VCC_2V1_WL_EN |
++                              EGPIO6_WL1V8_EN );
++      SET_HX4700_GPIO( WLAN_RESET_N, 0 );
++      led_trigger_event_shared(hx4700_radio_trig, LED_OFF);
++      return 0;
++}
++
++static struct resource acx_resources[] = {
++      [0] = {
++              .start  = WLAN_BASE,
++              .end    = WLAN_BASE + 0x20,
++              .flags  = IORESOURCE_MEM,
++      },
++      [1] = {
++              .start  = HX4700_IRQ(WLAN_IRQ_N),
++              .end    = HX4700_IRQ(WLAN_IRQ_N),
++              .flags  = IORESOURCE_IRQ,
++      },
++};
++
++static struct acx_hardware_data acx_data = {
++      .start_hw       = hx4700_wlan_start,
++      .stop_hw        = hx4700_wlan_stop,
++};
++
++static struct platform_device acx_device = {
++      .name   = "acx-mem",
++      .dev    = {
++              .platform_data = &acx_data,
++      },
++      .num_resources  = ARRAY_SIZE( acx_resources ),
++      .resource       = acx_resources,
++};
++
++static int __init
++hx4700_wlan_init( void )
++{
++      printk( "hx4700_wlan_init: acx-mem platform_device_register\n" );
++      return platform_device_register( &acx_device );
++}
++
++
++static void __exit
++hx4700_wlan_exit( void )
++{
++      platform_device_unregister( &acx_device );
++}
++
++module_init( hx4700_wlan_init );
++module_exit( hx4700_wlan_exit );
++
++MODULE_AUTHOR( "Todd Blumer <todd@sdgsystems.com>" );
++MODULE_DESCRIPTION( "WLAN driver for iPAQ hx4700" );
++MODULE_LICENSE( "GPL" );
++
+Index: linux-2.6.22/drivers/net/wireless/acx/ioctl.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/drivers/net/wireless/acx/ioctl.c      2007-08-23 18:34:19.000000000 +0200
+@@ -0,0 +1,2748 @@
++/***********************************************************************
++** Copyright (C) 2003  ACX100 Open Source Project
++**
++** The contents of this file are subject to the Mozilla Public
++** License Version 1.1 (the "License"); you may not use this file
++** except in compliance with the License. You may obtain a copy of
++** the License at http://www.mozilla.org/MPL/
++**
++** Software distributed under the License is distributed on an "AS
++** IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
++** implied. See the License for the specific language governing
++** rights and limitations under the License.
++**
++** Alternatively, the contents of this file may be used under the
++** terms of the GNU Public License version 2 (the "GPL"), in which
++** case the provisions of the GPL are applicable instead of the
++** above.  If you wish to allow the use of your version of this file
++** only under the terms of the GPL and not to allow others to use
++** your version of this file under the MPL, indicate your decision
++** by deleting the provisions above and replace them with the notice
++** and other provisions required by the GPL.  If you do not delete
++** the provisions above, a recipient may use your version of this
++** file under either the MPL or the GPL.
++** ---------------------------------------------------------------------
++** Inquiries regarding the ACX100 Open Source Project can be
++** made directly to:
++**
++** acx100-users@lists.sf.net
++** http://acx100.sf.net
++** ---------------------------------------------------------------------
++*/
++
++#include <linux/version.h>
++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18)
++#include <linux/config.h>
++#endif
++#include <linux/kernel.h>
++#include <linux/types.h>
++#include <asm/io.h>
++/* #include <asm/uaccess.h> */ /* required for 2.4.x kernels; verify_write() */
++#include <linux/if_arp.h>
++#include <linux/wireless.h>
++#include <net/iw_handler.h>
++
++#include "acx.h"
++
++
++/***********************************************************************
++*/
++
++/* channel frequencies
++ * TODO: Currently, every other 802.11 driver keeps its own copy of this. In
++ * the long run this should be integrated into ieee802_11.h or wireless.h or
++ * whatever IEEE802.11x framework evolves */
++static const u16 acx_channel_freq[] = {
++      2412, 2417, 2422, 2427, 2432, 2437, 2442,
++      2447, 2452, 2457, 2462, 2467, 2472, 2484,
++};
++
++
++/***********************************************************************
++** acx_ioctl_commit
++*/
++static int
++acx_ioctl_commit(struct net_device *ndev,
++      struct iw_request_info *info,
++      union iwreq_data *wrqu,
++      char *extra)
++{
++      acx_device_t *adev = ndev2adev(ndev);
++
++      FN_ENTER;
++
++      acx_sem_lock(adev);
++      if (ACX_STATE_IFACE_UP & adev->dev_state_mask)
++              acx_s_update_card_settings(adev);
++      acx_sem_unlock(adev);
++
++      FN_EXIT0;
++      return OK;
++}
++
++
++/***********************************************************************
++*/
++static int
++acx_ioctl_get_name(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      union iwreq_data *wrqu,
++      char *extra)
++{
++      acx_device_t *adev = ndev2adev(ndev);
++      static const char * const names[] = { "IEEE 802.11b+/g+", "IEEE 802.11b+" };
++
++      strcpy(wrqu->name, names[IS_ACX111(adev) ? 0 : 1]);
++
++      return OK;
++}
++
++
++/***********************************************************************
++** acx_ioctl_set_freq
++*/
++static int
++acx_ioctl_set_freq(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      union iwreq_data *wrqu,
++      char *extra)
++{
++      acx_device_t *adev = ndev2adev(ndev);
++      int channel = -1;
++      unsigned int mult = 1;
++      int result;
++
++      FN_ENTER;
++
++      if (wrqu->freq.e == 0 && wrqu->freq.m <= 1000) {
++              /* Setting by channel number */
++              channel = wrqu->freq.m;
++      } else {
++              /* If setting by frequency, convert to a channel */
++              int i;
++
++              for (i = 0; i < (6 - wrqu->freq.e); i++)
++                      mult *= 10;
++
++              for (i = 1; i <= 14; i++)
++                      if (wrqu->freq.m == acx_channel_freq[i - 1] * mult)
++                              channel = i;
++      }
++
++      if (channel > 14) {
++              result = -EINVAL;
++              goto end;
++      }
++
++      acx_sem_lock(adev);
++
++      adev->channel = channel;
++      /* hmm, the following code part is strange, but this is how
++       * it was being done before... */
++      log(L_IOCTL, "Changing to channel %d\n", channel);
++      SET_BIT(adev->set_mask, GETSET_CHANNEL);
++
++      result = -EINPROGRESS; /* need to call commit handler */
++
++      acx_sem_unlock(adev);
++end:
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/***********************************************************************
++*/
++static inline int
++acx_ioctl_get_freq(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      union iwreq_data *wrqu,
++      char *extra)
++{
++      acx_device_t *adev = ndev2adev(ndev);
++      wrqu->freq.e = 0;
++      wrqu->freq.m = adev->channel;
++      return OK;
++}
++
++
++/***********************************************************************
++** acx_ioctl_set_mode
++*/
++static int
++acx_ioctl_set_mode(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      union iwreq_data *wrqu,
++      char *extra)
++{
++      acx_device_t *adev = ndev2adev(ndev);
++      int result;
++
++      FN_ENTER;
++
++      acx_sem_lock(adev);
++
++      switch (wrqu->mode) {
++      case IW_MODE_AUTO:
++              adev->mode = ACX_MODE_OFF;
++              break;
++      case IW_MODE_MONITOR:
++              adev->mode = ACX_MODE_MONITOR;
++              break;
++      case IW_MODE_ADHOC:
++              adev->mode = ACX_MODE_0_ADHOC;
++              break;
++      case IW_MODE_INFRA:
++              adev->mode = ACX_MODE_2_STA;
++              break;
++      case IW_MODE_MASTER:
++              printk("acx: master mode (HostAP) is very, very "
++                      "experimental! It might work partially, but "
++                      "better get prepared for nasty surprises "
++                      "at any time\n");
++              adev->mode = ACX_MODE_3_AP;
++              break;
++      case IW_MODE_REPEAT:
++      case IW_MODE_SECOND:
++      default:
++              result = -EOPNOTSUPP;
++              goto end_unlock;
++      }
++
++      log(L_ASSOC, "new adev->mode=%d\n", adev->mode);
++      SET_BIT(adev->set_mask, GETSET_MODE);
++      result = -EINPROGRESS;
++
++end_unlock:
++      acx_sem_unlock(adev);
++
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/***********************************************************************
++*/
++static int
++acx_ioctl_get_mode(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      union iwreq_data *wrqu,
++      char *extra)
++{
++      acx_device_t *adev = ndev2adev(ndev);
++      int result = 0;
++
++      switch (adev->mode) {
++      case ACX_MODE_OFF:
++              wrqu->mode = IW_MODE_AUTO; break;
++      case ACX_MODE_MONITOR:
++              wrqu->mode = IW_MODE_MONITOR; break;
++      case ACX_MODE_0_ADHOC:
++              wrqu->mode = IW_MODE_ADHOC; break;
++      case ACX_MODE_2_STA:
++              wrqu->mode = IW_MODE_INFRA; break;
++      case ACX_MODE_3_AP:
++              wrqu->mode = IW_MODE_MASTER; break;
++      default:
++              result = -EOPNOTSUPP;
++      }
++      return result;
++}
++
++
++/***********************************************************************
++*/
++static int
++acx_ioctl_set_sens(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      union iwreq_data *wrqu,
++      char *extra)
++{
++      struct iw_param *vwrq = &wrqu->sens;
++      acx_device_t *adev = ndev2adev(ndev);
++
++      acx_sem_lock(adev);
++
++      adev->sensitivity = (1 == vwrq->disabled) ? 0 : vwrq->value;
++      SET_BIT(adev->set_mask, GETSET_SENSITIVITY);
++
++      acx_sem_unlock(adev);
++
++      return -EINPROGRESS;
++}
++
++
++/***********************************************************************
++*/
++static int
++acx_ioctl_get_sens(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      union iwreq_data *wrqu,
++      char *extra)
++{
++      struct iw_param *vwrq = &wrqu->sens;
++      acx_device_t *adev = ndev2adev(ndev);
++
++      if (IS_USB(adev))
++              /* setting the PHY reg via fw cmd doesn't work yet */
++              return -EOPNOTSUPP;
++
++      /* acx_sem_lock(adev); */
++
++      vwrq->value = adev->sensitivity;
++      vwrq->disabled = (vwrq->value == 0);
++      vwrq->fixed = 1;
++
++      /* acx_sem_unlock(adev); */
++
++      return OK;
++}
++
++
++/***********************************************************************
++** acx_ioctl_set_ap
++**
++** Sets the MAC address of the AP to associate with
++*/
++static int
++acx_ioctl_set_ap(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      union iwreq_data *wrqu,
++      char *extra)
++{
++      struct sockaddr *awrq = &wrqu->ap_addr;
++      acx_device_t *adev = ndev2adev(ndev);
++      int result = 0;
++      const u8 *ap;
++
++      FN_ENTER;
++      if (NULL == awrq) {
++              result = -EFAULT;
++              goto end;
++      }
++      if (ARPHRD_ETHER != awrq->sa_family) {
++              result = -EINVAL;
++              goto end;
++      }
++
++      ap = awrq->sa_data;
++      acxlog_mac(L_IOCTL, "set AP=", ap, "\n");
++
++      MAC_COPY(adev->ap, ap);
++
++      /* We want to start rescan in managed or ad-hoc mode,
++      ** otherwise just set adev->ap.
++      ** "iwconfig <if> ap <mac> mode managed": we must be able
++      ** to set ap _first_ and _then_ set mode */
++      switch (adev->mode) {
++      case ACX_MODE_0_ADHOC:
++      case ACX_MODE_2_STA:
++              /* FIXME: if there is a convention on what zero AP means,
++              ** please add a comment about that. I don't know of any --vda */
++              if (mac_is_zero(ap)) {
++                      /* "off" == 00:00:00:00:00:00 */
++                      MAC_BCAST(adev->ap);
++                      log(L_IOCTL, "Not reassociating\n");
++              } else {
++                      log(L_IOCTL, "Forcing reassociation\n");
++                      SET_BIT(adev->set_mask, GETSET_RESCAN);
++              }
++              break;
++      }
++      result = -EINPROGRESS;
++end:
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/***********************************************************************
++*/
++static int
++acx_ioctl_get_ap(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      union iwreq_data *wrqu,
++      char *extra)
++{
++      struct sockaddr *awrq = &wrqu->ap_addr;
++      acx_device_t *adev = ndev2adev(ndev);
++
++      if (ACX_STATUS_4_ASSOCIATED == adev->status) {
++              /* as seen in Aironet driver, airo.c */
++              MAC_COPY(awrq->sa_data, adev->bssid);
++      } else {
++              MAC_ZERO(awrq->sa_data);
++      }
++      awrq->sa_family = ARPHRD_ETHER;
++      return OK;
++}
++
++
++/***********************************************************************
++** acx_ioctl_get_aplist
++**
++** Deprecated in favor of iwscan.
++** We simply return the list of currently available stations in range,
++** don't do a new scan.
++*/
++static int
++acx_ioctl_get_aplist(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      union iwreq_data *wrqu,
++      char *extra)
++{
++      struct iw_point *dwrq = &wrqu->data;
++      acx_device_t *adev = ndev2adev(ndev);
++      struct sockaddr *address = (struct sockaddr *) extra;
++      struct iw_quality qual[IW_MAX_AP];
++      int i, cur;
++      int result = OK;
++
++      FN_ENTER;
++
++      /* we have AP list only in STA mode */
++      if (ACX_MODE_2_STA != adev->mode) {
++              result = -EOPNOTSUPP;
++              goto end;
++      }
++
++      cur = 0;
++      for (i = 0; i < VEC_SIZE(adev->sta_list); i++) {
++              struct client *bss = &adev->sta_list[i];
++              if (!bss->used) continue;
++              MAC_COPY(address[cur].sa_data, bss->bssid);
++              address[cur].sa_family = ARPHRD_ETHER;
++              qual[cur].level = bss->sir;
++              qual[cur].noise = bss->snr;
++#ifndef OLD_QUALITY
++              qual[cur].qual = acx_signal_determine_quality(qual[cur].level,
++                                                  qual[cur].noise);
++#else
++              qual[cur].qual = (qual[cur].noise <= 100) ?
++                             100 - qual[cur].noise : 0;
++#endif
++              /* no scan: level/noise/qual not updated: */
++              qual[cur].updated = 0;
++              cur++;
++      }
++      if (cur) {
++              dwrq->flags = 1;
++              memcpy(extra + sizeof(struct sockaddr)*cur, &qual,
++                              sizeof(struct iw_quality)*cur);
++      }
++      dwrq->length = cur;
++end:
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/***********************************************************************
++*/
++static int
++acx_ioctl_set_scan(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      union iwreq_data *wrqu,
++      char *extra)
++{
++      acx_device_t *adev = ndev2adev(ndev);
++      int result;
++
++      FN_ENTER;
++
++      acx_sem_lock(adev);
++
++      /* don't start scan if device is not up yet */
++      if (!(adev->dev_state_mask & ACX_STATE_IFACE_UP)) {
++              result = -EAGAIN;
++              goto end_unlock;
++      }
++
++      /* This is NOT a rescan for new AP!
++      ** Do not use SET_BIT(GETSET_RESCAN); */
++      acx_s_cmd_start_scan(adev);
++      result = OK;
++
++end_unlock:
++      acx_sem_unlock(adev);
++/* end: */
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/***********************************************************************
++** acx_s_scan_add_station
++*/
++/* helper. not sure whether it's really a _s_leeping fn */
++static char*
++acx_s_scan_add_station(
++      acx_device_t *adev,
++      char *ptr,
++      char *end_buf,
++      struct client *bss)
++{
++      struct iw_event iwe;
++      char *ptr_rate;
++
++      FN_ENTER;
++
++      /* MAC address has to be added first */
++      iwe.cmd = SIOCGIWAP;
++      iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
++      MAC_COPY(iwe.u.ap_addr.sa_data, bss->bssid);
++      acxlog_mac(L_IOCTL, "scan, station address: ", bss->bssid, "\n");
++      ptr = iwe_stream_add_event(ptr, end_buf, &iwe, IW_EV_ADDR_LEN);
++
++      /* Add ESSID */
++      iwe.cmd = SIOCGIWESSID;
++      iwe.u.data.length = bss->essid_len;
++      iwe.u.data.flags = 1;
++      log(L_IOCTL, "scan, essid: %s\n", bss->essid);
++      ptr = iwe_stream_add_point(ptr, end_buf, &iwe, bss->essid);
++
++      /* Add mode */
++      iwe.cmd = SIOCGIWMODE;
++      if (bss->cap_info & (WF_MGMT_CAP_ESS | WF_MGMT_CAP_IBSS)) {
++              if (bss->cap_info & WF_MGMT_CAP_ESS)
++                      iwe.u.mode = IW_MODE_MASTER;
++              else
++                      iwe.u.mode = IW_MODE_ADHOC;
++              log(L_IOCTL, "scan, mode: %d\n", iwe.u.mode);
++              ptr = iwe_stream_add_event(ptr, end_buf, &iwe, IW_EV_UINT_LEN);
++      }
++
++      /* Add frequency */
++      iwe.cmd = SIOCGIWFREQ;
++      iwe.u.freq.m = acx_channel_freq[bss->channel - 1] * 100000;
++      iwe.u.freq.e = 1;
++      log(L_IOCTL, "scan, frequency: %d\n", iwe.u.freq.m);
++      ptr = iwe_stream_add_event(ptr, end_buf, &iwe, IW_EV_FREQ_LEN);
++
++      /* Add link quality */
++      iwe.cmd = IWEVQUAL;
++      /* FIXME: these values should be expressed in dBm, but we don't know
++       * how to calibrate it yet */
++      iwe.u.qual.level = bss->sir;
++      iwe.u.qual.noise = bss->snr;
++#ifndef OLD_QUALITY
++      iwe.u.qual.qual = acx_signal_determine_quality(iwe.u.qual.level,
++                                                      iwe.u.qual.noise);
++#else
++      iwe.u.qual.qual = (iwe.u.qual.noise <= 100) ?
++                              100 - iwe.u.qual.noise : 0;
++#endif
++      iwe.u.qual.updated = 7;
++      log(L_IOCTL, "scan, link quality: %d/%d/%d\n",
++                      iwe.u.qual.level, iwe.u.qual.noise, iwe.u.qual.qual);
++      ptr = iwe_stream_add_event(ptr, end_buf, &iwe, IW_EV_QUAL_LEN);
++
++      /* Add encryption */
++      iwe.cmd = SIOCGIWENCODE;
++      if (bss->cap_info & WF_MGMT_CAP_PRIVACY)
++              iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
++      else
++              iwe.u.data.flags = IW_ENCODE_DISABLED;
++      iwe.u.data.length = 0;
++      log(L_IOCTL, "scan, encryption flags: %X\n", iwe.u.data.flags);
++      ptr = iwe_stream_add_point(ptr, end_buf, &iwe, bss->essid);
++
++      /* add rates */
++      iwe.cmd = SIOCGIWRATE;
++      iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
++      ptr_rate = ptr + IW_EV_LCP_LEN;
++
++      {
++      u16 rate = bss->rate_cap;
++      const u8* p = acx_bitpos2ratebyte;
++      while (rate) {
++              if (rate & 1) {
++                      iwe.u.bitrate.value = *p * 500000; /* units of 500kb/s */
++                      log(L_IOCTL, "scan, rate: %d\n", iwe.u.bitrate.value);
++                      ptr_rate = iwe_stream_add_value(ptr, ptr_rate, end_buf,
++                                              &iwe, IW_EV_PARAM_LEN);
++              }
++              rate >>= 1;
++              p++;
++      }}
++
++      if ((ptr_rate - ptr) > (ptrdiff_t)IW_EV_LCP_LEN)
++              ptr = ptr_rate;
++
++      /* drop remaining station data items for now */
++
++      FN_EXIT0;
++      return ptr;
++}
++
++
++/***********************************************************************
++ * acx_ioctl_get_scan
++ */
++static int
++acx_ioctl_get_scan(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      union iwreq_data *wrqu,
++      char *extra)
++{
++      struct iw_point *dwrq = &wrqu->data;
++      acx_device_t *adev = ndev2adev(ndev);
++      char *ptr = extra;
++      int i;
++      int result = OK;
++
++      FN_ENTER;
++
++      acx_sem_lock(adev);
++
++      /* no scan available if device is not up yet */
++      if (!(adev->dev_state_mask & ACX_STATE_IFACE_UP)) {
++              log(L_IOCTL, "iface not up yet\n");
++              result = -EAGAIN;
++              goto end_unlock;
++      }
++
++#ifdef ENODATA_TO_BE_USED_AFTER_SCAN_ERROR_ONLY
++      if (adev->bss_table_count == 0) {
++              /* no stations found */
++              result = -ENODATA;
++              goto end_unlock;
++      }
++#endif
++
++      for (i = 0; i < VEC_SIZE(adev->sta_list); i++) {
++              struct client *bss = &adev->sta_list[i];
++              if (!bss->used) continue;
++              ptr = acx_s_scan_add_station(adev, ptr,
++                      extra + IW_SCAN_MAX_DATA, bss);
++      }
++      dwrq->length = ptr - extra;
++      dwrq->flags = 0;
++
++end_unlock:
++      acx_sem_unlock(adev);
++/* end: */
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/***********************************************************************
++** acx_ioctl_set_essid
++*/
++static int
++acx_ioctl_set_essid(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      union iwreq_data *wrqu,
++      char *extra)
++{
++      struct iw_point *dwrq = &wrqu->essid;
++      acx_device_t *adev = ndev2adev(ndev);
++      int len = dwrq->length;
++      int result;
++
++      FN_ENTER;
++
++      if (len < 0) {
++              result = -EINVAL;
++              goto end;
++      }
++
++      log(L_IOCTL, "set ESSID '%*s', length %d, flags 0x%04X\n",
++                                      len, extra, len, dwrq->flags);
++
++#if WIRELESS_EXT >= 21
++      /* WE 21 gives real ESSID strlen, not +1 (trailing zero):
++       * see LKML "[patch] drivers/net/wireless: correct reported ssid lengths" */
++      len += 1;
++#endif
++
++      acx_sem_lock(adev);
++
++      /* ESSID disabled? */
++      if (0 == dwrq->flags) {
++              adev->essid_active = 0;
++
++      } else {
++              if (len > IW_ESSID_MAX_SIZE)    {
++                      result = -E2BIG;
++                      goto end_unlock;
++              }
++
++              if (len >= sizeof(adev->essid))
++                      len = sizeof(adev->essid) - 1;
++              memcpy(adev->essid, extra, len);
++              adev->essid[len] = '\0';
++              /* Paranoia: just in case there is a '\0'... */
++              adev->essid_len = strlen(adev->essid);
++              adev->essid_active = 1;
++      }
++
++      SET_BIT(adev->set_mask, GETSET_RESCAN);
++
++      result = -EINPROGRESS;
++
++end_unlock:
++      acx_sem_unlock(adev);
++end:
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/***********************************************************************
++*/
++static int
++acx_ioctl_get_essid(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      union iwreq_data *wrqu,
++      char *extra)
++{
++      struct iw_point *dwrq = &wrqu->essid;
++      acx_device_t *adev = ndev2adev(ndev);
++
++      dwrq->flags = adev->essid_active;
++      if (adev->essid_active) {
++              memcpy(extra, adev->essid, adev->essid_len);
++              extra[adev->essid_len] = '\0';
++              dwrq->length = adev->essid_len + 1;
++              dwrq->flags = 1;
++      }
++      return OK;
++}
++
++
++/***********************************************************************
++** acx_l_update_client_rates
++*/
++static void
++acx_l_update_client_rates(acx_device_t *adev, u16 rate)
++{
++      int i;
++      for (i = 0; i < VEC_SIZE(adev->sta_list); i++) {
++              client_t *clt = &adev->sta_list[i];
++              if (!clt->used) continue;
++              clt->rate_cfg = (clt->rate_cap & rate);
++              if (!clt->rate_cfg) {
++                      /* no compatible rates left: kick client */
++                      acxlog_mac(L_ASSOC, "client ",clt->address," kicked: "
++                              "rates are not compatible anymore\n");
++                      acx_l_sta_list_del(adev, clt);
++                      continue;
++              }
++              clt->rate_cur &= clt->rate_cfg;
++              if (!clt->rate_cur) {
++                      /* current rate become invalid, choose a valid one */
++                      clt->rate_cur = 1 << lowest_bit(clt->rate_cfg);
++              }
++              if (IS_ACX100(adev))
++                      clt->rate_100 = acx_bitpos2rate100[highest_bit(clt->rate_cur)];
++              clt->fallback_count = clt->stepup_count = 0;
++              clt->ignore_count = 16;
++      }
++      switch (adev->mode) {
++      case ACX_MODE_2_STA:
++              if (adev->ap_client && !adev->ap_client->used) {
++                      /* Owwww... we kicked our AP!! :) */
++                      SET_BIT(adev->set_mask, GETSET_RESCAN);
++              }
++      }
++}
++
++
++/***********************************************************************
++*/
++/* maps bits from acx111 rate to rate in Mbits */
++static const unsigned int
++acx111_rate_tbl[] = {
++     1000000, /* 0 */
++     2000000, /* 1 */
++     5500000, /* 2 */
++     6000000, /* 3 */
++     9000000, /* 4 */
++    11000000, /* 5 */
++    12000000, /* 6 */
++    18000000, /* 7 */
++    22000000, /* 8 */
++    24000000, /* 9 */
++    36000000, /* 10 */
++    48000000, /* 11 */
++    54000000, /* 12 */
++      500000, /* 13, should not happen */
++      500000, /* 14, should not happen */
++      500000, /* 15, should not happen */
++};
++
++/***********************************************************************
++ * acx_ioctl_set_rate
++ */
++static int
++acx_ioctl_set_rate(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      union iwreq_data *wrqu,
++      char *extra)
++{
++      struct iw_param *vwrq = &wrqu->param;
++      acx_device_t *adev = ndev2adev(ndev);
++      u16 txrate_cfg = 1;
++      unsigned long flags;
++      int autorate;
++      int result = -EINVAL;
++
++      FN_ENTER;
++      log(L_IOCTL, "rate %d fixed 0x%X disabled 0x%X flags 0x%X\n",
++              vwrq->value, vwrq->fixed, vwrq->disabled, vwrq->flags);
++
++      if ((0 == vwrq->fixed) || (1 == vwrq->fixed)) {
++              int i = VEC_SIZE(acx111_rate_tbl)-1;
++              if (vwrq->value == -1)
++                      /* "iwconfig rate auto" --> choose highest */
++                      vwrq->value = IS_ACX100(adev) ? 22000000 : 54000000;
++              while (i >= 0) {
++                      if (vwrq->value == acx111_rate_tbl[i]) {
++                              txrate_cfg <<= i;
++                              i = 0;
++                              break;
++                      }
++                      i--;
++              }
++              if (i == -1) { /* no matching rate */
++                      result = -EINVAL;
++                      goto end;
++              }
++      } else {        /* rate N, N<1000 (driver specific): we don't use this */
++              result = -EOPNOTSUPP;
++              goto end;
++      }
++      /* now: only one bit is set in txrate_cfg, corresponding to
++      ** indicated rate */
++
++      autorate = (vwrq->fixed == 0) && (RATE111_1 != txrate_cfg);
++      if (autorate) {
++              /* convert 00100000 -> 00111111 */
++              txrate_cfg = (txrate_cfg<<1)-1;
++      }
++
++      if (IS_ACX100(adev)) {
++              txrate_cfg &= RATE111_ACX100_COMPAT;
++              if (!txrate_cfg) {
++                      result = -ENOTSUPP; /* rate is not supported by acx100 */
++                      goto end;
++              }
++      }
++
++      acx_sem_lock(adev);
++      acx_lock(adev, flags);
++
++      adev->rate_auto = autorate;
++      adev->rate_oper = txrate_cfg;
++      adev->rate_basic = txrate_cfg;
++      /* only do that in auto mode, non-auto will be able to use
++       * one specific Tx rate only anyway */
++      if (autorate) {
++              /* only use 802.11b base rates, for standard 802.11b H/W
++               * compatibility */
++              adev->rate_basic &= RATE111_80211B_COMPAT;
++      }
++      adev->rate_bcast = 1 << lowest_bit(txrate_cfg);
++      if (IS_ACX100(adev))
++              adev->rate_bcast100 = acx_rate111to100(adev->rate_bcast);
++      acx_l_update_ratevector(adev);
++      acx_l_update_client_rates(adev, txrate_cfg);
++
++      /* Do/don't do tx rate fallback; beacon contents and rate */
++      SET_BIT(adev->set_mask, SET_RATE_FALLBACK|SET_TEMPLATES);
++      result = -EINPROGRESS;
++
++      acx_unlock(adev, flags);
++      acx_sem_unlock(adev);
++end:
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/***********************************************************************
++** acx_ioctl_get_rate
++*/
++static int
++acx_ioctl_get_rate(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      union iwreq_data *wrqu,
++      char *extra)
++{
++      struct iw_param *vwrq = &wrqu->param;
++      acx_device_t *adev = ndev2adev(ndev);
++      unsigned long flags;
++      u16 rate;
++
++      acx_lock(adev, flags);
++      rate = adev->rate_oper;
++      if (adev->ap_client)
++              rate = adev->ap_client->rate_cur;
++      vwrq->value = acx111_rate_tbl[highest_bit(rate)];
++      vwrq->fixed = !adev->rate_auto;
++      vwrq->disabled = 0;
++      acx_unlock(adev, flags);
++
++      return OK;
++}
++
++static int
++acx_ioctl_set_rts(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      union iwreq_data *wrqu,
++      char *extra)
++{
++      struct iw_param *vwrq = &wrqu->rts;
++      acx_device_t *adev = ndev2adev(ndev);
++      int val = vwrq->value;
++
++      if (vwrq->disabled)
++              val = 2312;
++      if ((val < 0) || (val > 2312))
++              return -EINVAL;
++
++      adev->rts_threshold = val;
++      return OK;
++}
++
++static inline int
++acx_ioctl_get_rts(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      union iwreq_data *wrqu,
++      char *extra)
++{
++      struct iw_param *vwrq = &wrqu->rts;
++      acx_device_t *adev = ndev2adev(ndev);
++
++      vwrq->value = adev->rts_threshold;
++      vwrq->disabled = (vwrq->value >= 2312);
++      vwrq->fixed = 1;
++      return OK;
++}
++
++
++#if ACX_FRAGMENTATION
++static int
++acx_ioctl_set_frag(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      struct iw_param *vwrq,
++      char *extra)
++{
++      acx_device_t *adev = ndev2adev(ndev);
++      int val = vwrq->value;
++
++      if (vwrq->disabled)
++              val = 32767;
++      else
++      if ((val < 256) || (val > 2347))
++              return -EINVAL;
++
++      adev->frag_threshold = val;
++      return OK;
++}
++
++static inline int
++acx_ioctl_get_frag(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      union iwreq_data *wrqu,
++      char *extra)
++{
++      struct iw_param *vwrq = &wrqu->frag;
++      acx_device_t *adev = ndev2adev(ndev);
++
++      vwrq->value = adev->frag_threshold;
++      vwrq->disabled = (vwrq->value >= 2347);
++      vwrq->fixed = 1;
++      return OK;
++}
++#endif
++
++
++/***********************************************************************
++** acx_ioctl_set_encode
++*/
++static int
++acx_ioctl_set_encode(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      union iwreq_data *wrqu,
++      char *extra)
++{
++      struct iw_point *dwrq = &wrqu->encoding;
++      acx_device_t *adev = ndev2adev(ndev);
++      int index;
++      int result;
++
++      FN_ENTER;
++
++      log(L_IOCTL, "set encoding flags=0x%04X, size=%d, key: %s\n",
++                      dwrq->flags, dwrq->length, extra ? "set" : "No key");
++
++      acx_sem_lock(adev);
++
++      index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
++
++      if (dwrq->length > 0) {
++              /* if index is 0 or invalid, use default key */
++              if ((index < 0) || (index > 3))
++                      index = (int)adev->wep_current_index;
++
++              if (0 == (dwrq->flags & IW_ENCODE_NOKEY)) {
++                      if (dwrq->length > 29)
++                              dwrq->length = 29; /* restrict it */
++
++                      if (dwrq->length > 13) {
++                              /* 29*8 == 232, WEP256 */
++                              adev->wep_keys[index].size = 29;
++                      } else if (dwrq->length > 5) {
++                              /* 13*8 == 104bit, WEP128 */
++                              adev->wep_keys[index].size = 13;
++                      } else if (dwrq->length > 0) {
++                              /* 5*8 == 40bit, WEP64 */
++                              adev->wep_keys[index].size = 5;
++                      } else {
++                              /* disable key */
++                              adev->wep_keys[index].size = 0;
++                      }
++
++                      memset(adev->wep_keys[index].key, 0,
++                              sizeof(adev->wep_keys[index].key));
++                      memcpy(adev->wep_keys[index].key, extra, dwrq->length);
++              }
++      } else {
++              /* set transmit key */
++              if ((index >= 0) && (index <= 3))
++                      adev->wep_current_index = index;
++              else if (0 == (dwrq->flags & IW_ENCODE_MODE)) {
++                      /* complain if we were not just setting
++                       * the key mode */
++                      result = -EINVAL;
++                      goto end_unlock;
++              }
++      }
++
++      adev->wep_enabled = !(dwrq->flags & IW_ENCODE_DISABLED);
++
++      if (dwrq->flags & IW_ENCODE_OPEN) {
++              adev->auth_alg = WLAN_AUTH_ALG_OPENSYSTEM;
++              adev->wep_restricted = 0;
++
++      } else if (dwrq->flags & IW_ENCODE_RESTRICTED) {
++              adev->auth_alg = WLAN_AUTH_ALG_SHAREDKEY;
++              adev->wep_restricted = 1;
++      }
++
++      /* set flag to make sure the card WEP settings get updated */
++      SET_BIT(adev->set_mask, GETSET_WEP);
++
++      log(L_IOCTL, "len=%d, key at 0x%p, flags=0x%X\n",
++              dwrq->length, extra, dwrq->flags);
++
++      for (index = 0; index <= 3; index++) {
++              if (adev->wep_keys[index].size) {
++                      log(L_IOCTL,    "index=%d, size=%d, key at 0x%p\n",
++                              adev->wep_keys[index].index,
++                              (int) adev->wep_keys[index].size,
++                              adev->wep_keys[index].key);
++              }
++      }
++      result = -EINPROGRESS;
++
++end_unlock:
++      acx_sem_unlock(adev);
++
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/***********************************************************************
++** acx_ioctl_get_encode
++*/
++static int
++acx_ioctl_get_encode(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      union iwreq_data *wrqu,
++      char *extra)
++{
++      struct iw_point *dwrq = &wrqu->encoding;
++      acx_device_t *adev = ndev2adev(ndev);
++      int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
++
++      FN_ENTER;
++
++      if (adev->wep_enabled == 0) {
++              dwrq->flags = IW_ENCODE_DISABLED;
++      } else {
++              if ((index < 0) || (index > 3))
++                      index = (int)adev->wep_current_index;
++
++              dwrq->flags = (adev->wep_restricted == 1) ?
++                              IW_ENCODE_RESTRICTED : IW_ENCODE_OPEN;
++              dwrq->length = adev->wep_keys[index].size;
++
++              memcpy(extra, adev->wep_keys[index].key,
++                            adev->wep_keys[index].size);
++      }
++
++      /* set the current index */
++      SET_BIT(dwrq->flags, index + 1);
++
++      log(L_IOCTL, "len=%d, key=%p, flags=0x%X\n",
++             dwrq->length, dwrq->pointer,
++             dwrq->flags);
++
++      FN_EXIT1(OK);
++      return OK;
++}
++
++
++/***********************************************************************
++*/
++static int
++acx_ioctl_set_power(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      union iwreq_data *wrqu,
++      char *extra)
++{
++      struct iw_param *vwrq = &wrqu->power;
++      acx_device_t *adev = ndev2adev(ndev);
++      int result = -EINPROGRESS;
++
++      FN_ENTER;
++
++      log(L_IOCTL, "set 802.11 powersave flags=0x%04X\n", vwrq->flags);
++
++      acx_sem_lock(adev);
++
++      if (vwrq->disabled) {
++              CLEAR_BIT(adev->ps_wakeup_cfg, PS_CFG_ENABLE);
++              SET_BIT(adev->set_mask, GETSET_POWER_80211);
++              goto end;
++      }
++      if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
++              u16 ps_timeout = (vwrq->value * 1024) / 1000;
++
++              if (ps_timeout > 255)
++                      ps_timeout = 255;
++              log(L_IOCTL, "setting PS timeout value to %d time units "
++                              "due to %dus\n", ps_timeout, vwrq->value);
++              adev->ps_hangover_period = ps_timeout;
++      } else if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_PERIOD) {
++              u16 ps_periods = vwrq->value / 1000000;
++
++              if (ps_periods > 255)
++                      ps_periods = 255;
++              log(L_IOCTL, "setting PS period value to %d periods "
++                              "due to %dus\n", ps_periods, vwrq->value);
++              adev->ps_listen_interval = ps_periods;
++              CLEAR_BIT(adev->ps_wakeup_cfg, PS_CFG_WAKEUP_MODE_MASK);
++              SET_BIT(adev->ps_wakeup_cfg, PS_CFG_WAKEUP_EACH_ITVL);
++      }
++
++      switch (vwrq->flags & IW_POWER_MODE) {
++              /* FIXME: are we doing the right thing here? */
++              case IW_POWER_UNICAST_R:
++                      CLEAR_BIT(adev->ps_options, PS_OPT_STILL_RCV_BCASTS);
++                      break;
++              case IW_POWER_MULTICAST_R:
++                      SET_BIT(adev->ps_options, PS_OPT_STILL_RCV_BCASTS);
++                      break;
++              case IW_POWER_ALL_R:
++                      SET_BIT(adev->ps_options, PS_OPT_STILL_RCV_BCASTS);
++                      break;
++              case IW_POWER_ON:
++                      break;
++              default:
++                      log(L_IOCTL, "unknown PS mode\n");
++                      result = -EINVAL;
++                      goto end;
++      }
++
++      SET_BIT(adev->ps_wakeup_cfg, PS_CFG_ENABLE);
++      SET_BIT(adev->set_mask, GETSET_POWER_80211);
++end:
++      acx_sem_unlock(adev);
++
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/***********************************************************************
++*/
++static int
++acx_ioctl_get_power(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      union iwreq_data *wrqu,
++      char *extra)
++{
++      struct iw_param *vwrq = &wrqu->power;
++      acx_device_t *adev = ndev2adev(ndev);
++
++      FN_ENTER;
++
++      log(L_IOCTL, "Get 802.11 Power Save flags = 0x%04X\n", vwrq->flags);
++      vwrq->disabled = ((adev->ps_wakeup_cfg & PS_CFG_ENABLE) == 0);
++      if (vwrq->disabled)
++              goto end;
++
++      if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
++              vwrq->value = adev->ps_hangover_period * 1000 / 1024;
++              vwrq->flags = IW_POWER_TIMEOUT;
++      } else {
++              vwrq->value = adev->ps_listen_interval * 1000000;
++              vwrq->flags = IW_POWER_PERIOD|IW_POWER_RELATIVE;
++      }
++      if (adev->ps_options & PS_OPT_STILL_RCV_BCASTS)
++              SET_BIT(vwrq->flags, IW_POWER_ALL_R);
++      else
++              SET_BIT(vwrq->flags, IW_POWER_UNICAST_R);
++end:
++      FN_EXIT1(OK);
++      return OK;
++}
++
++
++/***********************************************************************
++** acx_ioctl_get_txpow
++*/
++static inline int
++acx_ioctl_get_txpow(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      union iwreq_data *wrqu,
++      char *extra)
++{
++      struct iw_param *vwrq = &wrqu->power;
++      acx_device_t *adev = ndev2adev(ndev);
++
++      FN_ENTER;
++
++      vwrq->flags = IW_TXPOW_DBM;
++      vwrq->disabled = 0;
++      vwrq->fixed = 1;
++      vwrq->value = adev->tx_level_dbm;
++
++      log(L_IOCTL, "get txpower:%d dBm\n", adev->tx_level_dbm);
++
++      FN_EXIT1(OK);
++      return OK;
++}
++
++
++/***********************************************************************
++** acx_ioctl_set_txpow
++*/
++static int
++acx_ioctl_set_txpow(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      union iwreq_data *wrqu,
++      char *extra)
++{
++      struct iw_param *vwrq = &wrqu->power;
++      acx_device_t *adev = ndev2adev(ndev);
++      int result;
++
++      FN_ENTER;
++
++      log(L_IOCTL, "set txpower:%d, disabled:%d, flags:0x%04X\n",
++                      vwrq->value, vwrq->disabled, vwrq->flags);
++
++      acx_sem_lock(adev);
++
++      if (vwrq->disabled != adev->tx_disabled) {
++              SET_BIT(adev->set_mask, GETSET_TX);
++      }
++
++      adev->tx_disabled = vwrq->disabled;
++      if (vwrq->value == -1) {
++              if (vwrq->disabled) {
++                      adev->tx_level_dbm = 0;
++                      log(L_IOCTL, "disable radio tx\n");
++              } else {
++                      /* adev->tx_level_auto = 1; */
++                      log(L_IOCTL, "set tx power auto (NIY)\n");
++              }
++      } else {
++              adev->tx_level_dbm = vwrq->value <= 20 ? vwrq->value : 20;
++              /* adev->tx_level_auto = 0; */
++              log(L_IOCTL, "set txpower=%d dBm\n", adev->tx_level_dbm);
++      }
++      SET_BIT(adev->set_mask, GETSET_TXPOWER);
++
++      result = -EINPROGRESS;
++
++      acx_sem_unlock(adev);
++
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/***********************************************************************
++** acx_ioctl_get_range
++*/
++static int
++acx_ioctl_get_range(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      union iwreq_data *wrqu,
++      char *extra)
++{
++      struct iw_point *dwrq = &wrqu->data;
++      struct iw_range *range = (struct iw_range *)extra;
++      acx_device_t *adev = ndev2adev(ndev);
++      int i,n;
++
++      FN_ENTER;
++
++      if (!dwrq->pointer)
++              goto end;
++
++      dwrq->length = sizeof(struct iw_range);
++      memset(range, 0, sizeof(struct iw_range));
++      n = 0;
++      for (i = 1; i <= 14; i++) {
++              if (adev->reg_dom_chanmask & (1 << (i - 1))) {
++                      range->freq[n].i = i;
++                      range->freq[n].m = acx_channel_freq[i - 1] * 100000;
++                      range->freq[n].e = 1; /* units are MHz */
++                      n++;
++              }
++      }
++      range->num_channels = n;
++      range->num_frequency = n;
++
++      range->min_rts = 0;
++      range->max_rts = 2312;
++
++#if ACX_FRAGMENTATION
++      range->min_frag = 256;
++      range->max_frag = 2312;
++#endif
++
++      range->encoding_size[0] = 5;
++      range->encoding_size[1] = 13;
++      range->encoding_size[2] = 29;
++      range->num_encoding_sizes = 3;
++      range->max_encoding_tokens = 4;
++
++      range->min_pmp = 0;
++      range->max_pmp = 5000000;
++      range->min_pmt = 0;
++      range->max_pmt = 65535 * 1000;
++      range->pmp_flags = IW_POWER_PERIOD;
++      range->pmt_flags = IW_POWER_TIMEOUT;
++      range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R;
++
++      if (IS_ACX100(adev)) { /* ACX100 has direct radio programming - arbitrary levels, so offer a lot */
++              for (i = 0; i <= IW_MAX_TXPOWER - 1; i++)
++                      range->txpower[i] = 20 * i / (IW_MAX_TXPOWER - 1);
++              range->num_txpower = IW_MAX_TXPOWER;
++              range->txpower_capa = IW_TXPOW_DBM;
++      }
++      else {
++              int count = min(IW_MAX_TXPOWER, (int)adev->cfgopt_power_levels.len);
++              for (i = 0; i <= count; i++)
++                      range->txpower[i] = adev->cfgopt_power_levels.list[i];
++              range->num_txpower = count;
++              /* this list is given in mW */
++              range->txpower_capa = IW_TXPOW_MWATT;
++      }
++
++      range->we_version_compiled = WIRELESS_EXT;
++      range->we_version_source = 0x9;
++
++      range->retry_capa = IW_RETRY_LIMIT;
++      range->retry_flags = IW_RETRY_LIMIT;
++      range->min_retry = 1;
++      range->max_retry = 255;
++
++      range->r_time_flags = IW_RETRY_LIFETIME;
++      range->min_r_time = 0;
++      /* FIXME: lifetime ranges and orders of magnitude are strange?? */
++      range->max_r_time = 65535;
++
++      if (IS_USB(adev))
++              range->sensitivity = 0;
++      else if (IS_ACX111(adev))
++              range->sensitivity = 3;
++      else
++              range->sensitivity = 255;
++
++      for (i=0; i < adev->rate_supported_len; i++) {
++              range->bitrate[i] = (adev->rate_supported[i] & ~0x80) * 500000;
++              /* never happens, but keep it, to be safe: */
++              if (range->bitrate[i] == 0)
++                      break;
++      }
++      range->num_bitrates = i;
++
++      range->max_qual.qual = 100;
++      range->max_qual.level = 100;
++      range->max_qual.noise = 100;
++      /* TODO: better values */
++      range->avg_qual.qual = 90;
++      range->avg_qual.level = 80;
++      range->avg_qual.noise = 2;
++
++end:
++      FN_EXIT1(OK);
++      return OK;
++}
++
++
++/***********************************************************************
++** Private functions
++*/
++
++/***********************************************************************
++** acx_ioctl_get_nick
++*/
++static inline int
++acx_ioctl_get_nick(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      union iwreq_data *wrqu,
++      char *extra)
++{
++      struct iw_point *dwrq = &wrqu->data;
++      acx_device_t *adev = ndev2adev(ndev);
++
++      strcpy(extra, adev->nick);
++      dwrq->length = strlen(extra) + 1;
++
++      return OK;
++}
++
++
++/***********************************************************************
++** acx_ioctl_set_nick
++*/
++static int
++acx_ioctl_set_nick(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      union iwreq_data *wrqu,
++      char *extra)
++{
++      struct iw_point *dwrq = &wrqu->data;
++      acx_device_t *adev = ndev2adev(ndev);
++      int result;
++
++      FN_ENTER;
++
++      acx_sem_lock(adev);
++
++      if (dwrq->length > IW_ESSID_MAX_SIZE + 1) {
++              result = -E2BIG;
++              goto end_unlock;
++      }
++
++      /* extra includes trailing \0, so it's ok */
++      strcpy(adev->nick, extra);
++      result = OK;
++
++end_unlock:
++      acx_sem_unlock(adev);
++
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/***********************************************************************
++** acx_ioctl_get_retry
++*/
++static int
++acx_ioctl_get_retry(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      union iwreq_data *wrqu,
++      char *extra)
++{
++      struct iw_param *vwrq = &wrqu->retry;
++      acx_device_t *adev = ndev2adev(ndev);
++      unsigned int type = vwrq->flags & IW_RETRY_TYPE;
++      unsigned int modifier = vwrq->flags & IW_RETRY_MODIFIER;
++      int result;
++
++      FN_ENTER;
++
++      acx_sem_lock(adev);
++
++      /* return the short retry number by default */
++      if (type == IW_RETRY_LIFETIME) {
++              vwrq->flags = IW_RETRY_LIFETIME;
++              vwrq->value = adev->msdu_lifetime;
++      } else if (modifier == IW_RETRY_MAX) {
++              vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
++              vwrq->value = adev->long_retry;
++      } else {
++              vwrq->flags = IW_RETRY_LIMIT;
++              if (adev->long_retry != adev->short_retry)
++                      SET_BIT(vwrq->flags, IW_RETRY_MIN);
++              vwrq->value = adev->short_retry;
++      }
++
++      /* can't be disabled */
++      vwrq->disabled = (u8)0;
++      result = OK;
++
++      acx_sem_unlock(adev);
++
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/***********************************************************************
++** acx_ioctl_set_retry
++*/
++static int
++acx_ioctl_set_retry(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      union iwreq_data *wrqu,
++      char *extra)
++{
++      struct iw_param *vwrq = &wrqu->retry;
++      acx_device_t *adev = ndev2adev(ndev);
++      int result;
++
++      FN_ENTER;
++
++      if (!vwrq) {
++              result = -EFAULT;
++              goto end;
++      }
++      if (vwrq->disabled) {
++              result = -EINVAL;
++              goto end;
++      }
++
++      acx_sem_lock(adev);
++
++      result = -EINVAL;
++      if (IW_RETRY_LIMIT == (vwrq->flags & IW_RETRY_TYPE)) {
++              printk("old retry limits: short %d long %d\n",
++                              adev->short_retry, adev->long_retry);
++              if (vwrq->flags & IW_RETRY_MAX) {
++                      adev->long_retry = vwrq->value;
++              } else if (vwrq->flags & IW_RETRY_MIN) {
++                      adev->short_retry = vwrq->value;
++              } else {
++                      /* no modifier: set both */
++                      adev->long_retry = vwrq->value;
++                      adev->short_retry = vwrq->value;
++              }
++              printk("new retry limits: short %d long %d\n",
++                              adev->short_retry, adev->long_retry);
++              SET_BIT(adev->set_mask, GETSET_RETRY);
++              result = -EINPROGRESS;
++      }
++      else if (vwrq->flags & IW_RETRY_LIFETIME) {
++              adev->msdu_lifetime = vwrq->value;
++              printk("new MSDU lifetime: %d\n", adev->msdu_lifetime);
++              SET_BIT(adev->set_mask, SET_MSDU_LIFETIME);
++              result = -EINPROGRESS;
++      }
++
++      acx_sem_unlock(adev);
++end:
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/************************ private ioctls ******************************/
++
++
++/***********************************************************************
++** acx_ioctl_set_debug
++*/
++#if ACX_DEBUG
++static int
++acx_ioctl_set_debug(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      union iwreq_data *wrqu,
++      char *extra)
++{
++      unsigned int debug_new = *((unsigned int *)extra);
++      int result = -EINVAL;
++
++      log(L_ANY, "setting debug from %04X to %04X\n", acx_debug, debug_new);
++      acx_debug = debug_new;
++
++      result = OK;
++      return result;
++
++}
++#endif
++
++
++/***********************************************************************
++** acx_ioctl_list_reg_domain
++*/
++static int
++acx_ioctl_list_reg_domain(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      union iwreq_data *wrqu,
++      char *extra)
++{
++      int i = 1;
++      const char * const *entry = acx_reg_domain_strings;
++
++      printk("dom# chan# domain/country\n");
++      while (*entry)
++              printk("%4d %s\n", i++, *entry++);
++      return OK;
++}
++
++
++/***********************************************************************
++** acx_ioctl_set_reg_domain
++*/
++static int
++acx_ioctl_set_reg_domain(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      union iwreq_data *wrqu,
++      char *extra)
++{
++      acx_device_t *adev = ndev2adev(ndev);
++      int result;
++
++      FN_ENTER;
++
++      if ((*extra < 1) || ((size_t)*extra > acx_reg_domain_ids_len)) {
++              result = -EINVAL;
++              goto end;
++      }
++
++      acx_sem_lock(adev);
++
++      adev->reg_dom_id = acx_reg_domain_ids[*extra - 1];
++      SET_BIT(adev->set_mask, GETSET_REG_DOMAIN);
++
++      result = -EINPROGRESS;
++
++      acx_sem_unlock(adev);
++end:
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/***********************************************************************
++** acx_ioctl_get_reg_domain
++*/
++static int
++acx_ioctl_get_reg_domain(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      union iwreq_data *wrqu,
++      char *extra)
++{
++      acx_device_t *adev = ndev2adev(ndev);
++      int dom,i;
++
++      /* no locking */
++      dom = adev->reg_dom_id;
++
++      for (i = 1; i <= acx_reg_domain_ids_len; i++) {
++              if (acx_reg_domain_ids[i-1] == dom) {
++                      log(L_IOCTL, "regulatory domain is currently set "
++                              "to %d (0x%X): %s\n", i, dom,
++                              acx_reg_domain_strings[i-1]);
++                      *extra = i;
++                      break;
++              }
++      }
++
++      return OK;
++}
++
++
++/***********************************************************************
++** acx_ioctl_set_short_preamble
++*/
++static const char * const
++preamble_modes[] = {
++      "off",
++      "on",
++      "auto (peer capability dependent)",
++      "unknown mode, error"
++};
++
++static int
++acx_ioctl_set_short_preamble(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      union iwreq_data *wrqu,
++      char *extra)
++{
++      acx_device_t *adev = ndev2adev(ndev);
++      int i;
++      int result;
++
++      FN_ENTER;
++
++      if ((unsigned char)*extra > 2) {
++              result = -EINVAL;
++              goto end;
++      }
++
++      acx_sem_lock(adev);
++
++      adev->preamble_mode = (u8)*extra;
++      switch (adev->preamble_mode) {
++      case 0: /* long */
++              adev->preamble_cur = 0;
++              break;
++      case 1:
++              /* short, kick incapable peers */
++              adev->preamble_cur = 1;
++              for (i = 0; i < VEC_SIZE(adev->sta_list); i++) {
++                      client_t *clt = &adev->sta_list[i];
++                      if (!clt->used) continue;
++                      if (!(clt->cap_info & WF_MGMT_CAP_SHORT)) {
++                              clt->used = CLIENT_EMPTY_SLOT_0;
++                      }
++              }
++              switch (adev->mode) {
++              case ACX_MODE_2_STA:
++                      if (adev->ap_client && !adev->ap_client->used) {
++                              /* We kicked our AP :) */
++                              SET_BIT(adev->set_mask, GETSET_RESCAN);
++                      }
++              }
++              break;
++      case 2: /* auto. short only if all peers are short-capable */
++              adev->preamble_cur = 1;
++              for (i = 0; i < VEC_SIZE(adev->sta_list); i++) {
++                      client_t *clt = &adev->sta_list[i];
++                      if (!clt->used) continue;
++                      if (!(clt->cap_info & WF_MGMT_CAP_SHORT)) {
++                              adev->preamble_cur = 0;
++                              break;
++                      }
++              }
++              break;
++      }
++      printk("new short preamble setting: configured %s, active %s\n",
++                      preamble_modes[adev->preamble_mode],
++                      preamble_modes[adev->preamble_cur]);
++      result = OK;
++
++      acx_sem_unlock(adev);
++end:
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/***********************************************************************
++** acx_ioctl_get_short_preamble
++*/
++static int
++acx_ioctl_get_short_preamble(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      union iwreq_data *wrqu,
++      char *extra)
++{
++      acx_device_t *adev = ndev2adev(ndev);
++
++      acx_sem_lock(adev);
++
++      printk("current short preamble setting: configured %s, active %s\n",
++                      preamble_modes[adev->preamble_mode],
++                      preamble_modes[adev->preamble_cur]);
++
++      *extra = (char)adev->preamble_mode;
++
++      acx_sem_unlock(adev);
++
++      return OK;
++}
++
++
++/***********************************************************************
++** acx_ioctl_set_antenna
++**
++** TX and RX antenna can be set separately but this function good
++** for testing 0-4 bits
++*/
++static int
++acx_ioctl_set_antenna(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      union iwreq_data *wrqu,
++      char *extra)
++{
++      acx_device_t *adev = ndev2adev(ndev);
++
++      acx_sem_lock(adev);
++
++      printk("old antenna value: 0x%02X (COMBINED bit mask)\n"
++                   "Rx antenna selection:\n"
++                   "0x00 ant. 1\n"
++                   "0x40 ant. 2\n"
++                   "0x80 full diversity\n"
++                   "0xc0 partial diversity\n"
++                   "0x0f dwell time mask (in units of us)\n"
++                   "Tx antenna selection:\n"
++                   "0x00 ant. 2\n" /* yep, those ARE reversed! */
++                   "0x20 ant. 1\n"
++                   "new antenna value: 0x%02X\n",
++                   adev->antenna, (u8)*extra);
++
++      adev->antenna = (u8)*extra;
++      SET_BIT(adev->set_mask, GETSET_ANTENNA);
++
++      acx_sem_unlock(adev);
++
++      return -EINPROGRESS;
++}
++
++
++/***********************************************************************
++** acx_ioctl_get_antenna
++*/
++static int
++acx_ioctl_get_antenna(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      union iwreq_data *wrqu,
++      char *extra)
++{
++      acx_device_t *adev = ndev2adev(ndev);
++
++      /* no locking. it's pointless to lock a single load */
++      printk("current antenna value: 0x%02X (COMBINED bit mask)\n"
++                   "Rx antenna selection:\n"
++                   "0x00 ant. 1\n"
++                   "0x40 ant. 2\n"
++                   "0x80 full diversity\n"
++                   "0xc0 partial diversity\n"
++                   "Tx antenna selection:\n"
++                   "0x00 ant. 2\n" /* yep, those ARE reversed! */
++                   "0x20 ant. 1\n", adev->antenna);
++
++      return 0;
++}
++
++
++/***********************************************************************
++** acx_ioctl_set_rx_antenna
++**
++** 0 = antenna1; 1 = antenna2; 2 = full diversity; 3 = partial diversity
++** Could anybody test which antenna is the external one?
++*/
++static int
++acx_ioctl_set_rx_antenna(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      union iwreq_data *wrqu,
++      char *extra)
++{
++      acx_device_t *adev = ndev2adev(ndev);
++      int result;
++
++      FN_ENTER;
++
++      if (*extra > 3) {
++              result = -EINVAL;
++              goto end;
++      }
++
++      printk("old antenna value: 0x%02X\n", adev->antenna);
++
++      acx_sem_lock(adev);
++
++      adev->antenna &= 0x3f;
++      SET_BIT(adev->antenna, (*extra << 6));
++      SET_BIT(adev->set_mask, GETSET_ANTENNA);
++      printk("new antenna value: 0x%02X\n", adev->antenna);
++      result = -EINPROGRESS;
++
++      acx_sem_unlock(adev);
++end:
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/***********************************************************************
++** acx_ioctl_set_tx_antenna
++**
++** Arguments: 0 == antenna2; 1 == antenna1;
++** Could anybody test which antenna is the external one?
++*/
++static int
++acx_ioctl_set_tx_antenna(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      union iwreq_data *wrqu,
++      char *extra)
++{
++      acx_device_t *adev = ndev2adev(ndev);
++      int result;
++
++      FN_ENTER;
++
++      if (*extra > 1) {
++              result = -EINVAL;
++              goto end;
++      }
++
++      printk("old antenna value: 0x%02X\n", adev->antenna);
++
++      acx_sem_lock(adev);
++
++      adev->antenna &= ~0x30;
++      SET_BIT(adev->antenna, ((*extra & 0x01) << 5));
++      SET_BIT(adev->set_mask, GETSET_ANTENNA);
++      printk("new antenna value: 0x%02X\n", adev->antenna);
++      result = -EINPROGRESS;
++
++      acx_sem_unlock(adev);
++end:
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/***********************************************************************
++** acx_ioctl_wlansniff
++**
++** can we just remove this in favor of monitor mode? --vda
++*/
++static int
++acx_ioctl_wlansniff(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      union iwreq_data *wrqu,
++      char *extra)
++{
++      acx_device_t *adev = ndev2adev(ndev);
++      unsigned int *params = (unsigned int*)extra;
++      unsigned int enable = (unsigned int)(params[0] > 0);
++      int result;
++
++      FN_ENTER;
++
++      acx_sem_lock(adev);
++
++      /* not using printk() here, since it distorts kismet display
++       * when printk messages activated */
++      log(L_IOCTL, "setting monitor to: 0x%02X\n", params[0]);
++
++      switch (params[0]) {
++      case 0:
++              /* no monitor mode. hmm, should we simply ignore it
++               * or go back to enabling adev->netdev->type ARPHRD_ETHER? */
++              break;
++      case 1:
++              adev->monitor_type = ARPHRD_IEEE80211_PRISM;
++              break;
++      case 2:
++              adev->monitor_type = ARPHRD_IEEE80211;
++              break;
++      }
++
++      if (params[0]) {
++              adev->mode = ACX_MODE_MONITOR;
++              SET_BIT(adev->set_mask, GETSET_MODE);
++      }
++
++      if (enable) {
++              adev->channel = params[1];
++              SET_BIT(adev->set_mask, GETSET_RX);
++      }
++      result = -EINPROGRESS;
++
++      acx_sem_unlock(adev);
++
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/***********************************************************************
++** acx_ioctl_unknown11
++** FIXME: looks like some sort of "iwpriv kick_sta MAC" but it's broken
++*/
++static int
++acx_ioctl_unknown11(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      union iwreq_data *wrqu,
++      char *extra)
++{
++#ifdef BROKEN
++      struct iw_param *vwrq = &wrqu->param;
++      acx_device_t *adev = ndev2adev(ndev);
++      unsigned long flags;
++      client_t client;
++      int result;
++
++      acx_sem_lock(adev);
++      acx_lock(adev, flags);
++
++      acx_l_transmit_disassoc(adev, &client);
++      result = OK;
++
++      acx_unlock(adev, flags);
++      acx_sem_unlock(adev);
++
++      return result;
++#endif
++      return -EINVAL;
++}
++
++
++/***********************************************************************
++** debug helper function to be able to debug various issues relatively easily
++*/
++static int
++acx_ioctl_dbg_set_masks(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      union iwreq_data *wrqu,
++      char *extra)
++{
++      acx_device_t *adev = ndev2adev(ndev);
++      const unsigned int *params = (unsigned int*)extra;
++      int result;
++
++      acx_sem_lock(adev);
++
++      log(L_IOCTL, "setting flags in settings mask: "
++                      "get_mask %08X set_mask %08X\n"
++                      "before: get_mask %08X set_mask %08X\n",
++                      params[0], params[1],
++                      adev->get_mask, adev->set_mask);
++      SET_BIT(adev->get_mask, params[0]);
++      SET_BIT(adev->set_mask, params[1]);
++      log(L_IOCTL, "after: get_mask %08X set_mask %08X\n",
++                      adev->get_mask, adev->set_mask);
++      result = -EINPROGRESS; /* immediately call commit handler */
++
++      acx_sem_unlock(adev);
++
++      return result;
++}
++
++
++/***********************************************************************
++* acx_ioctl_set_rates
++*
++* This ioctl takes string parameter. Examples:
++* iwpriv wlan0 SetRates "1,2"
++*     use 1 and 2 Mbit rates, both are in basic rate set
++* iwpriv wlan0 SetRates "1,2 5,11"
++*     use 1,2,5.5,11 Mbit rates. 1 and 2 are basic
++* iwpriv wlan0 SetRates "1,2 5c,11c"
++*     same ('c' means 'CCK modulation' and it is a default for 5 and 11)
++* iwpriv wlan0 SetRates "1,2 5p,11p"
++*     use 1,2,5.5,11 Mbit, 1,2 are basic. 5 and 11 are using PBCC
++* iwpriv wlan0 SetRates "1,2,5,11 22p"
++*     use 1,2,5.5,11,22 Mbit. 1,2,5.5 and 11 are basic. 22 is using PBCC
++*     (this is the maximum acx100 can do (modulo x4 mode))
++* iwpriv wlan0 SetRates "1,2,5,11 22"
++*     same. 802.11 defines only PBCC modulation
++*     for 22 and 33 Mbit rates, so there is no ambiguity
++* iwpriv wlan0 SetRates "1,2,5,11 6o,9o,12o,18o,24o,36o,48o,54o"
++*     1,2,5.5 and 11 are basic. 11g OFDM rates are enabled but
++*     they are not in basic rate set. 22 Mbit is disabled.
++* iwpriv wlan0 SetRates "1,2,5,11 6,9,12,18,24,36,48,54"
++*     same. OFDM is default for 11g rates except 22 and 33 Mbit,
++*     thus 'o' is optional
++* iwpriv wlan0 SetRates "1,2,5,11 6d,9d,12d,18d,24d,36d,48d,54d"
++*     1,2,5.5 and 11 are basic. 11g CCK-OFDM rates are enabled
++*     (acx111 does not support CCK-OFDM, driver will reject this cmd)
++* iwpriv wlan0 SetRates "6,9,12 18,24,36,48,54"
++*     6,9,12 are basic, rest of 11g rates is enabled. Using OFDM
++*/
++#include "setrate.c"
++
++/* disallow: 33Mbit (unsupported by hw) */
++/* disallow: CCKOFDM (unsupported by hw) */
++static int
++acx111_supported(int mbit, int modulation, void *opaque)
++{
++      if (mbit==33) return -ENOTSUPP;
++      if (modulation==DOT11_MOD_CCKOFDM) return -ENOTSUPP;
++      return OK;
++}
++
++static const u16
++acx111mask[] = {
++      [DOT11_RATE_1 ] = RATE111_1 ,
++      [DOT11_RATE_2 ] = RATE111_2 ,
++      [DOT11_RATE_5 ] = RATE111_5 ,
++      [DOT11_RATE_11] = RATE111_11,
++      [DOT11_RATE_22] = RATE111_22,
++      /* [DOT11_RATE_33] = */
++      [DOT11_RATE_6 ] = RATE111_6 ,
++      [DOT11_RATE_9 ] = RATE111_9 ,
++      [DOT11_RATE_12] = RATE111_12,
++      [DOT11_RATE_18] = RATE111_18,
++      [DOT11_RATE_24] = RATE111_24,
++      [DOT11_RATE_36] = RATE111_36,
++      [DOT11_RATE_48] = RATE111_48,
++      [DOT11_RATE_54] = RATE111_54,
++};
++
++static u32
++acx111_gen_mask(int mbit, int modulation, void *opaque)
++{
++      /* lower 16 bits show selected 1, 2, CCK and OFDM rates */
++      /* upper 16 bits show selected PBCC rates */
++      u32 m = acx111mask[rate_mbit2enum(mbit)];
++      if (modulation==DOT11_MOD_PBCC)
++              return m<<16;
++      return m;
++}
++
++static int
++verify_rate(u32 rate, int chip_type)
++{
++      /* never happens. be paranoid */
++      if (!rate) return -EINVAL;
++
++      /* disallow: mixing PBCC and CCK at 5 and 11Mbit
++      ** (can be supported, but needs complicated handling in tx code) */
++      if (( rate & ((RATE111_11+RATE111_5)<<16) )
++      &&  ( rate & (RATE111_11+RATE111_5) )
++      ) {
++              return -ENOTSUPP;
++      }
++      if (CHIPTYPE_ACX100 == chip_type) {
++              if ( rate & ~(RATE111_ACX100_COMPAT+(RATE111_ACX100_COMPAT<<16)) )
++                      return -ENOTSUPP;
++      }
++      return 0;
++}
++
++static int
++acx_ioctl_set_rates(struct net_device *ndev,
++      struct iw_request_info *info,
++      union iwreq_data *wrqu,
++      char *extra)
++{
++      acx_device_t *adev = ndev2adev(ndev);
++      unsigned long flags;
++      int result;
++      u32 brate = 0, orate = 0; /* basic, operational rate set */
++
++      FN_ENTER;
++
++      log(L_IOCTL, "set_rates %s\n", extra);
++      result = fill_ratemasks(extra, &brate, &orate,
++                              acx111_supported, acx111_gen_mask, 0);
++      if (result) goto end;
++      SET_BIT(orate, brate);
++      log(L_IOCTL, "brate %08X orate %08X\n", brate, orate);
++
++      result = verify_rate(brate, adev->chip_type);
++      if (result) goto end;
++      result = verify_rate(orate, adev->chip_type);
++      if (result) goto end;
++
++      acx_sem_lock(adev);
++      acx_lock(adev, flags);
++
++      adev->rate_basic = brate;
++      adev->rate_oper = orate;
++      /* TODO: ideally, we shall monitor highest basic rate
++      ** which was successfully sent to every peer
++      ** (say, last we checked, everybody could hear 5.5 Mbits)
++      ** and use that for bcasts when we want to reach all peers.
++      ** For beacons, we probably shall use lowest basic rate
++      ** because we want to reach all *potential* new peers too */
++      adev->rate_bcast = 1 << lowest_bit(brate);
++      if (IS_ACX100(adev))
++              adev->rate_bcast100 = acx_rate111to100(adev->rate_bcast);
++      adev->rate_auto = !has_only_one_bit(orate);
++      acx_l_update_client_rates(adev, orate);
++      /* TODO: get rid of ratevector, build it only when needed */
++      acx_l_update_ratevector(adev);
++
++      /* Do/don't do tx rate fallback; beacon contents and rate */
++      SET_BIT(adev->set_mask, SET_RATE_FALLBACK|SET_TEMPLATES);
++      result = -EINPROGRESS;
++
++      acx_unlock(adev, flags);
++      acx_sem_unlock(adev);
++end:
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/***********************************************************************
++** acx_ioctl_get_phy_chan_busy_percentage
++*/
++static int
++acx_ioctl_get_phy_chan_busy_percentage(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      union iwreq_data *wrqu,
++      char *extra)
++{
++      acx_device_t *adev = ndev2adev(ndev);
++      struct {
++              u16 type;
++              u16 len;
++              u32 busytime;
++              u32 totaltime;
++      } ACX_PACKED usage;
++      int result;
++
++      acx_sem_lock(adev);
++
++      if (OK != acx_s_interrogate(adev, &usage, ACX1xx_IE_MEDIUM_USAGE)) {
++              result = NOT_OK;
++              goto end_unlock;
++      }
++
++      usage.busytime = le32_to_cpu(usage.busytime);
++      usage.totaltime = le32_to_cpu(usage.totaltime);
++      
++      /* yes, this is supposed to be "Medium" (singular of media),
++         not "average"! OK, reword the message to make it obvious... */
++      printk("%s: busy percentage of medium (since last invocation): %d%% "
++              "(%u of %u microseconds)\n",
++              ndev->name,
++              usage.busytime / ((usage.totaltime / 100) + 1),
++              usage.busytime, usage.totaltime);
++
++      result = OK;
++
++end_unlock:
++      acx_sem_unlock(adev);
++
++      return result;
++}
++
++
++/***********************************************************************
++** acx_ioctl_set_ed_threshold
++*/
++static inline int
++acx_ioctl_set_ed_threshold(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      union iwreq_data *wrqu,
++      char *extra)
++{
++      acx_device_t *adev = ndev2adev(ndev);
++
++      acx_sem_lock(adev);
++
++      printk("old ED threshold value: %d\n", adev->ed_threshold);
++      adev->ed_threshold = (unsigned char)*extra;
++      printk("new ED threshold value: %d\n", (unsigned char)*extra);
++      SET_BIT(adev->set_mask, GETSET_ED_THRESH);
++
++      acx_sem_unlock(adev);
++
++      return -EINPROGRESS;
++}
++
++
++/***********************************************************************
++** acx_ioctl_set_cca
++*/
++static inline int
++acx_ioctl_set_cca(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      union iwreq_data *wrqu,
++      char *extra)
++{
++      acx_device_t *adev = ndev2adev(ndev);
++      int result;
++
++      acx_sem_lock(adev);
++
++      printk("old CCA value: 0x%02X\n", adev->cca);
++      adev->cca = (unsigned char)*extra;
++      printk("new CCA value: 0x%02X\n", (unsigned char)*extra);
++      SET_BIT(adev->set_mask, GETSET_CCA);
++      result = -EINPROGRESS;
++
++      acx_sem_unlock(adev);
++
++      return result;
++}
++
++
++/***********************************************************************
++*/
++static const char * const
++scan_modes[] = { "active", "passive", "background" };
++
++static void
++acx_print_scan_params(acx_device_t *adev, const char* head)
++{
++      printk("%s: %smode %d (%s), min chan time %dTU, "
++              "max chan time %dTU, max scan rate byte: %d\n",
++              adev->ndev->name, head,
++              adev->scan_mode, scan_modes[adev->scan_mode],
++              adev->scan_probe_delay, adev->scan_duration, adev->scan_rate);
++}
++
++static int
++acx_ioctl_set_scan_params(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      union iwreq_data *wrqu,
++      char *extra)
++{
++      acx_device_t *adev = ndev2adev(ndev);
++      int result;
++      const int *params = (int *)extra;
++
++      acx_sem_lock(adev);
++
++      acx_print_scan_params(adev, "old scan parameters: ");
++      if ((params[0] != -1) && (params[0] >= 0) && (params[0] <= 2))
++              adev->scan_mode = params[0];
++      if (params[1] != -1)
++              adev->scan_probe_delay = params[1];
++      if (params[2] != -1)
++              adev->scan_duration = params[2];
++      if ((params[3] != -1) && (params[3] <= 255))
++              adev->scan_rate = params[3];
++      acx_print_scan_params(adev, "new scan parameters: ");
++      SET_BIT(adev->set_mask, GETSET_RESCAN);
++      result = -EINPROGRESS;
++
++      acx_sem_unlock(adev);
++
++      return result;
++}
++
++static int
++acx_ioctl_get_scan_params(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      union iwreq_data *wrqu,
++      char *extra)
++{
++      acx_device_t *adev = ndev2adev(ndev);
++      int result;
++      int *params = (int *)extra;
++
++      acx_sem_lock(adev);
++
++      acx_print_scan_params(adev, "current scan parameters: ");
++      params[0] = adev->scan_mode;
++      params[1] = adev->scan_probe_delay;
++      params[2] = adev->scan_duration;
++      params[3] = adev->scan_rate;
++      result = OK;
++
++      acx_sem_unlock(adev);
++
++      return result;
++}
++
++
++/***********************************************************************
++*/
++static int
++acx100_ioctl_set_led_power(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      union iwreq_data *wrqu,
++      char *extra)
++{
++      static const char * const led_modes[] = { "off", "on", "LinkQuality" };
++
++      acx_device_t *adev = ndev2adev(ndev);
++      int result;
++
++      acx_sem_lock(adev);
++
++      printk("%s: power LED status: old %d (%s), ",
++                      ndev->name,
++                      adev->led_power,
++                      led_modes[adev->led_power]);
++      adev->led_power = extra[0];
++      if (adev->led_power > 2) adev->led_power = 2;
++      printk("new %d (%s)\n",
++                      adev->led_power,
++                      led_modes[adev->led_power]);
++
++      if (adev->led_power == 2) {
++              printk("%s: max link quality setting: old %d, ",
++                      ndev->name, adev->brange_max_quality);
++              if (extra[1])
++                      adev->brange_max_quality = extra[1];
++              printk("new %d\n", adev->brange_max_quality);
++      }
++
++      SET_BIT(adev->set_mask, GETSET_LED_POWER);
++
++      result = -EINPROGRESS;
++
++      acx_sem_unlock(adev);
++
++      return result;
++}
++
++
++/***********************************************************************
++*/
++static inline int
++acx100_ioctl_get_led_power(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      union iwreq_data *wrqu,
++      char *extra)
++{
++      acx_device_t *adev = ndev2adev(ndev);
++
++      acx_sem_lock(adev);
++
++      extra[0] = adev->led_power;
++      if (adev->led_power == 2)
++              extra[1] = adev->brange_max_quality;
++      else
++              extra[1] = -1;
++
++      acx_sem_unlock(adev);
++
++      return OK;
++}
++
++
++/***********************************************************************
++*/
++static int
++acx111_ioctl_info(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      union iwreq_data *wrqu,
++      char *extra)
++{
++      struct iw_param *vwrq = &wrqu->param;
++      if (!IS_PCI(ndev2adev(ndev)))
++              return OK;
++      return acx111pci_ioctl_info(ndev, info, vwrq, extra);
++}
++
++
++/***********************************************************************
++*/
++static int
++acx100_ioctl_set_phy_amp_bias(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      union iwreq_data *wrqu,
++      char *extra)
++{
++      struct iw_param *vwrq = &wrqu->param;
++      if (IS_USB(ndev2adev(ndev))) {
++              printk("acx: set_phy_amp_bias() is not supported on USB\n");
++              return OK;
++      }
++#ifdef ACX_MEM
++      return acx100mem_ioctl_set_phy_amp_bias(ndev, info, vwrq, extra);
++#else
++      return acx100pci_ioctl_set_phy_amp_bias(ndev, info, vwrq, extra);
++#endif
++}
++
++
++/***********************************************************************
++*/
++static const iw_handler acx_ioctl_handler[] =
++{
++      acx_ioctl_commit,               /* SIOCSIWCOMMIT */
++      acx_ioctl_get_name,             /* SIOCGIWNAME */
++      NULL,                           /* SIOCSIWNWID */
++      NULL,                           /* SIOCGIWNWID */
++      acx_ioctl_set_freq,             /* SIOCSIWFREQ */
++      acx_ioctl_get_freq,             /* SIOCGIWFREQ */
++      acx_ioctl_set_mode,             /* SIOCSIWMODE */
++      acx_ioctl_get_mode,             /* SIOCGIWMODE */
++      acx_ioctl_set_sens,             /* SIOCSIWSENS */
++      acx_ioctl_get_sens,             /* SIOCGIWSENS */
++      NULL,                           /* SIOCSIWRANGE */
++      acx_ioctl_get_range,            /* SIOCGIWRANGE */
++      NULL,                           /* SIOCSIWPRIV */
++      NULL,                           /* SIOCGIWPRIV */
++      NULL,                           /* SIOCSIWSTATS */
++      NULL,                           /* SIOCGIWSTATS */
++#if IW_HANDLER_VERSION > 4
++      iw_handler_set_spy,             /* SIOCSIWSPY */
++      iw_handler_get_spy,             /* SIOCGIWSPY */
++      iw_handler_set_thrspy,          /* SIOCSIWTHRSPY */
++      iw_handler_get_thrspy,          /* SIOCGIWTHRSPY */
++#else /* IW_HANDLER_VERSION > 4 */
++#ifdef WIRELESS_SPY
++      NULL /* acx_ioctl_set_spy FIXME */,     /* SIOCSIWSPY */
++      NULL /* acx_ioctl_get_spy */,   /* SIOCGIWSPY */
++#else /* WSPY */
++      NULL,                           /* SIOCSIWSPY */
++      NULL,                           /* SIOCGIWSPY */
++#endif /* WSPY */
++      NULL,                           /* [nothing] */
++      NULL,                           /* [nothing] */
++#endif /* IW_HANDLER_VERSION > 4 */
++      acx_ioctl_set_ap,               /* SIOCSIWAP */
++      acx_ioctl_get_ap,               /* SIOCGIWAP */
++      NULL,                           /* [nothing] */
++      acx_ioctl_get_aplist,           /* SIOCGIWAPLIST */
++      acx_ioctl_set_scan,             /* SIOCSIWSCAN */
++      acx_ioctl_get_scan,             /* SIOCGIWSCAN */
++      acx_ioctl_set_essid,            /* SIOCSIWESSID */
++      acx_ioctl_get_essid,            /* SIOCGIWESSID */
++      acx_ioctl_set_nick,             /* SIOCSIWNICKN */
++      acx_ioctl_get_nick,             /* SIOCGIWNICKN */
++      NULL,                           /* [nothing] */
++      NULL,                           /* [nothing] */
++      acx_ioctl_set_rate,             /* SIOCSIWRATE */
++      acx_ioctl_get_rate,             /* SIOCGIWRATE */
++      acx_ioctl_set_rts,              /* SIOCSIWRTS */
++      acx_ioctl_get_rts,              /* SIOCGIWRTS */
++#if ACX_FRAGMENTATION
++      acx_ioctl_set_frag,             /* SIOCSIWFRAG */
++      acx_ioctl_get_frag,             /* SIOCGIWFRAG */
++#else
++      NULL,                           /* SIOCSIWFRAG */
++      NULL,                           /* SIOCGIWFRAG */
++#endif
++      acx_ioctl_set_txpow,            /* SIOCSIWTXPOW */
++      acx_ioctl_get_txpow,            /* SIOCGIWTXPOW */
++      acx_ioctl_set_retry,            /* SIOCSIWRETRY */
++      acx_ioctl_get_retry,            /* SIOCGIWRETRY */
++      acx_ioctl_set_encode,           /* SIOCSIWENCODE */
++      acx_ioctl_get_encode,           /* SIOCGIWENCODE */
++      acx_ioctl_set_power,            /* SIOCSIWPOWER */
++      acx_ioctl_get_power,            /* SIOCGIWPOWER */
++};
++
++
++/***********************************************************************
++*/
++
++/* if you plan to reorder something, make sure to reorder all other places
++ * accordingly! */
++/* SET/GET convention: SETs must have even position, GETs odd */
++#define ACX100_IOCTL SIOCIWFIRSTPRIV
++enum {
++      ACX100_IOCTL_DEBUG = ACX100_IOCTL,
++      ACX100_IOCTL_GET__________UNUSED1,
++      ACX100_IOCTL_SET_PLED,
++      ACX100_IOCTL_GET_PLED,
++      ACX100_IOCTL_SET_RATES,
++      ACX100_IOCTL_LIST_DOM,
++      ACX100_IOCTL_SET_DOM,
++      ACX100_IOCTL_GET_DOM,
++      ACX100_IOCTL_SET_SCAN_PARAMS,
++      ACX100_IOCTL_GET_SCAN_PARAMS,
++      ACX100_IOCTL_SET_PREAMB,
++      ACX100_IOCTL_GET_PREAMB,
++      ACX100_IOCTL_SET_ANT,
++      ACX100_IOCTL_GET_ANT,
++      ACX100_IOCTL_RX_ANT,
++      ACX100_IOCTL_TX_ANT,
++      ACX100_IOCTL_SET_PHY_AMP_BIAS,
++      ACX100_IOCTL_GET_PHY_CHAN_BUSY,
++      ACX100_IOCTL_SET_ED,
++      ACX100_IOCTL_GET__________UNUSED3,
++      ACX100_IOCTL_SET_CCA,
++      ACX100_IOCTL_GET__________UNUSED4,
++      ACX100_IOCTL_MONITOR,
++      ACX100_IOCTL_TEST,
++      ACX100_IOCTL_DBG_SET_MASKS,
++      ACX111_IOCTL_INFO,
++      ACX100_IOCTL_DBG_SET_IO,
++      ACX100_IOCTL_DBG_GET_IO
++};
++
++
++static const iw_handler acx_ioctl_private_handler[] =
++{
++#if ACX_DEBUG
++[ACX100_IOCTL_DEBUG           - ACX100_IOCTL] = acx_ioctl_set_debug,
++#endif
++[ACX100_IOCTL_SET_PLED                - ACX100_IOCTL] = acx100_ioctl_set_led_power,
++[ACX100_IOCTL_GET_PLED                - ACX100_IOCTL] = acx100_ioctl_get_led_power,
++[ACX100_IOCTL_SET_RATES               - ACX100_IOCTL] = acx_ioctl_set_rates,
++[ACX100_IOCTL_LIST_DOM                - ACX100_IOCTL] = acx_ioctl_list_reg_domain,
++[ACX100_IOCTL_SET_DOM         - ACX100_IOCTL] = acx_ioctl_set_reg_domain,
++[ACX100_IOCTL_GET_DOM         - ACX100_IOCTL] = acx_ioctl_get_reg_domain,
++[ACX100_IOCTL_SET_SCAN_PARAMS - ACX100_IOCTL] = acx_ioctl_set_scan_params,
++[ACX100_IOCTL_GET_SCAN_PARAMS - ACX100_IOCTL] = acx_ioctl_get_scan_params,
++[ACX100_IOCTL_SET_PREAMB      - ACX100_IOCTL] = acx_ioctl_set_short_preamble,
++[ACX100_IOCTL_GET_PREAMB      - ACX100_IOCTL] = acx_ioctl_get_short_preamble,
++[ACX100_IOCTL_SET_ANT         - ACX100_IOCTL] = acx_ioctl_set_antenna,
++[ACX100_IOCTL_GET_ANT         - ACX100_IOCTL] = acx_ioctl_get_antenna,
++[ACX100_IOCTL_RX_ANT          - ACX100_IOCTL] = acx_ioctl_set_rx_antenna,
++[ACX100_IOCTL_TX_ANT          - ACX100_IOCTL] = acx_ioctl_set_tx_antenna,
++[ACX100_IOCTL_SET_PHY_AMP_BIAS        - ACX100_IOCTL] = acx100_ioctl_set_phy_amp_bias,
++[ACX100_IOCTL_GET_PHY_CHAN_BUSY       - ACX100_IOCTL] = acx_ioctl_get_phy_chan_busy_percentage,
++[ACX100_IOCTL_SET_ED          - ACX100_IOCTL] = acx_ioctl_set_ed_threshold,
++[ACX100_IOCTL_SET_CCA         - ACX100_IOCTL] = acx_ioctl_set_cca,
++[ACX100_IOCTL_MONITOR         - ACX100_IOCTL] = acx_ioctl_wlansniff,
++[ACX100_IOCTL_TEST            - ACX100_IOCTL] = acx_ioctl_unknown11,
++[ACX100_IOCTL_DBG_SET_MASKS   - ACX100_IOCTL] = acx_ioctl_dbg_set_masks,
++[ACX111_IOCTL_INFO            - ACX100_IOCTL] = acx111_ioctl_info,
++};
++
++
++static const struct iw_priv_args acx_ioctl_private_args[] = {
++#if ACX_DEBUG
++{ cmd : ACX100_IOCTL_DEBUG,
++      set_args : IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
++      get_args : 0,
++      name : "SetDebug" },
++#endif
++{ cmd : ACX100_IOCTL_SET_PLED,
++      set_args : IW_PRIV_TYPE_BYTE | 2,
++      get_args : 0,
++      name : "SetLEDPower" },
++{ cmd : ACX100_IOCTL_GET_PLED,
++      set_args : 0,
++      get_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 2,
++      name : "GetLEDPower" },
++{ cmd : ACX100_IOCTL_SET_RATES,
++      set_args : IW_PRIV_TYPE_CHAR | 256,
++      get_args : 0,
++      name : "SetRates" },
++{ cmd : ACX100_IOCTL_LIST_DOM,
++      set_args : 0,
++      get_args : 0,
++      name : "ListRegDomain" },
++{ cmd : ACX100_IOCTL_SET_DOM,
++      set_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
++      get_args : 0,
++      name : "SetRegDomain" },
++{ cmd : ACX100_IOCTL_GET_DOM,
++      set_args : 0,
++      get_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
++      name : "GetRegDomain" },
++{ cmd : ACX100_IOCTL_SET_SCAN_PARAMS,
++      set_args : IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 4,
++      get_args : 0,
++      name : "SetScanParams" },
++{ cmd : ACX100_IOCTL_GET_SCAN_PARAMS,
++      set_args : 0,
++      get_args : IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 4,
++      name : "GetScanParams" },
++{ cmd : ACX100_IOCTL_SET_PREAMB,
++      set_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
++      get_args : 0,
++      name : "SetSPreamble" },
++{ cmd : ACX100_IOCTL_GET_PREAMB,
++      set_args : 0,
++      get_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
++      name : "GetSPreamble" },
++{ cmd : ACX100_IOCTL_SET_ANT,
++      set_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
++      get_args : 0,
++      name : "SetAntenna" },
++{ cmd : ACX100_IOCTL_GET_ANT,
++      set_args : 0,
++      get_args : 0,
++      name : "GetAntenna" },
++{ cmd : ACX100_IOCTL_RX_ANT,
++      set_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
++      get_args : 0,
++      name : "SetRxAnt" },
++{ cmd : ACX100_IOCTL_TX_ANT,
++      set_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
++      get_args : 0,
++      name : "SetTxAnt" },
++{ cmd : ACX100_IOCTL_SET_PHY_AMP_BIAS,
++      set_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
++      get_args : 0,
++      name : "SetPhyAmpBias"},
++{ cmd : ACX100_IOCTL_GET_PHY_CHAN_BUSY,
++      set_args : 0,
++      get_args : 0,
++      name : "GetPhyChanBusy" },
++{ cmd : ACX100_IOCTL_SET_ED,
++      set_args : IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
++      get_args : 0,
++      name : "SetED" },
++{ cmd : ACX100_IOCTL_SET_CCA,
++      set_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
++      get_args : 0,
++      name : "SetCCA" },
++{ cmd : ACX100_IOCTL_MONITOR,
++      set_args : IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2,
++      get_args : 0,
++      name : "monitor" },
++{ cmd : ACX100_IOCTL_TEST,
++      set_args : 0,
++      get_args : 0,
++      name : "Test" },
++{ cmd : ACX100_IOCTL_DBG_SET_MASKS,
++      set_args : IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2,
++      get_args : 0,
++      name : "DbgSetMasks" },
++{ cmd : ACX111_IOCTL_INFO,
++      set_args : 0,
++      get_args : 0,
++      name : "GetAcx111Info" },
++{ cmd : ACX100_IOCTL_DBG_SET_IO,
++      set_args : IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 4,
++      get_args : 0,
++      name : "DbgSetIO" },
++{ cmd : ACX100_IOCTL_DBG_GET_IO,
++      set_args : IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3,
++      get_args : 0,
++      name : "DbgGetIO" },
++};
++
++
++const struct iw_handler_def acx_ioctl_handler_def =
++{
++      .num_standard = VEC_SIZE(acx_ioctl_handler),
++      .num_private = VEC_SIZE(acx_ioctl_private_handler),
++      .num_private_args = VEC_SIZE(acx_ioctl_private_args),
++      .standard = (iw_handler *) acx_ioctl_handler,
++      .private = (iw_handler *) acx_ioctl_private_handler,
++      .private_args = (struct iw_priv_args *) acx_ioctl_private_args,
++#if IW_HANDLER_VERSION > 5
++      .get_wireless_stats = acx_e_get_wireless_stats
++#endif /* IW > 5 */
++};
+Index: linux-2.6.22/drivers/net/wireless/acx/Kconfig
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/drivers/net/wireless/acx/Kconfig      2007-08-23 18:34:19.000000000 +0200
+@@ -0,0 +1,113 @@
++config ACX
++      tristate "TI acx100/acx111 802.11b/g wireless chipsets"
++      depends on NET_RADIO && EXPERIMENTAL
++      select FW_LOADER
++      ---help---
++      A driver for 802.11b/g wireless cards based on
++      Texas Instruments acx100 and acx111 chipsets.
++
++      This driver supports Host AP mode that allows
++      your computer to act as an IEEE 802.11 access point.
++      This driver is new and experimental.
++
++      Texas Instruments did not take part in development of this driver
++      in any way, shape or form.
++
++      The driver can be compiled as a module and will be named "acx".
++
++config ACX_PCI
++      bool "TI acx100/acx111 802.11b/g PCI"
++      depends on ACX && PCI
++      ---help---
++      Include PCI and CardBus support in acx.
++
++      acx chipsets need their firmware loaded at startup.
++      You will need to provide a firmware image via hotplug.
++
++      Firmware may be in a form of single image 40-100kb in size
++      (a 'combined' firmware) or two images - main image
++      (again 40-100kb) and radio image (~10kb or less).
++
++      Firmware images are requested from hotplug using following names:
++
++      tiacx100 - main firmware image for acx100 chipset
++      tiacx100rNN - radio acx100 firmware for radio type NN
++      tiacx100cNN - combined acx100 firmware for radio type NN
++      tiacx111 - main acx111 firmware
++      tiacx111rNN - radio acx111 firmware for radio type NN
++      tiacx111cNN - combined acx111 firmware for radio type NN
++
++      Driver will attempt to load combined image first.
++      If no such image is found, it will try to load main image
++      and radio image instead.
++
++      Firmware files are not covered by GPL and are not distributed
++      with this driver for legal reasons.
++
++config ACX_USB
++      bool "TI acx100/acx111 802.11b/g USB"
++      depends on ACX && (USB=y || USB=ACX)
++      ---help---
++      Include USB support in acx.
++
++      There is only one currently known device in this category,
++      D-Link DWL-120+, but newer devices seem to be on the horizon.
++
++      acx chipsets need their firmware loaded at startup.
++      You will need to provide a firmware image via hotplug.
++
++      Firmware for USB device is requested from hotplug
++      by the 'tiacx100usb' name.
++
++      Firmware files are not covered by GPL and are not distributed
++      with this driver for legal reasons.
++
++config ACX_MEM
++      bool "TI acx100/acx111 802.11b/g memory mapped slave 16 interface"
++      depends on ACX
++      ---help---
++      acx chipsets need their firmware loaded at startup.
++      You will need to provide a firmware image via hotplug.
++
++      Firmware for USB device is requested from hotplug
++      by the 'tiacx100usb' name.
++
++      Firmware files are not covered by GPL and are not distributed
++      with this driver for legal reasons.
++
++config ACX_CS
++      bool "TI acx100/acx111 802.11b/g cardbus interface"
++      depends on ACX
++      ---help---
++      acx chipsets need their firmware loaded at startup.
++      You will need to provide a firmware image via hotplug.
++      
++      This driver is based on memory mapped driver.
++
++      Firmware files are not covered by GPL and are not distributed
++      with this driver for legal reasons.
++
++config ACX_HX4700
++      tristate "ACX support for the iPAQ hx4700 using ACX_MEM"
++      depends on HX4700_CORE && ACX_MEM
++      ---help---
++      Include memory interface support in acx for the iPAQ hx4700.
++
++config ACX_HTCUNIVERSAL
++      tristate "ACX support for the HTC Universal using ACX_MEM"
++      depends on HTCUNIVERSAL_CORE && HTC_ASIC3 && ACX_MEM
++      ---help---
++      Include memory interface support in acx for the HTC Universal.
++
++config ACX_HTCSABLE
++      tristate "ACX support for the HTC Sable (IPAQ hw6915) using ACX_MEM"
++      depends on MACH_HW6900 && HTC_ASIC3 && ACX_MEM
++      ---help---
++      Include memory interface support in acx for the HTC Sable (IPAQ hw6915).
++
++config ACX_RX3000
++      tristate "ACX support for the iPAQ RX3000 using ACX_MEM"
++      depends on MACH_RX3715 && ACX_MEM && LEDS_ASIC3
++      ---help---
++      Include memory interface support in acx for the IPAQ RX3000.
++
+Index: linux-2.6.22/drivers/net/wireless/acx/Makefile
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/drivers/net/wireless/acx/Makefile     2007-08-23 18:34:19.000000000 +0200
+@@ -0,0 +1,21 @@
++#obj-m += acx.o
++
++#acx-obj-y += pci.o
++#acx-obj-y += usb.o
++
++#acx-objs := wlan.o conv.o ioctl.o common.o $(acx-obj-y)
++
++# Use this if you have proper Kconfig integration:
++
++obj-$(CONFIG_ACX) += acx.o
++obj-$(CONFIG_ACX_HX4700) += hx4700_acx.o
++obj-$(CONFIG_ACX_HTCUNIVERSAL) += htcuniversal_acx.o
++obj-$(CONFIG_ACX_HTCSABLE) += htcsable_acx.o
++obj-$(CONFIG_ACX_RX3000) += rx3000_acx.o
++#
++acx-obj-$(CONFIG_ACX_PCI) += pci.o
++acx-obj-$(CONFIG_ACX_USB) += usb.o
++acx-obj-$(CONFIG_ACX_MEM) += mem.o
++acx-obj-$(CONFIG_ACX_CS) += cs.o
++#
++acx-objs := wlan.o conv.o ioctl.o common.o $(acx-obj-y)
+Index: linux-2.6.22/drivers/net/wireless/acx/mem.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/drivers/net/wireless/acx/mem.c        2007-08-23 18:34:19.000000000 +0200
+@@ -0,0 +1,5363 @@
++/***********************************************************************
++** Copyright (C) 2003  ACX100 Open Source Project
++**
++** The contents of this file are subject to the Mozilla Public
++** License Version 1.1 (the "License"); you may not use this file
++** except in compliance with the License. You may obtain a copy of
++** the License at http://www.mozilla.org/MPL/
++**
++** Software distributed under the License is distributed on an "AS
++** IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
++** implied. See the License for the specific language governing
++** rights and limitations under the License.
++**
++** Alternatively, the contents of this file may be used under the
++** terms of the GNU Public License version 2 (the "GPL"), in which
++** case the provisions of the GPL are applicable instead of the
++** above.  If you wish to allow the use of your version of this file
++** only under the terms of the GPL and not to allow others to use
++** your version of this file under the MPL, indicate your decision
++** by deleting the provisions above and replace them with the notice
++** and other provisions required by the GPL.  If you do not delete
++** the provisions above, a recipient may use your version of this
++** file under either the MPL or the GPL.
++** ---------------------------------------------------------------------
++** Inquiries regarding the ACX100 Open Source Project can be
++** made directly to:
++**
++** acx100-users@lists.sf.net
++** http://acx100.sf.net
++** ---------------------------------------------------------------------
++**
++** Slave memory interface support:
++**
++** Todd Blumer - SDG Systems
++** Bill Reese - HP
++** Eric McCorkle - Shadowsun
++*/
++#define ACX_MEM 1
++
++/*
++ * non-zero makes it dump the ACX memory to the console then
++ * panic when you cat /proc/driver/acx_wlan0_diag
++ */
++#define DUMP_MEM_DEFINED 1
++
++#define DUMP_MEM_DURING_DIAG 0
++#define DUMP_IF_SLOW 0
++
++#define PATCH_AROUND_BAD_SPOTS 1
++#define HX4700_FIRMWARE_CHECKSUM 0x0036862e
++#define HX4700_ALTERNATE_FIRMWARE_CHECKSUM 0x00368a75
++
++#include <linux/version.h>
++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18)
++#include <linux/config.h>
++#endif
++
++/* Linux 2.6.18+ uses <linux/utsrelease.h> */
++#ifndef UTS_RELEASE
++#include <linux/utsrelease.h>
++#endif
++
++#include <linux/compiler.h> /* required for Lx 2.6.8 ?? */
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/sched.h>
++#include <linux/types.h>
++#include <linux/skbuff.h>
++#include <linux/slab.h>
++#include <linux/if_arp.h>
++#include <linux/irq.h>
++#include <linux/rtnetlink.h>
++#include <linux/wireless.h>
++#include <net/iw_handler.h>
++#include <linux/netdevice.h>
++#include <linux/ioport.h>
++#include <linux/pci.h>
++#include <linux/platform_device.h>
++#include <linux/pm.h>
++#include <linux/vmalloc.h>
++#include <linux/delay.h>
++#include <linux/workqueue.h>
++#include <linux/inetdevice.h>
++
++#include "acx.h"
++#include "acx_hw.h"
++
++/***********************************************************************
++*/
++
++#define CARD_EEPROM_ID_SIZE 6
++
++#include <asm/io.h>
++
++#define REG_ACX_VENDOR_ID 0x900
++/*
++ * This is the vendor id on the HX4700, anyway
++ */
++#define ACX_VENDOR_ID 0x8400104c
++
++typedef enum {
++      ACX_SOFT_RESET = 0,
++
++      ACX_SLV_REG_ADDR,
++      ACX_SLV_REG_DATA,
++      ACX_SLV_REG_ADATA,
++
++      ACX_SLV_MEM_CP,
++      ACX_SLV_MEM_ADDR,
++      ACX_SLV_MEM_DATA,
++      ACX_SLV_MEM_CTL,
++} acxreg_t;
++
++/***********************************************************************
++*/
++static void acxmem_i_tx_timeout(struct net_device *ndev);
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
++static irqreturn_t acxmem_i_interrupt(int irq, void *dev_id);
++#else
++static irqreturn_t acxmem_i_interrupt(int irq, void *dev_id, struct pt_regs *regs);
++#endif
++static void acxmem_i_set_multicast_list(struct net_device *ndev);
++
++static int acxmem_e_open(struct net_device *ndev);
++static int acxmem_e_close(struct net_device *ndev);
++static void acxmem_s_up(struct net_device *ndev);
++static void acxmem_s_down(struct net_device *ndev);
++
++static void dump_acxmem (acx_device_t *adev, u32 start, int length);
++static int acxmem_complete_hw_reset (acx_device_t *adev);
++static void acxmem_s_delete_dma_regions(acx_device_t *adev);
++
++static struct platform_device *resume_pdev;
++
++static int
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11)
++acxmem_e_suspend(struct platform_device *pdev, pm_message_t state);
++#else
++acxmem_e_suspend(struct device *pdev, u32 state);
++#endif
++static void
++fw_resumer(struct work_struct *notused);
++//fw_resumer( void *data );
++
++static int acx_netdev_event(struct notifier_block *this, unsigned long event, void *ptr)
++{
++  struct net_device *ndev = ptr;
++  acx_device_t *adev = ndev2adev(ndev);
++
++  /*
++   * Upper level ioctl() handlers send a NETDEV_CHANGEADDR if the MAC address changes.
++   */
++
++  if (NETDEV_CHANGEADDR == event) {
++    /*
++     * the upper layers put the new MAC address in ndev->dev_addr; we just copy
++     * it over and update the ACX with it.
++     */
++    MAC_COPY(adev->dev_addr, adev->ndev->dev_addr);
++    adev->set_mask |= GETSET_STATION_ID;
++    acx_s_update_card_settings (adev);
++  }
++
++  return 0;
++}
++
++static struct notifier_block acx_netdev_notifier = {
++        .notifier_call = acx_netdev_event,
++};
++
++/***********************************************************************
++** Register access
++*/
++
++/* Pick one */
++/* #define INLINE_IO static */
++#define INLINE_IO static inline
++
++INLINE_IO u32
++read_id_register (acx_device_t *adev)
++{
++  writel (0x24, &adev->iobase[ACX_SLV_REG_ADDR]);
++  return readl (&adev->iobase[ACX_SLV_REG_DATA]);
++}
++
++INLINE_IO u32
++read_reg32(acx_device_t *adev, unsigned int offset)
++{
++        u32 val;
++      u32 addr;
++
++        if (offset > IO_ACX_ECPU_CTRL)
++        addr = offset;
++      else
++        addr = adev->io[offset];
++
++      if (addr < 0x20) {
++        return readl(((u8*)adev->iobase) + addr);
++      }
++
++      writel( addr, &adev->iobase[ACX_SLV_REG_ADDR] );
++      val = readl( &adev->iobase[ACX_SLV_REG_DATA] );
++
++      return val;
++}
++
++INLINE_IO u16
++read_reg16(acx_device_t *adev, unsigned int offset)
++{
++      u16 lo;
++      u32 addr;
++
++        if (offset > IO_ACX_ECPU_CTRL)
++        addr = offset;
++      else
++        addr = adev->io[offset];
++
++      if (addr < 0x20) {
++          return readw(((u8 *) adev->iobase) + addr);
++      }
++
++      writel( addr, &adev->iobase[ACX_SLV_REG_ADDR] );
++      lo = readw( (u16 *)&adev->iobase[ACX_SLV_REG_DATA] );
++
++      return lo;
++}
++
++INLINE_IO u8
++read_reg8(acx_device_t *adev, unsigned int offset)
++{
++      u8 lo;
++      u32 addr;
++
++        if (offset > IO_ACX_ECPU_CTRL)
++        addr = offset;
++      else
++        addr = adev->io[offset];
++
++      if (addr < 0x20)
++          return readb(((u8 *)adev->iobase) + addr);
++
++      writel( addr, &adev->iobase[ACX_SLV_REG_ADDR] );
++      lo = readw( (u8 *)&adev->iobase[ACX_SLV_REG_DATA] );
++
++      return (u8)lo;
++}
++
++INLINE_IO void
++write_reg32(acx_device_t *adev, unsigned int offset, u32 val)
++{
++      u32 addr;
++
++        if (offset > IO_ACX_ECPU_CTRL)
++        addr = offset;
++      else
++        addr = adev->io[offset];
++
++      if (addr < 0x20) {
++          writel(val, ((u8*)adev->iobase) + addr);
++          return;
++      }
++
++      writel( addr, &adev->iobase[ACX_SLV_REG_ADDR] );
++      writel( val, &adev->iobase[ACX_SLV_REG_DATA] );
++}
++
++INLINE_IO void
++write_reg16(acx_device_t *adev, unsigned int offset, u16 val)
++{
++      u32 addr;
++
++        if (offset > IO_ACX_ECPU_CTRL)
++        addr = offset;
++      else
++        addr = adev->io[offset];
++
++      if (addr < 0x20) {
++          writew(val, ((u8 *)adev->iobase) + addr);
++          return;
++      }
++      writel( addr, &adev->iobase[ACX_SLV_REG_ADDR] );
++      writew( val, (u16 *) &adev->iobase[ACX_SLV_REG_DATA] );
++}
++
++INLINE_IO void
++write_reg8(acx_device_t *adev, unsigned int offset, u8 val)
++{
++      u32 addr;
++
++        if (offset > IO_ACX_ECPU_CTRL)
++        addr = offset;
++      else
++        addr = adev->io[offset];
++
++      if (addr < 0x20) {
++          writeb(val, ((u8 *) adev->iobase) + addr);
++          return;
++      }
++      writel( addr, &adev->iobase[ACX_SLV_REG_ADDR] );
++      writeb( val, (u8 *)&adev->iobase[ACX_SLV_REG_DATA] );
++}
++
++/* Handle PCI posting properly:
++ * Make sure that writes reach the adapter in case they require to be executed
++ * *before* the next write, by reading a random (and safely accessible) register.
++ * This call has to be made if there is no read following (which would flush the data
++ * to the adapter), yet the written data has to reach the adapter immediately. */
++INLINE_IO void
++write_flush(acx_device_t *adev)
++{
++      /* readb(adev->iobase + adev->io[IO_ACX_INFO_MAILBOX_OFFS]); */
++      /* faster version (accesses the first register, IO_ACX_SOFT_RESET,
++       * which should also be safe): */
++      (void) readl(adev->iobase);
++}
++
++INLINE_IO void
++set_regbits (acx_device_t *adev, unsigned int offset, u32 bits) {
++  u32 tmp;
++
++  tmp = read_reg32 (adev, offset);
++  tmp = tmp | bits;
++  write_reg32 (adev, offset, tmp);
++  write_flush (adev);
++}
++
++INLINE_IO void
++clear_regbits (acx_device_t *adev, unsigned int offset, u32 bits) {
++  u32 tmp;
++
++  tmp = read_reg32 (adev, offset);
++  tmp = tmp & ~bits;
++  write_reg32 (adev, offset, tmp);
++  write_flush (adev);
++}
++
++/*
++ * Copy from PXA memory to the ACX memory.  This assumes both the PXA and ACX
++ * addresses are 32 bit aligned.  Count is in bytes.
++ */
++INLINE_IO void
++write_slavemem32 (acx_device_t *adev, u32 slave_address, u32 val)
++{
++  write_reg32 (adev, IO_ACX_SLV_MEM_CTL, 0x0);
++  write_reg32 (adev, IO_ACX_SLV_MEM_ADDR, slave_address);
++  udelay (10);
++  write_reg32 (adev, IO_ACX_SLV_MEM_DATA, val);
++}
++
++INLINE_IO u32
++read_slavemem32 (acx_device_t *adev, u32 slave_address)
++{
++  u32 val;
++
++  write_reg32 (adev, IO_ACX_SLV_MEM_CTL, 0x0);
++  write_reg32 (adev, IO_ACX_SLV_MEM_ADDR, slave_address);
++  udelay (10);
++  val = read_reg32 (adev, IO_ACX_SLV_MEM_DATA);
++
++  return val;
++}
++
++INLINE_IO void
++write_slavemem8 (acx_device_t *adev, u32 slave_address, u8 val)
++{
++  u32 data;
++  u32 base;
++  int offset;
++
++  /*
++   * Get the word containing the target address and the byte offset in that word.
++   */
++  base = slave_address & ~3;
++  offset = (slave_address & 3) * 8;
++
++  data = read_slavemem32 (adev, base);
++  data &= ~(0xff << offset);
++  data |= val << offset;
++  write_slavemem32 (adev, base, data);
++}
++
++INLINE_IO u8
++read_slavemem8 (acx_device_t *adev, u32 slave_address)
++{
++  u8 val;
++  u32 base;
++  u32 data;
++  int offset;
++
++  base = slave_address & ~3;
++  offset = (slave_address & 3) * 8;
++
++  data = read_slavemem32 (adev, base);
++ 
++  val = (data >> offset) & 0xff;
++
++  return val;
++}
++
++/*
++ * doesn't split across word boundaries
++ */
++INLINE_IO void
++write_slavemem16 (acx_device_t *adev, u32 slave_address, u16 val)
++{
++  u32 data;
++  u32 base;
++  int offset;
++
++  /*
++   * Get the word containing the target address and the byte offset in that word.
++   */
++  base = slave_address & ~3;
++  offset = (slave_address & 3) * 8;
++
++  data = read_slavemem32 (adev, base);
++  data &= ~(0xffff << offset);
++  data |= val << offset;
++  write_slavemem32 (adev, base, data);
++}
++
++/*
++ * doesn't split across word boundaries
++ */
++INLINE_IO u16
++read_slavemem16 (acx_device_t *adev, u32 slave_address)
++{
++  u16 val;
++  u32 base;
++  u32 data;
++  int offset;
++
++  base = slave_address & ~3;
++  offset = (slave_address & 3) * 8;
++
++  data = read_slavemem32 (adev, base);
++ 
++  val = (data >> offset) & 0xffff;
++
++  return val;
++}
++
++/*
++ * Copy from slave memory
++ *
++ * TODO - rewrite using address autoincrement, handle partial words
++ */
++void
++copy_from_slavemem (acx_device_t *adev, u8 *destination, u32 source, int count) {
++  u32 tmp = 0;
++  u8 *ptmp = (u8 *) &tmp;
++
++  /*
++   * Right now I'm making the assumption that the destination is aligned, but
++   * I'd better check.
++   */
++  if ((u32) destination & 3) {
++    printk ("acx copy_from_slavemem: warning!  destination not word-aligned!\n");
++  }
++
++  while (count >= 4) {
++    write_reg32 (adev, IO_ACX_SLV_MEM_ADDR, source);
++    udelay (10);
++    *((u32 *) destination) = read_reg32 (adev, IO_ACX_SLV_MEM_DATA);
++    count -= 4;
++    source += 4;
++    destination += 4;
++  }
++
++  /*
++   * If the word reads above didn't satisfy the count, read one more word
++   * and transfer a byte at a time until the request is satisfied.
++   */
++  if (count) {
++    write_reg32 (adev, IO_ACX_SLV_MEM_ADDR, source);
++    udelay (10);
++    tmp = read_reg32 (adev, IO_ACX_SLV_MEM_DATA);
++    while (count--) {
++      *destination++ = *ptmp++;
++    }
++  }
++}
++
++/*
++ * Copy to slave memory
++ *
++ * TODO - rewrite using autoincrement, handle partial words
++ */
++void
++copy_to_slavemem (acx_device_t *adev, u32 destination, u8 *source, int count)
++{
++  u32 tmp = 0;
++  u8* ptmp = (u8 *) &tmp;
++  static u8 src[512]; /* make static to avoid huge stack objects */
++
++  /*
++   * For now, make sure the source is word-aligned by copying it to a word-aligned
++   * buffer.  Someday rewrite to avoid the extra copy.
++   */
++  if (count > sizeof (src)) {
++    printk ("acx copy_to_slavemem: Warning! buffer overflow!\n");
++    count = sizeof (src);
++  }
++  memcpy (src, source, count);
++  source = src;
++
++  while (count >= 4) {
++    write_reg32 (adev, IO_ACX_SLV_MEM_ADDR, destination);
++    udelay (10);
++    write_reg32 (adev, IO_ACX_SLV_MEM_DATA, *((u32 *) source));
++    count -= 4;
++    source += 4;
++    destination += 4;
++  }
++
++  /*
++   * If there are leftovers read the next word from the acx and merge in
++   * what they want to write.
++   */
++  if (count) {
++    write_reg32 (adev, IO_ACX_SLV_MEM_ADDR, destination);
++    udelay (10);
++    tmp = read_reg32 (adev, IO_ACX_SLV_MEM_DATA);
++    while (count--) {
++      *ptmp++ = *source++;
++    }
++    /*
++     * reset address in case we're currently in auto-increment mode
++     */
++    write_reg32 (adev, IO_ACX_SLV_MEM_ADDR, destination);
++    udelay (10);
++    write_reg32 (adev, IO_ACX_SLV_MEM_DATA, tmp);
++    udelay (10);
++  }
++  
++}
++
++/*
++ * Block copy to slave buffers using memory block chain mode.  Copies to the ACX
++ * transmit buffer structure with minimal intervention on our part.
++ * Interrupts should be disabled when calling this.
++ */
++void
++chaincopy_to_slavemem (acx_device_t *adev, u32 destination, u8 *source, int count)
++{
++  u32 val;
++  u32 *data = (u32 *) source;
++  static u8 aligned_source[WLAN_A4FR_MAXLEN_WEP_FCS];
++
++  /*
++   * Warn if the pointers don't look right.  Destination must fit in [23:5] with
++   * zero elsewhere and source should be 32 bit aligned.
++   * This should never happen since we're in control of both, but I want to know about
++   * it if it does.
++   */
++  if ((destination & 0x00ffffe0) != destination) {
++    printk ("acx chaincopy: destination block 0x%04x not aligned!\n", destination);
++  }
++  if (count > sizeof aligned_source) {
++      printk( KERN_ERR "chaincopy_to_slavemem overflow!\n" );
++      count = sizeof aligned_source;
++  }
++  if ((u32) source & 3) {
++    memcpy (aligned_source, source, count);
++    data = (u32 *) aligned_source;
++  }
++
++  /*
++   * SLV_MEM_CTL[17:16] = memory block chain mode with auto-increment
++   * SLV_MEM_CTL[5:2] = offset to data portion = 1 word
++   */
++  val = 2 << 16 | 1 << 2;
++  writel (val, &adev->iobase[ACX_SLV_MEM_CTL]);
++
++  /*
++   * SLV_MEM_CP[23:5] = start of 1st block
++   * SLV_MEM_CP[3:2] = offset to memblkptr = 0
++   */
++  val = destination & 0x00ffffe0;
++  writel (val, &adev->iobase[ACX_SLV_MEM_CP]);
++
++  /*
++   * SLV_MEM_ADDR[23:2] = SLV_MEM_CTL[5:2] + SLV_MEM_CP[23:5]
++   */
++  val = (destination & 0x00ffffe0) + (1<<2);
++  writel (val, &adev->iobase[ACX_SLV_MEM_ADDR]);
++
++  /*
++   * Write the data to the slave data register, rounding up to the end
++   * of the word containing the last byte (hence the > 0)
++   */
++  while (count > 0) {
++    writel (*data++, &adev->iobase[ACX_SLV_MEM_DATA]);
++    count -= 4;
++  }
++}
++
++
++/*
++ * Block copy from slave buffers using memory block chain mode.  Copies from the ACX
++ * receive buffer structures with minimal intervention on our part.
++ * Interrupts should be disabled when calling this.
++ */
++void
++chaincopy_from_slavemem (acx_device_t *adev, u8 *destination, u32 source, int count)
++{
++  u32 val;
++  u32 *data = (u32 *) destination;
++  static u8 aligned_destination[WLAN_A4FR_MAXLEN_WEP_FCS];
++  int saved_count = count;
++
++  /*
++   * Warn if the pointers don't look right.  Destination must fit in [23:5] with
++   * zero elsewhere and source should be 32 bit aligned.
++   * Turns out the network stack sends unaligned things, so fix them before
++   * copying to the ACX.
++   */
++  if ((source & 0x00ffffe0) != source) {
++    printk ("acx chaincopy: source block 0x%04x not aligned!\n", source);
++    dump_acxmem (adev, 0, 0x10000);
++  }
++  if ((u32) destination & 3) {
++    //printk ("acx chaincopy: data destination not word aligned!\n");
++    data = (u32 *) aligned_destination;
++    if (count > sizeof aligned_destination) {
++      printk( KERN_ERR "chaincopy_from_slavemem overflow!\n" );
++      count = sizeof aligned_destination;
++    }
++  }
++
++  /*
++   * SLV_MEM_CTL[17:16] = memory block chain mode with auto-increment
++   * SLV_MEM_CTL[5:2] = offset to data portion = 1 word
++   */
++  val = (2 << 16) | (1 << 2);
++  writel (val, &adev->iobase[ACX_SLV_MEM_CTL]);
++
++  /*
++   * SLV_MEM_CP[23:5] = start of 1st block
++   * SLV_MEM_CP[3:2] = offset to memblkptr = 0
++   */
++  val = source & 0x00ffffe0;
++  writel (val, &adev->iobase[ACX_SLV_MEM_CP]);
++
++  /*
++   * SLV_MEM_ADDR[23:2] = SLV_MEM_CTL[5:2] + SLV_MEM_CP[23:5]
++   */
++  val = (source & 0x00ffffe0) + (1<<2);
++  writel (val, &adev->iobase[ACX_SLV_MEM_ADDR]);
++
++  /*
++   * Read the data from the slave data register, rounding up to the end
++   * of the word containing the last byte (hence the > 0)
++   */
++  while (count > 0) {
++    *data++ = readl (&adev->iobase[ACX_SLV_MEM_DATA]);
++    count -= 4;
++  }
++
++  /*
++   * If the destination wasn't aligned, we would have saved it in
++   * the aligned buffer, so copy it where it should go.
++   */
++  if ((u32) destination & 3) {
++    memcpy (destination, aligned_destination, saved_count);
++  }
++}
++
++char
++printable (char c) 
++{
++  return ((c >= 20) && (c < 127)) ? c : '.';
++}
++
++#if DUMP_MEM_DEFINED > 0
++static void
++dump_acxmem (acx_device_t *adev, u32 start, int length)
++{
++  int i;
++  u8 buf[16];
++
++  while (length > 0) {
++    printk ("%04x ", start);
++    copy_from_slavemem (adev, buf, start, 16);
++    for (i = 0; (i < 16) && (i < length); i++) {
++      printk ("%02x ", buf[i]);
++    }
++    for (i = 0; (i < 16) && (i < length); i++) {
++      printk ("%c", printable (buf[i]));
++    }
++    printk ("\n");
++    start += 16;
++    length -= 16;
++  }
++}
++#endif
++
++static void
++enable_acx_irq(acx_device_t *adev);
++static void
++disable_acx_irq(acx_device_t *adev);
++
++/*
++ * Return an acx pointer to the next transmit data block.
++ */
++u32
++allocate_acx_txbuf_space (acx_device_t *adev, int count) {
++  u32 block, next, last_block;
++  int blocks_needed;
++  unsigned long flags;
++
++  spin_lock_irqsave(&adev->txbuf_lock, flags);
++  /*
++   * Take 4 off the memory block size to account for the reserved word at the start of
++   * the block.
++   */
++  blocks_needed = count / (adev->memblocksize - 4);
++  if (count % (adev->memblocksize - 4))
++    blocks_needed++;
++
++  if (blocks_needed <= adev->acx_txbuf_blocks_free) {
++    /*
++     * Take blocks at the head of the free list.
++     */
++    last_block = block = adev->acx_txbuf_free;
++
++    /*
++     * Follow block pointers through the requested number of blocks both to
++     * find the new head of the free list and to set the flags for the blocks
++     * appropriately.
++     */
++    while (blocks_needed--) {
++      /*
++       * Keep track of the last block of the allocation
++       */
++      last_block = adev->acx_txbuf_free;
++
++      /*
++       * Make sure the end control flag is not set.
++       */
++      next = read_slavemem32 (adev, adev->acx_txbuf_free) & 0x7ffff;
++      write_slavemem32 (adev, adev->acx_txbuf_free, next);
++
++      /*
++       * Update the new head of the free list
++       */
++      adev->acx_txbuf_free = next << 5;
++      adev->acx_txbuf_blocks_free--;
++
++    }
++
++    /*
++     * Flag the last block both by clearing out the next pointer
++     * and marking the control field.
++     */
++    write_slavemem32 (adev, last_block, 0x02000000);
++
++    /*
++     * If we're out of buffers make sure the free list pointer is NULL
++     */
++    if (!adev->acx_txbuf_blocks_free) {
++      adev->acx_txbuf_free = 0;
++    }
++  }
++  else {
++    block = 0;
++  }
++  spin_unlock_irqrestore (&adev->txbuf_lock, flags);
++  return block;
++}
++
++/*
++ * Return buffer space back to the pool by following the next pointers until we find
++ * the block marked as the end.  Point the last block to the head of the free list,
++ * then update the head of the free list to point to the newly freed memory.
++ * This routine gets called in interrupt context, so it shouldn't block to protect
++ * the integrity of the linked list.  The ISR already holds the lock.
++ */
++void
++reclaim_acx_txbuf_space (acx_device_t *adev, u32 blockptr) {
++  u32 cur, last, next;
++  unsigned long flags;
++
++  spin_lock_irqsave (&adev->txbuf_lock, flags);
++  if ((blockptr >= adev->acx_txbuf_start) &&
++      (blockptr <= adev->acx_txbuf_start +
++       (adev->acx_txbuf_numblocks - 1) * adev->memblocksize)) {
++    cur = blockptr;
++    do {
++      last = cur;
++      next = read_slavemem32 (adev, cur);
++      
++      /*
++       * Advance to the next block in this allocation
++       */
++      cur = (next & 0x7ffff) << 5;
++      
++      /*
++       * This block now counts as free.
++       */
++      adev->acx_txbuf_blocks_free++;
++    } while (!(next & 0x02000000));
++    
++    /*
++     * last now points to the last block of that allocation.  Update the pointer
++     * in that block to point to the free list and reset the free list to the
++     * first block of the free call.  If there were no free blocks, make sure
++     * the new end of the list marks itself as truly the end.
++     */
++    if (adev->acx_txbuf_free) {
++      write_slavemem32 (adev, last, adev->acx_txbuf_free >> 5);
++    }
++    else {
++      write_slavemem32 (adev, last, 0x02000000);
++    }
++    adev->acx_txbuf_free = blockptr;
++  } 
++  spin_unlock_irqrestore(&adev->txbuf_lock, flags);
++}
++
++/*
++ * Initialize the pieces managing the transmit buffer pool on the ACX.  The transmit
++ * buffer is a circular queue with one 32 bit word reserved at the beginning of each
++ * block.  The upper 13 bits are a control field, of which only 0x02000000 has any
++ * meaning.  The lower 19 bits are the address of the next block divided by 32.
++ */
++void
++init_acx_txbuf (acx_device_t *adev) {
++  
++  /*
++   * acx100_s_init_memory_pools set up txbuf_start and txbuf_numblocks for us.
++   * All we need to do is reset the rest of the bookeeping.
++   */
++  
++  adev->acx_txbuf_free = adev->acx_txbuf_start;
++  adev->acx_txbuf_blocks_free = adev->acx_txbuf_numblocks;
++  
++  /*
++   * Initialization leaves the last transmit pool block without a pointer back to
++   * the head of the list, but marked as the end of the list.  That's how we want
++   * to see it, too, so leave it alone.  This is only ever called after a firmware
++   * reset, so the ACX memory is in the state we want.
++   */
++      
++}
++
++INLINE_IO int
++adev_present(acx_device_t *adev)
++{
++      /* fast version (accesses the first register, IO_ACX_SOFT_RESET,
++       * which should be safe): */
++      return readl(adev->iobase) != 0xffffffff;
++}
++
++/***********************************************************************
++*/
++static inline txdesc_t*
++get_txdesc(acx_device_t *adev, int index)
++{
++      return (txdesc_t*) (((u8*)adev->txdesc_start) + index * adev->txdesc_size);
++}
++
++static inline txdesc_t*
++advance_txdesc(acx_device_t *adev, txdesc_t* txdesc, int inc)
++{
++      return (txdesc_t*) (((u8*)txdesc) + inc * adev->txdesc_size);
++}
++
++static txhostdesc_t*
++get_txhostdesc(acx_device_t *adev, txdesc_t* txdesc)
++{
++      int index = (u8*)txdesc - (u8*)adev->txdesc_start;
++      if (unlikely(ACX_DEBUG && (index % adev->txdesc_size))) {
++              printk("bad txdesc ptr %p\n", txdesc);
++              return NULL;
++      }
++      index /= adev->txdesc_size;
++      if (unlikely(ACX_DEBUG && (index >= TX_CNT))) {
++              printk("bad txdesc ptr %p\n", txdesc);
++              return NULL;
++      }
++      return &adev->txhostdesc_start[index*2];
++}
++
++static inline client_t*
++get_txc(acx_device_t *adev, txdesc_t* txdesc)
++{
++      int index = (u8*)txdesc - (u8*)adev->txdesc_start;
++      if (unlikely(ACX_DEBUG && (index % adev->txdesc_size))) {
++              printk("bad txdesc ptr %p\n", txdesc);
++              return NULL;
++      }
++      index /= adev->txdesc_size;
++      if (unlikely(ACX_DEBUG && (index >= TX_CNT))) {
++              printk("bad txdesc ptr %p\n", txdesc);
++              return NULL;
++      }
++      return adev->txc[index];
++}
++
++static inline u16
++get_txr(acx_device_t *adev, txdesc_t* txdesc)
++{
++      int index = (u8*)txdesc - (u8*)adev->txdesc_start;
++      index /= adev->txdesc_size;
++      return adev->txr[index];
++}
++
++static inline void
++put_txcr(acx_device_t *adev, txdesc_t* txdesc, client_t* c, u16 r111)
++{
++      int index = (u8*)txdesc - (u8*)adev->txdesc_start;
++      if (unlikely(ACX_DEBUG && (index % adev->txdesc_size))) {
++              printk("bad txdesc ptr %p\n", txdesc);
++              return;
++      }
++      index /= adev->txdesc_size;
++      if (unlikely(ACX_DEBUG && (index >= TX_CNT))) {
++              printk("bad txdesc ptr %p\n", txdesc);
++              return;
++      }
++      adev->txc[index] = c;
++      adev->txr[index] = r111;
++}
++
++
++/***********************************************************************
++** EEPROM and PHY read/write helpers
++*/
++/***********************************************************************
++** acxmem_read_eeprom_byte
++**
++** Function called to read an octet in the EEPROM.
++**
++** This function is used by acxmem_e_probe to check if the
++** connected card is a legal one or not.
++**
++** Arguments:
++**    adev            ptr to acx_device structure
++**    addr            address to read in the EEPROM
++**    charbuf         ptr to a char. This is where the read octet
++**                    will be stored
++*/
++int
++acxmem_read_eeprom_byte(acx_device_t *adev, u32 addr, u8 *charbuf)
++{
++      int result;
++      int count;
++
++      write_reg32(adev, IO_ACX_EEPROM_CFG, 0);
++      write_reg32(adev, IO_ACX_EEPROM_ADDR, addr);
++      write_flush(adev);
++      write_reg32(adev, IO_ACX_EEPROM_CTL, 2);
++
++      count = 0xffff;
++      while (read_reg16(adev, IO_ACX_EEPROM_CTL)) {
++              /* scheduling away instead of CPU burning loop
++               * doesn't seem to work here at all:
++               * awful delay, sometimes also failure.
++               * Doesn't matter anyway (only small delay). */
++              if (unlikely(!--count)) {
++                      printk("%s: timeout waiting for EEPROM read\n",
++                                                      adev->ndev->name);
++                      result = NOT_OK;
++                      goto fail;
++              }
++              cpu_relax();
++      }
++
++      *charbuf = read_reg8(adev, IO_ACX_EEPROM_DATA);
++      log(L_DEBUG, "EEPROM at 0x%04X = 0x%02X\n", addr, *charbuf);
++      result = OK;
++
++fail:
++      return result;
++}
++
++
++/***********************************************************************
++** We don't lock hw accesses here since we never r/w eeprom in IRQ
++** Note: this function sleeps only because of GFP_KERNEL alloc
++*/
++#ifdef UNUSED
++int
++acxmem_s_write_eeprom(acx_device_t *adev, u32 addr, u32 len, const u8 *charbuf)
++{
++      u8 *data_verify = NULL;
++      unsigned long flags;
++      int count, i;
++      int result = NOT_OK;
++      u16 gpio_orig;
++
++      printk("acx: WARNING! I would write to EEPROM now. "
++              "Since I really DON'T want to unless you know "
++              "what you're doing (THIS CODE WILL PROBABLY "
++              "NOT WORK YET!), I will abort that now. And "
++              "definitely make sure to make a "
++              "/proc/driver/acx_wlan0_eeprom backup copy first!!! "
++              "(the EEPROM content includes the PCI config header!! "
++              "If you kill important stuff, then you WILL "
++              "get in trouble and people DID get in trouble already)\n");
++      return OK;
++
++      FN_ENTER;
++
++      data_verify = kmalloc(len, GFP_KERNEL);
++      if (!data_verify) {
++              goto end;
++      }
++
++      /* first we need to enable the OE (EEPROM Output Enable) GPIO line
++       * to be able to write to the EEPROM.
++       * NOTE: an EEPROM writing success has been reported,
++       * but you probably have to modify GPIO_OUT, too,
++       * and you probably need to activate a different GPIO
++       * line instead! */
++      gpio_orig = read_reg16(adev, IO_ACX_GPIO_OE);
++      write_reg16(adev, IO_ACX_GPIO_OE, gpio_orig & ~1);
++      write_flush(adev);
++
++      /* ok, now start writing the data out */
++      for (i = 0; i < len; i++) {
++              write_reg32(adev, IO_ACX_EEPROM_CFG, 0);
++              write_reg32(adev, IO_ACX_EEPROM_ADDR, addr + i);
++              write_reg32(adev, IO_ACX_EEPROM_DATA, *(charbuf + i));
++              write_flush(adev);
++              write_reg32(adev, IO_ACX_EEPROM_CTL, 1);
++
++              count = 0xffff;
++              while (read_reg16(adev, IO_ACX_EEPROM_CTL)) {
++                      if (unlikely(!--count)) {
++                              printk("WARNING, DANGER!!! "
++                                      "Timeout waiting for EEPROM write\n");
++                              goto end;
++                      }
++                      cpu_relax();
++              }
++      }
++
++      /* disable EEPROM writing */
++      write_reg16(adev, IO_ACX_GPIO_OE, gpio_orig);
++      write_flush(adev);
++
++      /* now start a verification run */
++      for (i = 0; i < len; i++) {
++              write_reg32(adev, IO_ACX_EEPROM_CFG, 0);
++              write_reg32(adev, IO_ACX_EEPROM_ADDR, addr + i);
++              write_flush(adev);
++              write_reg32(adev, IO_ACX_EEPROM_CTL, 2);
++
++              count = 0xffff;
++              while (read_reg16(adev, IO_ACX_EEPROM_CTL)) {
++                      if (unlikely(!--count)) {
++                              printk("timeout waiting for EEPROM read\n");
++                              goto end;
++                      }
++                      cpu_relax();
++              }
++
++              data_verify[i] = read_reg16(adev, IO_ACX_EEPROM_DATA);
++      }
++
++      if (0 == memcmp(charbuf, data_verify, len))
++              result = OK; /* read data matches, success */
++
++end:
++      kfree(data_verify);
++      FN_EXIT1(result);
++      return result;
++}
++#endif /* UNUSED */
++
++
++/***********************************************************************
++** acxmem_s_read_phy_reg
++**
++** Messing with rx/tx disabling and enabling here
++** (write_reg32(adev, IO_ACX_ENABLE, 0b000000xx)) kills traffic
++*/
++int
++acxmem_s_read_phy_reg(acx_device_t *adev, u32 reg, u8 *charbuf)
++{
++      int result = NOT_OK;
++      int count;
++
++      FN_ENTER;
++
++      write_reg32(adev, IO_ACX_PHY_ADDR, reg);
++      write_flush(adev);
++      write_reg32(adev, IO_ACX_PHY_CTL, 2);
++
++      count = 0xffff;
++      while (read_reg32(adev, IO_ACX_PHY_CTL)) {
++              /* scheduling away instead of CPU burning loop
++               * doesn't seem to work here at all:
++               * awful delay, sometimes also failure.
++               * Doesn't matter anyway (only small delay). */
++              if (unlikely(!--count)) {
++                      printk("%s: timeout waiting for phy read\n",
++                                                      adev->ndev->name);
++                      *charbuf = 0;
++                      goto fail;
++              }
++              cpu_relax();
++      }
++
++      log(L_DEBUG, "count was %u\n", count);
++      *charbuf = read_reg8(adev, IO_ACX_PHY_DATA);
++
++      log(L_DEBUG, "radio PHY at 0x%04X = 0x%02X\n", *charbuf, reg);
++      result = OK;
++      goto fail; /* silence compiler warning */
++fail:
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/***********************************************************************
++*/
++int
++acxmem_s_write_phy_reg(acx_device_t *adev, u32 reg, u8 value)
++{
++        int count;
++      FN_ENTER;
++
++      /* mprusko said that 32bit accesses result in distorted sensitivity
++       * on his card. Unconfirmed, looks like it's not true (most likely since we
++       * now properly flush writes). */
++      write_reg32(adev, IO_ACX_PHY_DATA, value);
++      write_reg32(adev, IO_ACX_PHY_ADDR, reg);
++      write_flush(adev);
++      write_reg32(adev, IO_ACX_PHY_CTL, 1);
++      write_flush(adev);
++
++      count = 0xffff;
++      while (read_reg32(adev, IO_ACX_PHY_CTL)) {
++              /* scheduling away instead of CPU burning loop
++               * doesn't seem to work here at all:
++               * awful delay, sometimes also failure.
++               * Doesn't matter anyway (only small delay). */
++              if (unlikely(!--count)) {
++                      printk("%s: timeout waiting for phy read\n",
++                                                      adev->ndev->name);
++                      goto fail;
++              }
++              cpu_relax();
++      }
++
++      log(L_DEBUG, "radio PHY write 0x%02X at 0x%04X\n", value, reg);
++ fail:
++      FN_EXIT1(OK);
++      return OK;
++}
++
++
++#define NO_AUTO_INCREMENT     1
++
++/***********************************************************************
++** acxmem_s_write_fw
++**
++** Write the firmware image into the card.
++**
++** Arguments:
++**    adev            wlan device structure
++**    fw_image        firmware image.
++**
++** Returns:
++**    1       firmware image corrupted
++**    0       success
++*/
++static int
++acxmem_s_write_fw(acx_device_t *adev, const firmware_image_t *fw_image, u32 offset)
++{
++      int len, size, checkMismatch = -1;
++      u32 sum, v32, tmp, id;
++      /* we skip the first four bytes which contain the control sum */
++      const u8 *p = (u8*)fw_image + 4;
++
++      /* start the image checksum by adding the image size value */
++      sum = p[0]+p[1]+p[2]+p[3];
++      p += 4;
++
++#ifdef NOPE
++#if NO_AUTO_INCREMENT
++      write_reg32(adev, IO_ACX_SLV_MEM_CTL, 0); /* use basic mode */
++#else
++      write_reg32(adev, IO_ACX_SLV_MEM_CTL, 1); /* use autoincrement mode */
++      write_reg32(adev, IO_ACX_SLV_MEM_ADDR, offset); /* configure start address */
++      write_flush(adev);
++#endif
++#endif
++      len = 0;
++      size = le32_to_cpu(fw_image->size) & (~3);
++
++      while (likely(len < size)) {
++              v32 = be32_to_cpu(*(u32*)p);
++              sum += p[0]+p[1]+p[2]+p[3];
++              p += 4;
++              len += 4;
++
++#ifdef NOPE
++#if NO_AUTO_INCREMENT 
++              write_reg32(adev, IO_ACX_SLV_MEM_ADDR, offset + len - 4);
++              write_flush(adev);
++#endif
++              write_reg32(adev, IO_ACX_SLV_MEM_DATA, v32);
++              write_flush(adev);
++#endif
++              write_slavemem32 (adev, offset + len - 4, v32);
++
++              id = read_id_register (adev);
++              
++              /*
++               * check the data written
++               */
++              tmp = read_slavemem32 (adev, offset + len - 4);
++              if (checkMismatch && (tmp != v32)) {
++                printk ("first data mismatch at 0x%08x good 0x%08x bad 0x%08x id 0x%08x\n",
++                        offset + len - 4, v32, tmp, id);
++                checkMismatch = 0;
++              }
++      }
++      log(L_DEBUG, "firmware written, size:%d sum1:%x sum2:%x\n",
++                      size, sum, le32_to_cpu(fw_image->chksum));
++
++      /* compare our checksum with the stored image checksum */
++      return (sum != le32_to_cpu(fw_image->chksum));
++}
++
++
++/***********************************************************************
++** acxmem_s_validate_fw
++**
++** Compare the firmware image given with
++** the firmware image written into the card.
++**
++** Arguments:
++**    adev            wlan device structure
++**    fw_image        firmware image.
++**
++** Returns:
++**    NOT_OK  firmware image corrupted or not correctly written
++**    OK      success
++*/
++static int
++acxmem_s_validate_fw(acx_device_t *adev, const firmware_image_t *fw_image,
++                              u32 offset)
++{
++      u32 sum, v32, w32;
++      int len, size;
++      int result = OK;
++      /* we skip the first four bytes which contain the control sum */
++      const u8 *p = (u8*)fw_image + 4;
++
++      /* start the image checksum by adding the image size value */
++      sum = p[0]+p[1]+p[2]+p[3];
++      p += 4;
++
++      write_reg32(adev, IO_ACX_SLV_END_CTL, 0);
++
++#if NO_AUTO_INCREMENT
++      write_reg32(adev, IO_ACX_SLV_MEM_CTL, 0); /* use basic mode */
++#else
++      write_reg32(adev, IO_ACX_SLV_MEM_CTL, 1); /* use autoincrement mode */
++      write_reg32(adev, IO_ACX_SLV_MEM_ADDR, offset); /* configure start address */
++#endif
++
++      len = 0;
++      size = le32_to_cpu(fw_image->size) & (~3);
++
++      while (likely(len < size)) {
++              v32 = be32_to_cpu(*(u32*)p);
++              p += 4;
++              len += 4;
++
++#ifdef NOPE
++#if NO_AUTO_INCREMENT
++              write_reg32(adev, IO_ACX_SLV_MEM_ADDR, offset + len - 4);
++#endif
++              udelay(10);
++              w32 = read_reg32(adev, IO_ACX_SLV_MEM_DATA);
++#endif
++              w32 = read_slavemem32 (adev, offset + len - 4);
++
++              if (unlikely(w32 != v32)) {
++                      printk("acx: FATAL: firmware upload: "
++                      "data parts at offset %d don't match\n(0x%08X vs. 0x%08X)!\n"
++                      "I/O timing issues or defective memory, with DWL-xx0+? "
++                      "ACX_IO_WIDTH=16 may help. Please report\n",
++                              len, v32, w32);
++                      result = NOT_OK;
++                      break;
++              }
++
++              sum += (u8)w32 + (u8)(w32>>8) + (u8)(w32>>16) + (u8)(w32>>24);
++      }
++
++      /* sum control verification */
++      if (result != NOT_OK) {
++              if (sum != le32_to_cpu(fw_image->chksum)) {
++                      printk("acx: FATAL: firmware upload: "
++                              "checksums don't match!\n");
++                      result = NOT_OK;
++              }
++      }
++
++      return result;
++}
++
++
++/***********************************************************************
++** acxmem_s_upload_fw
++**
++** Called from acx_reset_dev
++*/
++static int
++acxmem_s_upload_fw(acx_device_t *adev)
++{
++      firmware_image_t *fw_image = NULL;
++      int res = NOT_OK;
++      int try;
++      u32 file_size;
++      char *filename = "WLANGEN.BIN";
++#ifdef PATCH_AROUND_BAD_SPOTS
++      u32 offset;
++      int i;
++        /*
++         * arm-linux-objdump -d patch.bin, or
++         * od -Ax -t x4 patch.bin after finding the bounds
++         * of the .text section with arm-linux-objdump -s patch.bin
++         */
++        u32 patch[] = {
++        0xe584c030, 0xe59fc008,
++        0xe92d1000, 0xe59fc004, 0xe8bd8000, 0x0000080c,
++        0x0000aa68, 0x605a2200, 0x2c0a689c, 0x2414d80a,
++        0x2f00689f, 0x1c27d007, 0x06241e7c, 0x2f000e24,
++        0xe000d1f6, 0x602e6018, 0x23036468, 0x480203db,
++        0x60ca6003, 0xbdf0750a, 0xffff0808
++      };
++#endif
++
++      FN_ENTER;
++      /* No combined image; tell common we need the radio firmware, too */
++      adev->need_radio_fw = 1;
++
++      fw_image = acx_s_read_fw(adev->dev, filename, &file_size);
++      if (!fw_image) {
++        FN_EXIT1(NOT_OK);
++        return NOT_OK;
++      }
++
++      for (try = 1; try <= 5; try++) {
++              res = acxmem_s_write_fw(adev, fw_image, 0);
++              log(L_DEBUG|L_INIT, "acx_write_fw (main): %d\n", res);
++              if (OK == res) {
++                      res = acxmem_s_validate_fw(adev, fw_image, 0);
++                      log(L_DEBUG|L_INIT, "acx_validate_fw "
++                                      "(main): %d\n", res);
++              }
++
++              if (OK == res) {
++                      SET_BIT(adev->dev_state_mask, ACX_STATE_FW_LOADED);
++                      break;
++              }
++              printk("acx: firmware upload attempt #%d FAILED, "
++                      "retrying...\n", try);
++              acx_s_msleep(1000); /* better wait for a while... */
++      }
++
++#ifdef PATCH_AROUND_BAD_SPOTS
++      /*
++       * Only want to do this if the firmware is exactly what we expect for an
++       * iPaq 4700; otherwise, bad things would ensue.
++       */
++      if ((HX4700_FIRMWARE_CHECKSUM == fw_image->chksum) ||
++          (HX4700_ALTERNATE_FIRMWARE_CHECKSUM == fw_image->chksum)) {
++        /*
++         * Put the patch after the main firmware image.  0x950c contains
++         * the ACX's idea of the end of the firmware.  Use that location to
++         * load ours (which depends on that location being 0xab58) then
++         * update that location to point to after ours.
++         */
++
++        offset = read_slavemem32 (adev, 0x950c);
++        
++        log (L_DEBUG, "acx: patching in at 0x%04x\n", offset);
++
++        for (i = 0; i < sizeof(patch) / sizeof(patch[0]); i++) {
++          write_slavemem32 (adev, offset, patch[i]);
++          offset += sizeof(u32);
++        }
++
++        /*
++         * Patch the instruction at 0x0804 to branch to our ARM patch at 0xab58
++         */
++        write_slavemem32 (adev, 0x0804, 0xea000000 + (0xab58-0x0804-8)/4);
++
++        /*
++         * Patch the instructions at 0x1f40 to branch to our Thumb patch at 0xab74
++         *
++         * 4a00 ldr r2, [pc, #0]
++         * 4710 bx  r2
++         * .data 0xab74+1
++         */
++        write_slavemem32 (adev, 0x1f40, 0x47104a00);
++        write_slavemem32 (adev, 0x1f44, 0x0000ab74+1);
++
++        /*
++         * Bump the end of the firmware up to beyond our patch.
++         */
++        write_slavemem32 (adev, 0x950c, offset);
++      
++      }
++#endif
++
++      vfree(fw_image);
++
++      FN_EXIT1(res);
++      return res;
++}
++
++
++/***********************************************************************
++** acxmem_s_upload_radio
++**
++** Uploads the appropriate radio module firmware into the card.
++*/
++int
++acxmem_s_upload_radio(acx_device_t *adev)
++{
++      acx_ie_memmap_t mm;
++      firmware_image_t *radio_image;
++      acx_cmd_radioinit_t radioinit;
++      int res = NOT_OK;
++      int try;
++      u32 offset;
++      u32 size;
++      char filename[sizeof("RADIONN.BIN")];
++
++      if (!adev->need_radio_fw) return OK;
++
++      FN_ENTER;
++
++      acx_s_interrogate(adev, &mm, ACX1xx_IE_MEMORY_MAP);
++      offset = le32_to_cpu(mm.CodeEnd);
++
++      snprintf(filename, sizeof(filename), "RADIO%02x.BIN",
++              adev->radio_type);
++      radio_image = acx_s_read_fw(adev->dev, filename, &size);
++      if (!radio_image) {
++              printk("acx: can't load radio module '%s'\n", filename);
++              goto fail;
++      }
++
++      acx_s_issue_cmd(adev, ACX1xx_CMD_SLEEP, NULL, 0);
++
++      for (try = 1; try <= 5; try++) {
++              res = acxmem_s_write_fw(adev, radio_image, offset);
++              log(L_DEBUG|L_INIT, "acx_write_fw (radio): %d\n", res);
++              if (OK == res) {
++                      res = acxmem_s_validate_fw(adev, radio_image, offset);
++                      log(L_DEBUG|L_INIT, "acx_validate_fw (radio): %d\n", res);
++              }
++
++              if (OK == res)
++                      break;
++              printk("acx: radio firmware upload attempt #%d FAILED, "
++                      "retrying...\n", try);
++              acx_s_msleep(1000); /* better wait for a while... */
++      }
++
++      acx_s_issue_cmd(adev, ACX1xx_CMD_WAKE, NULL, 0);
++      radioinit.offset = cpu_to_le32(offset);
++
++      /* no endian conversion needed, remains in card CPU area: */
++      radioinit.len = radio_image->size;
++
++      vfree(radio_image);
++
++      if (OK != res)
++              goto fail;
++
++      /* will take a moment so let's have a big timeout */
++      acx_s_issue_cmd_timeo(adev, ACX1xx_CMD_RADIOINIT,
++              &radioinit, sizeof(radioinit), CMD_TIMEOUT_MS(1000));
++
++      res = acx_s_interrogate(adev, &mm, ACX1xx_IE_MEMORY_MAP);
++
++fail:
++      FN_EXIT1(res);
++      return res;
++}
++
++/***********************************************************************
++** acxmem_l_reset_mac
++**
++** MAC will be reset
++** Call context: reset_dev
++*/
++static void
++acxmem_l_reset_mac(acx_device_t *adev)
++{
++  int count;
++      FN_ENTER;
++
++      /* halt eCPU */
++      set_regbits (adev, IO_ACX_ECPU_CTRL, 0x1);
++
++      /* now do soft reset of eCPU, set bit */
++      set_regbits (adev, IO_ACX_SOFT_RESET, 0x1);
++      log(L_DEBUG, "%s: enable soft reset...\n", __func__);
++
++      /* Windows driver sleeps here for a while with this sequence */
++      for (count = 0; count < 200; count++) {
++        udelay (50);
++      }
++
++      /* now clear bit again: deassert eCPU reset */
++      log(L_DEBUG, "%s: disable soft reset and go to init mode...\n", __func__);
++      clear_regbits (adev, IO_ACX_SOFT_RESET, 0x1);
++
++      /* now start a burst read from initial EEPROM */
++      set_regbits (adev, IO_ACX_EE_START, 0x1);
++
++      /*
++       * Windows driver sleeps here for a while with this sequence
++       */
++      for (count = 0; count < 200; count++) {
++        udelay (50);
++      }
++
++      /* Windows driver writes 0x10000 to register 0x808 here */
++      
++      write_reg32 (adev, 0x808, 0x10000);
++
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++** acxmem_s_verify_init
++*/
++static int
++acxmem_s_verify_init(acx_device_t *adev)
++{
++      int result = NOT_OK;
++      unsigned long timeout;
++
++      FN_ENTER;
++
++      timeout = jiffies + 2*HZ;
++      for (;;) {
++              u32 irqstat = read_reg32(adev, IO_ACX_IRQ_STATUS_NON_DES);
++              if ((irqstat != 0xFFFFFFFF) && (irqstat & HOST_INT_FCS_THRESHOLD)) {
++                      result = OK;
++                      write_reg32(adev, IO_ACX_IRQ_ACK, HOST_INT_FCS_THRESHOLD);
++                      break;
++              }
++              if (time_after(jiffies, timeout))
++                      break;
++              /* Init may take up to ~0.5 sec total */
++              acx_s_msleep(50);
++      }
++
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/***********************************************************************
++** A few low-level helpers
++**
++** Note: these functions are not protected by lock
++** and thus are never allowed to be called from IRQ.
++** Also they must not race with fw upload which uses same hw regs
++*/
++
++/***********************************************************************
++** acxmem_write_cmd_type_status
++*/
++
++static inline void
++acxmem_write_cmd_type_status(acx_device_t *adev, u16 type, u16 status)
++{
++  write_slavemem32 (adev, (u32) adev->cmd_area, type | (status << 16));
++  write_flush(adev);
++}
++
++
++/***********************************************************************
++** acxmem_read_cmd_type_status
++*/
++static u32
++acxmem_read_cmd_type_status(acx_device_t *adev)
++{
++      u32 cmd_type, cmd_status;
++
++      cmd_type = read_slavemem32 (adev, (u32) adev->cmd_area);
++
++      cmd_status = (cmd_type >> 16);
++      cmd_type = (u16)cmd_type;
++
++      log(L_CTL, "cmd_type:%04X cmd_status:%04X [%s]\n",
++              cmd_type, cmd_status,
++              acx_cmd_status_str(cmd_status));
++
++      return cmd_status;
++}
++
++
++/***********************************************************************
++** acxmem_s_reset_dev
++**
++** Arguments:
++**    netdevice that contains the adev variable
++** Returns:
++**    NOT_OK on fail
++**    OK on success
++** Side effects:
++**    device is hard reset
++** Call context:
++**    acxmem_e_probe
++** Comment:
++**    This resets the device using low level hardware calls
++**    as well as uploads and verifies the firmware to the card
++*/
++
++static inline void
++init_mboxes(acx_device_t *adev)
++{
++      u32 cmd_offs, info_offs;
++
++      cmd_offs = read_reg32(adev, IO_ACX_CMD_MAILBOX_OFFS);
++      info_offs = read_reg32(adev, IO_ACX_INFO_MAILBOX_OFFS);
++      adev->cmd_area = (u8*) cmd_offs;
++      adev->info_area = (u8*) info_offs;
++      /*
++      log(L_DEBUG, "iobase2=%p\n"
++      */
++      log( L_DEBUG, "cmd_mbox_offset=%X cmd_area=%p\n"
++              "info_mbox_offset=%X info_area=%p\n",
++              cmd_offs, adev->cmd_area,
++              info_offs, adev->info_area);
++}
++
++
++static inline void
++read_eeprom_area(acx_device_t *adev)
++{
++#if ACX_DEBUG > 1
++      int offs;
++      u8 tmp;
++
++      for (offs = 0x8c; offs < 0xb9; offs++)
++              acxmem_read_eeprom_byte(adev, offs, &tmp);
++#endif
++}
++
++static int
++acxmem_s_reset_dev(acx_device_t *adev)
++{
++      const char* msg = "";
++      unsigned long flags;
++      int result = NOT_OK;
++      u16 hardware_info;
++      u16 ecpu_ctrl;
++      int count;
++      u32 tmp;
++
++      FN_ENTER;
++      /*
++      write_reg32 (adev, IO_ACX_SLV_MEM_CP, 0);
++      */
++      /* reset the device to make sure the eCPU is stopped
++       * to upload the firmware correctly */
++
++      acx_lock(adev, flags);
++
++      /* Windows driver does some funny things here */
++      /*
++       * clear bit 0x200 in register 0x2A0
++       */
++      clear_regbits (adev, 0x2A0, 0x200);
++
++      /*
++       * Set bit 0x200 in ACX_GPIO_OUT
++       */
++      set_regbits (adev, IO_ACX_GPIO_OUT, 0x200);
++
++      /*
++       * read register 0x900 until its value is 0x8400104C, sleeping
++       * in between reads if it's not immediate
++       */
++      tmp = read_reg32 (adev, REG_ACX_VENDOR_ID);
++      count = 500;
++      while (count-- && (tmp != ACX_VENDOR_ID)) {
++        mdelay (10);
++        tmp = read_reg32 (adev, REG_ACX_VENDOR_ID);
++      }
++
++      /* end what Windows driver does */
++
++      acxmem_l_reset_mac(adev);
++
++      ecpu_ctrl = read_reg32(adev, IO_ACX_ECPU_CTRL) & 1;
++      if (!ecpu_ctrl) {
++              msg = "eCPU is already running. ";
++              goto end_unlock;
++      }
++
++#ifdef WE_DONT_NEED_THAT_DO_WE
++      if (read_reg16(adev, IO_ACX_SOR_CFG) & 2) {
++              /* eCPU most likely means "embedded CPU" */
++              msg = "eCPU did not start after boot from flash. ";
++              goto end_unlock;
++      }
++
++      /* check sense on reset flags */
++      if (read_reg16(adev, IO_ACX_SOR_CFG) & 0x10) {
++              printk("%s: eCPU did not start after boot (SOR), "
++                      "is this fatal?\n", adev->ndev->name);
++      }
++#endif
++      /* scan, if any, is stopped now, setting corresponding IRQ bit */
++      adev->irq_status |= HOST_INT_SCAN_COMPLETE;
++
++      acx_unlock(adev, flags);
++      
++      /* need to know radio type before fw load */
++      /* Need to wait for arrival of this information in a loop,
++       * most probably since eCPU runs some init code from EEPROM
++       * (started burst read in reset_mac()) which also
++       * sets the radio type ID */
++
++      count = 0xffff;
++      do {
++              hardware_info = read_reg16(adev, IO_ACX_EEPROM_INFORMATION);
++              if (!--count) {
++                      msg = "eCPU didn't indicate radio type";
++                      goto end_fail;
++              }
++              cpu_relax();
++      } while (!(hardware_info & 0xff00)); /* radio type still zero? */
++      printk("ACX radio type 0x%02x\n", (hardware_info >> 8) & 0xff);
++      /* printk("DEBUG: count %d\n", count); */
++      adev->form_factor = hardware_info & 0xff;
++      adev->radio_type = hardware_info >> 8;
++
++      /* load the firmware */
++      if (OK != acxmem_s_upload_fw(adev))
++              goto end_fail;
++
++      /* acx_s_msleep(10);    this one really shouldn't be required */
++
++      /* now start eCPU by clearing bit */
++      clear_regbits (adev, IO_ACX_ECPU_CTRL, 0x1);
++      log(L_DEBUG, "booted eCPU up and waiting for completion...\n");
++
++      /* Windows driver clears bit 0x200 in register 0x2A0 here */
++      clear_regbits (adev, 0x2A0, 0x200);
++
++      /* Windows driver sets bit 0x200 in ACX_GPIO_OUT here */
++      set_regbits (adev, IO_ACX_GPIO_OUT, 0x200);
++      /* wait for eCPU bootup */
++      if (OK != acxmem_s_verify_init(adev)) {
++              msg = "timeout waiting for eCPU. ";
++              goto end_fail;
++      }
++      log(L_DEBUG, "eCPU has woken up, card is ready to be configured\n");
++      init_mboxes(adev);
++      acxmem_write_cmd_type_status(adev, ACX1xx_CMD_RESET, 0);
++
++      /* test that EEPROM is readable */
++      read_eeprom_area(adev);
++
++      result = OK;
++      goto end;
++
++/* Finish error message. Indicate which function failed */
++end_unlock:
++      acx_unlock(adev, flags);
++end_fail:
++      printk("acx: %sreset_dev() FAILED\n", msg);
++end:
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/***********************************************************************
++** acxmem_s_issue_cmd_timeo
++**
++** Sends command to fw, extract result
++**
++** NB: we do _not_ take lock inside, so be sure to not touch anything
++** which may interfere with IRQ handler operation
++**
++** TODO: busy wait is a bit silly, so:
++** 1) stop doing many iters - go to sleep after first
++** 2) go to waitqueue based approach: wait, not poll!
++*/
++#undef FUNC
++#define FUNC "issue_cmd"
++
++#if !ACX_DEBUG
++int
++acxmem_s_issue_cmd_timeo(
++      acx_device_t *adev,
++      unsigned int cmd,
++      void *buffer,
++      unsigned buflen,
++      unsigned cmd_timeout)
++{
++#else
++int
++acxmem_s_issue_cmd_timeo_debug(
++      acx_device_t *adev,
++      unsigned cmd,
++      void *buffer,
++      unsigned buflen,
++      unsigned cmd_timeout,
++      const char* cmdstr)
++{
++      unsigned long start = jiffies;
++#endif
++      const char *devname;
++      unsigned counter;
++      u16 irqtype;
++      int i, j;
++      u8 *p;
++      u16 cmd_status;
++      unsigned long timeout;
++
++      FN_ENTER;
++
++      devname = adev->ndev->name;
++      if (!devname || !devname[0] || devname[4]=='%')
++              devname = "acx";
++
++      log(L_CTL, FUNC"(cmd:%s,buflen:%u,timeout:%ums,type:0x%04X)\n",
++              cmdstr, buflen, cmd_timeout,
++              buffer ? le16_to_cpu(((acx_ie_generic_t *)buffer)->type) : -1);
++
++      if (!(adev->dev_state_mask & ACX_STATE_FW_LOADED)) {
++              printk("%s: "FUNC"(): firmware is not loaded yet, "
++                      "cannot execute commands!\n", devname);
++              goto bad;
++      }
++
++      if ((acx_debug & L_DEBUG) && (cmd != ACX1xx_CMD_INTERROGATE)) {
++              printk("input buffer (len=%u):\n", buflen);
++              acx_dump_bytes(buffer, buflen);
++      }
++
++      /* wait for firmware to become idle for our command submission */
++      timeout = HZ/5;
++      counter = (timeout * 1000 / HZ) - 1; /* in ms */
++      timeout += jiffies;
++      do {
++              cmd_status = acxmem_read_cmd_type_status(adev);
++              /* Test for IDLE state */
++              if (!cmd_status)
++                      break;
++              if (counter % 8 == 0) {
++                      if (time_after(jiffies, timeout)) {
++                              counter = 0;
++                              break;
++                      }
++                      /* we waited 8 iterations, no luck. Sleep 8 ms */
++                      acx_s_msleep(8);
++              }
++      } while (likely(--counter));
++
++      if (!counter) {
++              /* the card doesn't get idle, we're in trouble */
++              printk("%s: "FUNC"(): cmd_status is not IDLE: 0x%04X!=0\n",
++                      devname, cmd_status);
++#if DUMP_IF_SLOW > 0
++              dump_acxmem (adev, 0, 0x10000);
++              panic ("not idle");
++#endif
++              goto bad;
++      } else if (counter < 190) { /* if waited >10ms... */
++              log(L_CTL|L_DEBUG, FUNC"(): waited for IDLE %dms. "
++                      "Please report\n", 199 - counter);
++      }
++
++      /* now write the parameters of the command if needed */
++      if (buffer && buflen) {
++              /* if it's an INTERROGATE command, just pass the length
++               * of parameters to read, as data */
++#if CMD_DISCOVERY
++              if (cmd == ACX1xx_CMD_INTERROGATE)
++                      memset_io(adev->cmd_area + 4, 0xAA, buflen);
++#endif
++              /*
++               * slave memory version
++               */
++              copy_to_slavemem (adev, (u32) (adev->cmd_area + 4), buffer, 
++                             (cmd == ACX1xx_CMD_INTERROGATE) ? 4 : buflen);
++      }
++      /* now write the actual command type */
++      acxmem_write_cmd_type_status(adev, cmd, 0);
++
++      /* clear CMD_COMPLETE bit. can be set only by IRQ handler: */
++      adev->irq_status &= ~HOST_INT_CMD_COMPLETE;
++
++      /* execute command */
++      write_reg16(adev, IO_ACX_INT_TRIG, INT_TRIG_CMD);
++      write_flush(adev);
++
++      /* wait for firmware to process command */
++
++      /* Ensure nonzero and not too large timeout.
++      ** Also converts e.g. 100->99, 200->199
++      ** which is nice but not essential */
++      cmd_timeout = (cmd_timeout-1) | 1;
++      if (unlikely(cmd_timeout > 1199))
++              cmd_timeout = 1199;
++
++      /* we schedule away sometimes (timeout can be large) */
++      counter = cmd_timeout;
++      timeout = jiffies + cmd_timeout * HZ / 1000;
++      do {
++              if (!adev->irqs_active) { /* IRQ disabled: poll */
++                      irqtype = read_reg16(adev, IO_ACX_IRQ_STATUS_NON_DES);
++                      if (irqtype & HOST_INT_CMD_COMPLETE) {
++                              write_reg16(adev, IO_ACX_IRQ_ACK,
++                                              HOST_INT_CMD_COMPLETE);
++                              break;
++                      }
++              } else { /* Wait when IRQ will set the bit */
++                      irqtype = adev->irq_status;
++                      if (irqtype & HOST_INT_CMD_COMPLETE)
++                              break;
++              }
++
++              if (counter % 8 == 0) {
++                      if (time_after(jiffies, timeout)) {
++                              counter = 0;
++                              break;
++                      }
++                      /* we waited 8 iterations, no luck. Sleep 8 ms */
++                      acx_s_msleep(8);
++              }
++      } while (likely(--counter));
++
++      /* save state for debugging */
++      cmd_status = acxmem_read_cmd_type_status(adev);
++
++      /* put the card in IDLE state */
++      acxmem_write_cmd_type_status(adev, ACX1xx_CMD_RESET, 0);
++
++      if (!counter) { /* timed out! */
++              printk("%s: "FUNC"(): timed out %s for CMD_COMPLETE. "
++                      "irq bits:0x%04X irq_status:0x%04X timeout:%dms "
++                      "cmd_status:%d (%s)\n",
++                      devname, (adev->irqs_active) ? "waiting" : "polling",
++                      irqtype, adev->irq_status, cmd_timeout,
++                      cmd_status, acx_cmd_status_str(cmd_status));
++              printk("%s: "FUNC"(): device irq status 0x%04x\n",
++                     devname, read_reg16(adev, IO_ACX_IRQ_STATUS_NON_DES));
++              printk("%s: "FUNC"(): IO_ACX_IRQ_MASK 0x%04x IO_ACX_FEMR 0x%04x\n",
++                     devname,
++                     read_reg16 (adev, IO_ACX_IRQ_MASK),
++                     read_reg16 (adev, IO_ACX_FEMR));
++              if (read_reg16 (adev, IO_ACX_IRQ_MASK) == 0xffff) {
++                      printk ("acxmem: firmware probably hosed - reloading\n");
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11)
++                      {
++                              pm_message_t state;
++                              acxmem_e_suspend (resume_pdev, state);
++                      }
++#else
++                      acxmem_e_suspend (adev->dev, 0);
++#endif
++                      {
++                              struct work_struct *notused;
++                              fw_resumer (notused);
++                      }
++              }
++
++              goto bad;
++      } else if (cmd_timeout - counter > 30) { /* if waited >30ms... */
++              log(L_CTL|L_DEBUG, FUNC"(): %s for CMD_COMPLETE %dms. "
++                      "count:%d. Please report\n",
++                      (adev->irqs_active) ? "waited" : "polled",
++                      cmd_timeout - counter, counter);
++      }
++
++      if (1 != cmd_status) { /* it is not a 'Success' */
++              printk("%s: "FUNC"(): cmd_status is not SUCCESS: %d (%s). "
++                      "Took %dms of %d\n",
++                      devname, cmd_status, acx_cmd_status_str(cmd_status),
++                      cmd_timeout - counter, cmd_timeout);
++              /* zero out result buffer
++               * WARNING: this will trash stack in case of illegally large input
++               * length! */
++              if (buflen > 388) {
++                /*
++                 * 388 is maximum command length
++                 */
++                printk ("invalid length 0x%08x\n", buflen);
++                buflen = 388;
++              }
++              p = (u8 *) buffer;
++              for (i = 0; i < buflen; i+= 16) {
++                printk ("%04x:", i);
++                for (j = 0; (j < 16) && (i+j < buflen); j++) {
++                  printk (" %02x", *p++);
++                }
++                printk ("\n");
++              }
++
++              if (buffer && buflen)
++                      memset(buffer, 0, buflen);
++              goto bad;
++      }
++
++      /* read in result parameters if needed */
++      if (buffer && buflen && (cmd == ACX1xx_CMD_INTERROGATE)) {
++              copy_from_slavemem (adev, buffer, (u32) (adev->cmd_area + 4), buflen);
++              if (acx_debug & L_DEBUG) {
++                      printk("output buffer (len=%u): ", buflen);
++                      acx_dump_bytes(buffer, buflen);
++              }
++      }
++
++/* ok: */
++      log(L_CTL, FUNC"(%s): took %ld jiffies to complete\n",
++                       cmdstr, jiffies - start);
++      FN_EXIT1(OK);
++      return OK;
++
++bad:
++      /* Give enough info so that callers can avoid
++      ** printing their own diagnostic messages */
++#if ACX_DEBUG
++      printk("%s: "FUNC"(cmd:%s) FAILED\n", devname, cmdstr);
++#else
++      printk("%s: "FUNC"(cmd:0x%04X) FAILED\n", devname, cmd);
++#endif
++      dump_stack();
++      FN_EXIT1(NOT_OK);
++      return NOT_OK;
++}
++
++
++/***********************************************************************
++*/
++#if defined(NONESSENTIAL_FEATURES)
++typedef struct device_id {
++      unsigned char id[6];
++      char *descr;
++      char *type;
++} device_id_t;
++
++static const device_id_t
++device_ids[] =
++{
++      {
++              {'G', 'l', 'o', 'b', 'a', 'l'},
++              NULL,
++              NULL,
++      },
++      {
++              {0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
++              "uninitialized",
++              "SpeedStream SS1021 or Gigafast WF721-AEX"
++      },
++      {
++              {0x80, 0x81, 0x82, 0x83, 0x84, 0x85},
++              "non-standard",
++              "DrayTek Vigor 520"
++      },
++      {
++              {'?', '?', '?', '?', '?', '?'},
++              "non-standard",
++              "Level One WPC-0200"
++      },
++      {
++              {0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
++              "empty",
++              "DWL-650+ variant"
++      }
++};
++
++static void
++acx_show_card_eeprom_id(acx_device_t *adev)
++{
++      unsigned char buffer[CARD_EEPROM_ID_SIZE];
++      int i;
++
++      memset(&buffer, 0, CARD_EEPROM_ID_SIZE);
++      /* use direct EEPROM access */
++      for (i = 0; i < CARD_EEPROM_ID_SIZE; i++) {
++              if (OK != acxmem_read_eeprom_byte(adev,
++                                       ACX100_EEPROM_ID_OFFSET + i,
++                                       &buffer[i])) {
++                      printk("acx: reading EEPROM FAILED\n");
++                      break;
++              }
++      }
++
++      for (i = 0; i < VEC_SIZE(device_ids); i++) {
++              if (!memcmp(&buffer, device_ids[i].id, CARD_EEPROM_ID_SIZE)) {
++                      if (device_ids[i].descr) {
++                              printk("acx: EEPROM card ID string check "
++                                      "found %s card ID: is this %s?\n",
++                                      device_ids[i].descr, device_ids[i].type);
++                      }
++                      break;
++              }
++      }
++      if (i == VEC_SIZE(device_ids)) {
++              printk("acx: EEPROM card ID string check found "
++                      "unknown card: expected 'Global', got '%.*s\'. "
++                      "Please report\n", CARD_EEPROM_ID_SIZE, buffer);
++      }
++}
++#endif /* NONESSENTIAL_FEATURES */
++
++/***********************************************************************
++** acxmem_free_desc_queues
++**
++** Releases the queues that have been allocated, the
++** others have been initialised to NULL so this
++** function can be used if only part of the queues were allocated.
++*/
++
++void
++acxmem_free_desc_queues(acx_device_t *adev)
++{
++#define ACX_FREE_QUEUE(size, ptr, phyaddr) \
++        if (ptr) { \
++                kfree(ptr); \
++                ptr = NULL; \
++                size = 0; \
++        }
++
++      FN_ENTER;
++
++      ACX_FREE_QUEUE(adev->txhostdesc_area_size, adev->txhostdesc_start, adev->txhostdesc_startphy);
++      ACX_FREE_QUEUE(adev->txbuf_area_size, adev->txbuf_start, adev->txbuf_startphy);
++
++      adev->txdesc_start = NULL;
++
++      ACX_FREE_QUEUE(adev->rxhostdesc_area_size, adev->rxhostdesc_start, adev->rxhostdesc_startphy);
++      ACX_FREE_QUEUE(adev->rxbuf_area_size, adev->rxbuf_start, adev->rxbuf_startphy);
++
++      adev->rxdesc_start = NULL;
++
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++** acxmem_s_delete_dma_regions
++*/
++static void
++acxmem_s_delete_dma_regions(acx_device_t *adev)
++{
++      unsigned long flags;
++
++      FN_ENTER;
++      /* disable radio Tx/Rx. Shouldn't we use the firmware commands
++       * here instead? Or are we that much down the road that it's no
++       * longer possible here? */
++      /*
++       * slave memory interface really doesn't like this.
++       */
++      /*
++      write_reg16(adev, IO_ACX_ENABLE, 0);
++      */
++
++      acx_s_msleep(100);
++
++      acx_lock(adev, flags);
++      acxmem_free_desc_queues(adev);
++      acx_unlock(adev, flags);
++
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++** acxmem_e_probe
++**
++** Probe routine called when a PCI device w/ matching ID is found.
++** Here's the sequence:
++**   - Allocate the PCI resources.
++**   - Read the PCMCIA attribute memory to make sure we have a WLAN card
++**   - Reset the MAC
++**   - Initialize the dev and wlan data
++**   - Initialize the MAC
++**
++** pdev       - ptr to pci device structure containing info about pci configuration
++** id - ptr to the device id entry that matched this device
++*/
++static const u16
++IO_ACX100[] =
++{
++      0x0000, /* IO_ACX_SOFT_RESET */
++
++      0x0014, /* IO_ACX_SLV_MEM_ADDR */
++      0x0018, /* IO_ACX_SLV_MEM_DATA */
++      0x001c, /* IO_ACX_SLV_MEM_CTL */
++      0x0020, /* IO_ACX_SLV_END_CTL */
++
++      0x0034, /* IO_ACX_FEMR */
++
++      0x007c, /* IO_ACX_INT_TRIG */
++      0x0098, /* IO_ACX_IRQ_MASK */
++      0x00a4, /* IO_ACX_IRQ_STATUS_NON_DES */
++      0x00a8, /* IO_ACX_IRQ_STATUS_CLEAR */
++      0x00ac, /* IO_ACX_IRQ_ACK */
++      0x00b0, /* IO_ACX_HINT_TRIG */
++
++      0x0104, /* IO_ACX_ENABLE */
++
++      0x0250, /* IO_ACX_EEPROM_CTL */
++      0x0254, /* IO_ACX_EEPROM_ADDR */
++      0x0258, /* IO_ACX_EEPROM_DATA */
++      0x025c, /* IO_ACX_EEPROM_CFG */
++
++      0x0268, /* IO_ACX_PHY_ADDR */
++      0x026c, /* IO_ACX_PHY_DATA */
++      0x0270, /* IO_ACX_PHY_CTL */
++
++      0x0290, /* IO_ACX_GPIO_OE */
++
++      0x0298, /* IO_ACX_GPIO_OUT */
++
++      0x02a4, /* IO_ACX_CMD_MAILBOX_OFFS */
++      0x02a8, /* IO_ACX_INFO_MAILBOX_OFFS */
++      0x02ac, /* IO_ACX_EEPROM_INFORMATION */
++
++      0x02d0, /* IO_ACX_EE_START */
++      0x02d4, /* IO_ACX_SOR_CFG */
++      0x02d8 /* IO_ACX_ECPU_CTRL */
++};
++
++static const u16
++IO_ACX111[] =
++{
++      0x0000, /* IO_ACX_SOFT_RESET */
++
++      0x0014, /* IO_ACX_SLV_MEM_ADDR */
++      0x0018, /* IO_ACX_SLV_MEM_DATA */
++      0x001c, /* IO_ACX_SLV_MEM_CTL */
++      0x0020, /* IO_ACX_SLV_MEM_CP */
++
++      0x0034, /* IO_ACX_FEMR */
++
++      0x00b4, /* IO_ACX_INT_TRIG */
++      0x00d4, /* IO_ACX_IRQ_MASK */
++      /* we do mean NON_DES (0xf0), not NON_DES_MASK which is at 0xe0: */
++      0x00f0, /* IO_ACX_IRQ_STATUS_NON_DES */
++      0x00e4, /* IO_ACX_IRQ_STATUS_CLEAR */
++      0x00e8, /* IO_ACX_IRQ_ACK */
++      0x00ec, /* IO_ACX_HINT_TRIG */
++
++      0x01d0, /* IO_ACX_ENABLE */
++
++      0x0338, /* IO_ACX_EEPROM_CTL */
++      0x033c, /* IO_ACX_EEPROM_ADDR */
++      0x0340, /* IO_ACX_EEPROM_DATA */
++      0x0344, /* IO_ACX_EEPROM_CFG */
++
++      0x0350, /* IO_ACX_PHY_ADDR */
++      0x0354, /* IO_ACX_PHY_DATA */
++      0x0358, /* IO_ACX_PHY_CTL */
++
++      0x0374, /* IO_ACX_GPIO_OE */
++
++      0x037c, /* IO_ACX_GPIO_OUT */
++
++      0x0388, /* IO_ACX_CMD_MAILBOX_OFFS */
++      0x038c, /* IO_ACX_INFO_MAILBOX_OFFS */
++      0x0390, /* IO_ACX_EEPROM_INFORMATION */
++
++      0x0100, /* IO_ACX_EE_START */
++      0x0104, /* IO_ACX_SOR_CFG */
++      0x0108, /* IO_ACX_ECPU_CTRL */
++};
++
++static void
++dummy_netdev_init(struct net_device *ndev) {}
++
++/*
++ * Most of the acx specific pieces of hardware reset.
++ */
++static int
++acxmem_complete_hw_reset (acx_device_t *adev)
++{
++      acx111_ie_configoption_t co;
++
++      /* NB: read_reg() reads may return bogus data before reset_dev(),
++       * since the firmware which directly controls large parts of the I/O
++       * registers isn't initialized yet.
++       * acx100 seems to be more affected than acx111 */
++      if (OK != acxmem_s_reset_dev (adev))
++        return -1;
++
++      if (IS_ACX100(adev)) {
++              /* ACX100: configopt struct in cmd mailbox - directly after reset */
++              copy_from_slavemem (adev, (u8*) &co, (u32) adev->cmd_area, sizeof (co));
++      }
++
++      if (OK != acx_s_init_mac(adev))
++        return -3;
++
++      if (IS_ACX111(adev)) {
++              /* ACX111: configopt struct needs to be queried after full init */
++              acx_s_interrogate(adev, &co, ACX111_IE_CONFIG_OPTIONS);
++      }
++
++      /*
++       * Set up transmit buffer administration
++       */
++      init_acx_txbuf (adev);
++
++      /*
++       * Windows driver writes 0x01000000 to register 0x288, RADIO_CTL, if the form factor
++       * is 3.  It also write protects the EEPROM by writing 1<<9 to GPIO_OUT
++       */
++      if (adev->form_factor == 3) {
++        set_regbits (adev, 0x288, 0x01000000);
++        set_regbits (adev, 0x298, 1<<9);
++      }
++
++/* TODO: merge them into one function, they are called just once and are the same for pci & usb */
++      if (OK != acxmem_read_eeprom_byte(adev, 0x05, &adev->eeprom_version))
++        return -2;
++
++      acx_s_parse_configoption(adev, &co);
++      acx_s_get_firmware_version(adev); /* needs to be after acx_s_init_mac() */
++      acx_display_hardware_details(adev);
++
++      return 0;
++}
++
++static int __devinit
++acxmem_e_probe(struct platform_device *pdev)
++{
++      struct acx_hardware_data *hwdata = pdev->dev.platform_data;
++      acx_device_t *adev = NULL;
++      struct net_device *ndev = NULL;
++      const char *chip_name;
++      int result = -EIO;
++      int err;
++      int i;
++      unsigned long addr_size=0;
++      u8 chip_type;
++
++      FN_ENTER;
++      (void) hwdata->start_hw();
++
++      /* FIXME: prism54 calls pci_set_mwi() here,
++       * should we do/support the same? */
++
++      /* chiptype is u8 but id->driver_data is ulong
++      ** Works for now (possible values are 1 and 2) */
++      chip_type = CHIPTYPE_ACX100;
++      /* acx100 and acx111 have different PCI memory regions */
++      if (chip_type == CHIPTYPE_ACX100) {
++              chip_name = "ACX100";
++      } else if (chip_type == CHIPTYPE_ACX111) {
++              chip_name = "ACX111";
++      } else {
++              printk("acx: unknown chip type 0x%04X\n", chip_type);
++              goto fail_unknown_chiptype;
++      }
++
++      printk("acx: found %s-based wireless network card\n", chip_name);
++      log(L_ANY, "initial debug setting is 0x%04X\n", acx_debug);
++
++      ndev = alloc_netdev(sizeof(*adev), "wlan%d", dummy_netdev_init);
++      /* (NB: memsets to 0 entire area) */
++      if (!ndev) {
++              printk("acx: no memory for netdevice struct\n");
++              goto fail_alloc_netdev;
++      }
++
++      platform_set_drvdata (pdev, ndev);
++
++      ether_setup(ndev);
++
++      /*
++       * use platform_data resources that were provided
++       */
++      ndev->irq = 0;
++      for (i=0; i<pdev->num_resources; i++) {
++              if (pdev->resource[i].flags == IORESOURCE_IRQ) {
++                      ndev->irq = pdev->resource[i].start;
++              }
++              else if (pdev->resource[i].flags == IORESOURCE_MEM) {
++                      ndev->base_addr = pdev->resource[i].start;
++                      addr_size = pdev->resource[i].end - pdev->resource[i].start;
++              }
++      }
++      if (addr_size == 0 || ndev->irq == 0)
++              goto fail_hw_params;
++      ndev->open = &acxmem_e_open;
++      ndev->stop = &acxmem_e_close;
++      pdev->dev.release = &acxmem_e_release;
++      ndev->hard_start_xmit = &acx_i_start_xmit;
++      ndev->get_stats = &acx_e_get_stats;
++#if IW_HANDLER_VERSION <= 5
++      ndev->get_wireless_stats = &acx_e_get_wireless_stats;
++#endif
++      ndev->wireless_handlers = (struct iw_handler_def *)&acx_ioctl_handler_def;
++      ndev->set_multicast_list = &acxmem_i_set_multicast_list;
++      ndev->tx_timeout = &acxmem_i_tx_timeout;
++      ndev->change_mtu = &acx_e_change_mtu;
++      ndev->watchdog_timeo = 4 * HZ;
++
++      adev = ndev2adev(ndev);
++      spin_lock_init(&adev->lock);    /* initial state: unlocked */
++      spin_lock_init(&adev->txbuf_lock);
++      /* We do not start with downed sem: we want PARANOID_LOCKING to work */
++      sema_init(&adev->sem, 1);       /* initial state: 1 (upped) */
++      /* since nobody can see new netdev yet, we can as well
++      ** just _presume_ that we're under sem (instead of actually taking it): */
++      /* acx_sem_lock(adev); */
++      adev->dev = &pdev->dev;
++      adev->ndev = ndev;
++      adev->dev_type = DEVTYPE_MEM;
++      adev->chip_type = chip_type;
++      adev->chip_name = chip_name;
++      adev->io = (CHIPTYPE_ACX100 == chip_type) ? IO_ACX100 : IO_ACX111;
++      adev->membase = (volatile u32 *) ndev->base_addr;
++      adev->iobase = (volatile u32 *) ioremap_nocache (ndev->base_addr, addr_size);
++      /* to find crashes due to weird driver access
++       * to unconfigured interface (ifup) */
++      adev->mgmt_timer.function = (void (*)(unsigned long))0x0000dead;
++
++#if defined(NONESSENTIAL_FEATURES)
++      acx_show_card_eeprom_id(adev);
++#endif /* NONESSENTIAL_FEATURES */
++
++#ifdef SET_MODULE_OWNER
++      SET_MODULE_OWNER(ndev);
++#endif
++      SET_NETDEV_DEV(ndev, &pdev->dev);
++
++      log(L_IRQ|L_INIT, "using IRQ %d\n", ndev->irq);
++
++      /* ok, pci setup is finished, now start initializing the card */
++
++      if (OK != acxmem_complete_hw_reset (adev))
++        goto fail_reset;
++
++      /*
++       * Set up default things for most of the card settings.
++       */
++      acx_s_set_defaults(adev);
++
++      /* Register the card, AFTER everything else has been set up,
++       * since otherwise an ioctl could step on our feet due to
++       * firmware operations happening in parallel or uninitialized data */
++      err = register_netdev(ndev);
++      if (OK != err) {
++              printk("acx: register_netdev() FAILED: %d\n", err);
++              goto fail_register_netdev;
++      }
++
++      acx_proc_register_entries(ndev);
++
++      /* Now we have our device, so make sure the kernel doesn't try
++       * to send packets even though we're not associated to a network yet */
++      acx_stop_queue(ndev, "on probe");
++      acx_carrier_off(ndev, "on probe");
++
++      /*
++       * Set up a default monitor type so that poor combinations of initialization
++       * sequences in monitor mode don't end up destroying the hardware type.
++       */
++      adev->monitor_type = ARPHRD_ETHER;
++
++      /*
++       * Register to receive inetaddr notifier changes.  This will allow us to
++       * catch if the user changes the MAC address of the interface.
++       */
++      register_netdevice_notifier(&acx_netdev_notifier);
++
++      /* after register_netdev() userspace may start working with dev
++       * (in particular, on other CPUs), we only need to up the sem */
++      /* acx_sem_unlock(adev); */
++
++      printk("acx "ACX_RELEASE": net device %s, driver compiled "
++              "against wireless extensions %d and Linux %s\n",
++              ndev->name, WIRELESS_EXT, UTS_RELEASE);
++
++#if CMD_DISCOVERY
++      great_inquisitor(adev);
++#endif
++
++      result = OK;
++      goto done;
++
++      /* error paths: undo everything in reverse order... */
++
++fail_register_netdev:
++
++      acxmem_s_delete_dma_regions(adev);
++
++fail_reset:
++fail_hw_params:
++      free_netdev(ndev);
++fail_alloc_netdev:
++fail_unknown_chiptype:
++
++
++done:
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/***********************************************************************
++** acxmem_e_remove
++**
++** Shut device down (if not hot unplugged)
++** and deallocate PCI resources for the acx chip.
++**
++** pdev - ptr to PCI device structure containing info about pci configuration
++*/
++static int __devexit
++acxmem_e_remove(struct platform_device *pdev)
++{
++      struct acx_hardware_data *hwdata = pdev->dev.platform_data;
++      struct net_device *ndev;
++      acx_device_t *adev;
++      unsigned long flags;
++
++      FN_ENTER;
++
++      ndev = (struct net_device*) platform_get_drvdata(pdev);
++      if (!ndev) {
++              log(L_DEBUG, "%s: card is unused. Skipping any release code\n",
++                      __func__);
++              goto end;
++      }
++
++      adev = ndev2adev(ndev);
++
++      /* If device wasn't hot unplugged... */
++      if (adev_present(adev)) {
++
++              acx_sem_lock(adev);
++
++              /* disable both Tx and Rx to shut radio down properly */
++              acx_s_issue_cmd(adev, ACX1xx_CMD_DISABLE_TX, NULL, 0);
++              acx_s_issue_cmd(adev, ACX1xx_CMD_DISABLE_RX, NULL, 0);
++
++#ifdef REDUNDANT
++              /* put the eCPU to sleep to save power
++               * Halting is not possible currently,
++               * since not supported by all firmware versions */
++              acx_s_issue_cmd(adev, ACX100_CMD_SLEEP, NULL, 0);
++#endif
++              acx_lock(adev, flags);
++
++              /* disable power LED to save power :-) */
++              log(L_INIT, "switching off power LED to save power\n");
++              acxmem_l_power_led(adev, 0);
++
++              /* stop our eCPU */
++              if (IS_ACX111(adev)) {
++                      /* FIXME: does this actually keep halting the eCPU?
++                       * I don't think so...
++                       */
++                      acxmem_l_reset_mac(adev);
++              } else {
++                      u16 temp;
++
++                      /* halt eCPU */
++                      temp = read_reg16(adev, IO_ACX_ECPU_CTRL) | 0x1;
++                      write_reg16(adev, IO_ACX_ECPU_CTRL, temp);
++                      write_flush(adev);
++              }
++
++              acx_unlock(adev, flags);
++
++              acx_sem_unlock(adev);
++      }
++
++
++      /*
++       * Unregister the notifier chain
++       */
++      unregister_netdevice_notifier(&acx_netdev_notifier);
++
++      /* unregister the device to not let the kernel
++       * (e.g. ioctls) access a half-deconfigured device
++       * NB: this will cause acxmem_e_close() to be called,
++       * thus we shouldn't call it under sem! */
++      log(L_INIT, "removing device %s\n", ndev->name);
++      unregister_netdev(ndev);
++
++      /* unregister_netdev ensures that no references to us left.
++       * For paranoid reasons we continue to follow the rules */
++      acx_sem_lock(adev);
++
++      if (adev->dev_state_mask & ACX_STATE_IFACE_UP) {
++              acxmem_s_down(ndev);
++              CLEAR_BIT(adev->dev_state_mask, ACX_STATE_IFACE_UP);
++      }
++
++      acx_proc_unregister_entries(ndev);
++
++      acxmem_s_delete_dma_regions(adev);
++
++      /* finally, clean up PCI bus state */
++      if (adev->iobase) iounmap((void *)adev->iobase);
++
++      acx_sem_unlock(adev);
++
++      /* Free netdev (quite late,
++       * since otherwise we might get caught off-guard
++       * by a netdev timeout handler execution
++       * expecting to see a working dev...) */
++      free_netdev(ndev);
++
++      (void) hwdata->stop_hw();
++
++      printk ("e_remove done\n");
++end:
++      FN_EXIT0;
++
++      return 0;
++}
++
++
++/***********************************************************************
++** TODO: PM code needs to be fixed / debugged / tested.
++*/
++#ifdef CONFIG_PM
++static int
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11)
++acxmem_e_suspend(struct platform_device *pdev, pm_message_t state)
++#else
++acxmem_e_suspend(struct device *pdev, u32 state)
++#endif
++{
++      struct net_device *ndev = platform_get_drvdata(pdev);
++      acx_device_t *adev;
++      struct acx_hardware_data *hwdata;
++
++      FN_ENTER;
++      printk("acx: suspend handler is experimental!\n");
++      printk("sus: dev %p\n", ndev);
++
++      if (!netif_running(ndev))
++              goto end;
++
++      adev = ndev2adev(ndev);
++      printk("sus: adev %p\n", adev);
++
++      hwdata = adev->dev->platform_data;
++
++      acx_sem_lock(adev);
++
++      netif_device_detach(ndev);      /* this one cannot sleep */
++      acxmem_s_down(ndev);
++      /* down() does not set it to 0xffff, but here we really want that */
++      write_reg16(adev, IO_ACX_IRQ_MASK, 0xffff);
++      write_reg16(adev, IO_ACX_FEMR, 0x0);
++      acxmem_s_delete_dma_regions(adev);
++
++      /*
++       * Turn the ACX chip off.
++       */
++      hwdata->stop_hw();
++
++      acx_sem_unlock(adev);
++end:
++      FN_EXIT0;
++      return OK;
++}
++
++
++
++static void
++fw_resumer(struct work_struct *notused)
++{
++        struct platform_device *pdev = resume_pdev;
++      struct net_device *ndev = platform_get_drvdata(pdev);
++      acx_device_t *adev;
++      struct acx_hardware_data *hwdata;
++
++      printk("acx: resume handler is experimental!\n");
++      printk("rsm: got dev %p\n", ndev);
++
++      if (!netif_running(ndev))
++              return;
++
++      adev = ndev2adev(ndev);
++      printk("rsm: got adev %p\n", adev);
++
++      acx_sem_lock(adev);
++
++      hwdata = adev->dev->platform_data;
++
++      /*
++       * Turn on the ACX.
++       */
++      hwdata->start_hw();
++
++      acxmem_complete_hw_reset (adev);
++
++      /*
++       * done by acx_s_set_defaults for initial startup
++       */
++      acxmem_set_interrupt_mask(adev);
++
++      printk ("rsm: bringing up interface\n");
++      SET_BIT (adev->set_mask, GETSET_ALL);
++      acxmem_s_up(ndev);
++      printk("rsm: acx up done\n");
++
++      /* now even reload all card parameters as they were before suspend,
++       * and possibly be back in the network again already :-) 
++       */
++      /* - most settings updated in acxmem_s_up()
++      if (ACX_STATE_IFACE_UP & adev->dev_state_mask) {
++              adev->set_mask = GETSET_ALL;
++              acx_s_update_card_settings(adev);
++              printk("rsm: settings updated\n");
++      }
++      */
++      netif_device_attach(ndev);
++      printk("rsm: device attached\n");
++
++      acx_sem_unlock(adev);
++}
++
++DECLARE_WORK( fw_resume_work, fw_resumer );
++
++static int
++acxmem_e_resume(struct platform_device *pdev)
++{
++      FN_ENTER;
++
++      resume_pdev = pdev;
++      schedule_work( &fw_resume_work );
++
++      FN_EXIT0;
++      return OK;
++}
++#endif /* CONFIG_PM */
++
++
++/***********************************************************************
++** acxmem_s_up
++**
++** This function is called by acxmem_e_open (when ifconfig sets the device as up)
++**
++** Side effects:
++** - Enables on-card interrupt requests
++** - calls acx_s_start
++*/
++
++static void
++enable_acx_irq(acx_device_t *adev)
++{
++      FN_ENTER;
++      write_reg16(adev, IO_ACX_IRQ_MASK, adev->irq_mask);
++      write_reg16(adev, IO_ACX_FEMR, 0x8000);
++      adev->irqs_active = 1;
++      FN_EXIT0;
++}
++
++static void
++acxmem_s_up(struct net_device *ndev)
++{
++      acx_device_t *adev = ndev2adev(ndev);
++      unsigned long flags;
++
++      FN_ENTER;
++
++      acx_lock(adev, flags);
++      enable_acx_irq(adev);
++      acx_unlock(adev, flags);
++
++      /* acx fw < 1.9.3.e has a hardware timer, and older drivers
++      ** used to use it. But we don't do that anymore, our OS
++      ** has reliable software timers */
++      init_timer(&adev->mgmt_timer);
++      adev->mgmt_timer.function = acx_i_timer;
++      adev->mgmt_timer.data = (unsigned long)adev;
++
++      /* Need to set ACX_STATE_IFACE_UP first, or else
++      ** timer won't be started by acx_set_status() */
++      SET_BIT(adev->dev_state_mask, ACX_STATE_IFACE_UP);
++      switch (adev->mode) {
++      case ACX_MODE_0_ADHOC:
++      case ACX_MODE_2_STA:
++              /* actual scan cmd will happen in start() */
++              acx_set_status(adev, ACX_STATUS_1_SCANNING); break;
++      case ACX_MODE_3_AP:
++      case ACX_MODE_MONITOR:
++              acx_set_status(adev, ACX_STATUS_4_ASSOCIATED); break;
++      }
++
++      acx_s_start(adev);
++
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++** acxmem_s_down
++**
++** This disables the netdevice
++**
++** Side effects:
++** - disables on-card interrupt request
++*/
++
++static void
++disable_acx_irq(acx_device_t *adev)
++{
++      FN_ENTER;
++
++      /* I guess mask is not 0xffff because acx100 won't signal
++      ** cmd completion then (needed for ifup).
++      ** Someone with acx100 please confirm */
++      write_reg16(adev, IO_ACX_IRQ_MASK, adev->irq_mask_off);
++      write_reg16(adev, IO_ACX_FEMR, 0x0);
++      adev->irqs_active = 0;
++      FN_EXIT0;
++}
++
++static void
++acxmem_s_down(struct net_device *ndev)
++{
++      acx_device_t *adev = ndev2adev(ndev);
++      unsigned long flags;
++
++      FN_ENTER;
++
++      /* Disable IRQs first, so that IRQs cannot race with us */
++      /* then wait until interrupts have finished executing on other CPUs */
++      acx_lock(adev, flags);
++      disable_acx_irq(adev);
++      synchronize_irq(adev->pdev->irq);
++      acx_unlock(adev, flags);
++
++      /* we really don't want to have an asynchronous tasklet disturb us
++      ** after something vital for its job has been shut down, so
++      ** end all remaining work now.
++      **
++      ** NB: carrier_off (done by set_status below) would lead to
++      ** not yet fully understood deadlock in FLUSH_SCHEDULED_WORK().
++      ** That's why we do FLUSH first.
++      **
++      ** NB2: we have a bad locking bug here: FLUSH_SCHEDULED_WORK()
++      ** waits for acx_e_after_interrupt_task to complete if it is running
++      ** on another CPU, but acx_e_after_interrupt_task
++      ** will sleep on sem forever, because it is taken by us!
++      ** Work around that by temporary sem unlock.
++      ** This will fail miserably if we'll be hit by concurrent
++      ** iwconfig or something in between. TODO! */
++      acx_sem_unlock(adev);
++      FLUSH_SCHEDULED_WORK();
++      acx_sem_lock(adev);
++
++      /* This is possible:
++      ** FLUSH_SCHEDULED_WORK -> acx_e_after_interrupt_task ->
++      ** -> set_status(ASSOCIATED) -> wake_queue()
++      ** That's why we stop queue _after_ FLUSH_SCHEDULED_WORK
++      ** lock/unlock is just paranoia, maybe not needed */
++      acx_lock(adev, flags);
++      acx_stop_queue(ndev, "on ifdown");
++      acx_set_status(adev, ACX_STATUS_0_STOPPED);
++      acx_unlock(adev, flags);
++
++      /* kernel/timer.c says it's illegal to del_timer_sync()
++      ** a timer which restarts itself. We guarantee this cannot
++      ** ever happen because acx_i_timer() never does this if
++      ** status is ACX_STATUS_0_STOPPED */
++      del_timer_sync(&adev->mgmt_timer);
++
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++** acxmem_e_open
++**
++** Called as a result of SIOCSIFFLAGS ioctl changing the flags bit IFF_UP
++** from clear to set. In other words: ifconfig up.
++**
++** Returns:
++**    0       success
++**    >0      f/w reported error
++**    <0      driver reported error
++*/
++static int
++acxmem_e_open(struct net_device *ndev)
++{
++      acx_device_t *adev = ndev2adev(ndev);
++      int result = OK;
++
++      FN_ENTER;
++
++      acx_sem_lock(adev);
++
++      acx_init_task_scheduler(adev);
++
++/* TODO: pci_set_power_state(pdev, PCI_D0); ? */
++
++      /* request shared IRQ handler */
++      if (request_irq(ndev->irq, acxmem_i_interrupt, SA_INTERRUPT, ndev->name, ndev)) {
++              printk("%s: request_irq FAILED\n", ndev->name);
++              result = -EAGAIN;
++              goto done;
++      }
++      set_irq_type (ndev->irq, IRQT_FALLING);
++      log(L_DEBUG|L_IRQ, "request_irq %d successful\n", ndev->irq);
++
++      /* ifup device */
++      acxmem_s_up(ndev);
++
++      /* We don't currently have to do anything else.
++       * The setup of the MAC should be subsequently completed via
++       * the mlme commands.
++       * Higher layers know we're ready from dev->start==1 and
++       * dev->tbusy==0.  Our rx path knows to pass up received/
++       * frames because of dev->flags&IFF_UP is true.
++       */
++done:
++      acx_sem_unlock(adev);
++
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/***********************************************************************
++** acxmem_e_close
++**
++** Called as a result of SIOCSIIFFLAGS ioctl changing the flags bit IFF_UP
++** from set to clear. I.e. called by "ifconfig DEV down"
++**
++** Returns:
++**    0       success
++**    >0      f/w reported error
++**    <0      driver reported error
++*/
++static int
++acxmem_e_close(struct net_device *ndev)
++{
++      acx_device_t *adev = ndev2adev(ndev);
++
++      FN_ENTER;
++
++      acx_sem_lock(adev);
++
++      /* ifdown device */
++      CLEAR_BIT(adev->dev_state_mask, ACX_STATE_IFACE_UP);
++      if (netif_device_present(ndev)) {
++              acxmem_s_down(ndev);
++      }
++
++      /* disable all IRQs, release shared IRQ handler */
++      write_reg16(adev, IO_ACX_IRQ_MASK, 0xffff);
++      write_reg16(adev, IO_ACX_FEMR, 0x0);
++      free_irq(ndev->irq, ndev);
++
++/* TODO: pci_set_power_state(pdev, PCI_D3hot); ? */
++
++      /* We currently don't have to do anything else.
++       * Higher layers know we're not ready from dev->start==0 and
++       * dev->tbusy==1.  Our rx path knows to not pass up received
++       * frames because of dev->flags&IFF_UP is false.
++       */
++      acx_sem_unlock(adev);
++
++      log(L_INIT, "closed device\n");
++      FN_EXIT0;
++      return OK;
++}
++
++
++/***********************************************************************
++** acxmem_i_tx_timeout
++**
++** Called from network core. Must not sleep!
++*/
++static void
++acxmem_i_tx_timeout(struct net_device *ndev)
++{
++      acx_device_t *adev = ndev2adev(ndev);
++      unsigned long flags;
++      unsigned int tx_num_cleaned;
++
++      FN_ENTER;
++
++      acx_lock(adev, flags);
++
++      /* clean processed tx descs, they may have been completely full */
++      tx_num_cleaned = acxmem_l_clean_txdesc(adev);
++
++      /* nothing cleaned, yet (almost) no free buffers available?
++       * --> clean all tx descs, no matter which status!!
++       * Note that I strongly suspect that doing emergency cleaning
++       * may confuse the firmware. This is a last ditch effort to get
++       * ANYTHING to work again...
++       *
++       * TODO: it's best to simply reset & reinit hw from scratch...
++       */
++      if ((adev->tx_free <= TX_EMERG_CLEAN) && (tx_num_cleaned == 0)) {
++              printk("%s: FAILED to free any of the many full tx buffers. "
++                      "Switching to emergency freeing. "
++                      "Please report!\n", ndev->name);
++              acxmem_l_clean_txdesc_emergency(adev);
++      }
++
++      if (acx_queue_stopped(ndev) && (ACX_STATUS_4_ASSOCIATED == adev->status))
++              acx_wake_queue(ndev, "after tx timeout");
++
++      /* stall may have happened due to radio drift, so recalib radio */
++      acx_schedule_task(adev, ACX_AFTER_IRQ_CMD_RADIO_RECALIB);
++
++      /* do unimportant work last */
++      printk("%s: tx timeout!\n", ndev->name);
++      adev->stats.tx_errors++;
++
++      acx_unlock(adev, flags);
++
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++** acxmem_i_set_multicast_list
++** FIXME: most likely needs refinement
++*/
++static void
++acxmem_i_set_multicast_list(struct net_device *ndev)
++{
++      acx_device_t *adev = ndev2adev(ndev);
++      unsigned long flags;
++
++      FN_ENTER;
++
++      acx_lock(adev, flags);
++
++      /* firmwares don't have allmulti capability,
++       * so just use promiscuous mode instead in this case. */
++      if (ndev->flags & (IFF_PROMISC|IFF_ALLMULTI)) {
++              SET_BIT(adev->rx_config_1, RX_CFG1_RCV_PROMISCUOUS);
++              CLEAR_BIT(adev->rx_config_1, RX_CFG1_FILTER_ALL_MULTI);
++              SET_BIT(adev->set_mask, SET_RXCONFIG);
++              /* let kernel know in case *we* needed to set promiscuous */
++              ndev->flags |= (IFF_PROMISC|IFF_ALLMULTI);
++      } else {
++              CLEAR_BIT(adev->rx_config_1, RX_CFG1_RCV_PROMISCUOUS);
++              SET_BIT(adev->rx_config_1, RX_CFG1_FILTER_ALL_MULTI);
++              SET_BIT(adev->set_mask, SET_RXCONFIG);
++              ndev->flags &= ~(IFF_PROMISC|IFF_ALLMULTI);
++      }
++
++      /* cannot update card settings directly here, atomic context */
++      acx_schedule_task(adev, ACX_AFTER_IRQ_UPDATE_CARD_CFG);
++
++      acx_unlock(adev, flags);
++
++      FN_EXIT0;
++}
++
++
++/***************************************************************
++** acxmem_l_process_rxdesc
++**
++** Called directly and only from the IRQ handler
++*/
++
++#if !ACX_DEBUG
++static inline void log_rxbuffer(const acx_device_t *adev) {}
++#else
++static void
++log_rxbuffer(const acx_device_t *adev)
++{
++      register const struct rxhostdesc *rxhostdesc;
++      int i;
++      /* no FN_ENTER here, we don't want that */
++
++      rxhostdesc = adev->rxhostdesc_start;
++      if (unlikely(!rxhostdesc)) return;
++      for (i = 0; i < RX_CNT; i++) {
++              if ((rxhostdesc->Ctl_16 & cpu_to_le16(DESC_CTL_HOSTOWN))
++               && (rxhostdesc->Status & cpu_to_le32(DESC_STATUS_FULL)))
++                      printk("rx: buf %d full\n", i);
++              rxhostdesc++;
++      }
++}
++#endif
++
++static void
++acxmem_l_process_rxdesc(acx_device_t *adev)
++{
++      register rxhostdesc_t *hostdesc;
++      register rxdesc_t *rxdesc;
++      unsigned count, tail;
++      u32 addr;
++      u8 Ctl_8;
++
++      FN_ENTER;
++
++      if (unlikely(acx_debug & L_BUFR))
++              log_rxbuffer(adev);
++
++      /* First, have a loop to determine the first descriptor that's
++       * full, just in case there's a mismatch between our current
++       * rx_tail and the full descriptor we're supposed to handle. */
++      tail = adev->rx_tail;
++      count = RX_CNT;
++      while (1) {
++              hostdesc = &adev->rxhostdesc_start[tail];
++              rxdesc = &adev->rxdesc_start[tail];
++              /* advance tail regardless of outcome of the below test */
++              tail = (tail + 1) % RX_CNT;
++
++              /*
++               * Unlike the PCI interface, where the ACX can write directly to
++               * the host descriptors, on the slave memory interface we have to
++               * pull these.  All we really need to do is check the Ctl_8 field
++               * in the rx descriptor on the ACX, which should be 0x11000000 if
++               * we should process it.
++               */
++              Ctl_8 = hostdesc->Ctl_16 = read_slavemem8 (adev, (u32) &(rxdesc->Ctl_8));
++                if ((Ctl_8 & DESC_CTL_HOSTOWN) &&
++                  (Ctl_8 & DESC_CTL_ACXDONE))
++                break;                /* found it! */
++
++              if (unlikely(!--count)) /* hmm, no luck: all descs empty, bail out */
++                      goto end;
++      }
++
++      /* now process descriptors, starting with the first we figured out */
++      while (1) {
++              log(L_BUFR, "rx: tail=%u Ctl_8=%02X\n", tail, Ctl_8);
++              /*
++               * If the ACX has CTL_RECLAIM set on this descriptor there
++               * is no buffer associated; it just wants us to tell it to
++               * reclaim the memory.
++               */
++              if (!(Ctl_8 & DESC_CTL_RECLAIM)) {
++
++                /*
++               * slave interface - pull data now
++               */
++              hostdesc->length = read_slavemem16 (adev, (u32) &(rxdesc->total_length));
++
++              /*
++               * hostdesc->data is an rxbuffer_t, which includes header information,
++               * but the length in the data packet doesn't.  The header information
++               * takes up an additional 12 bytes, so add that to the length we copy.
++               */
++              addr = read_slavemem32 (adev, (u32) &(rxdesc->ACXMemPtr));
++                if (addr) {
++                  /*
++                   * How can &(rxdesc->ACXMemPtr) above ever be zero?  Looks like we
++                   * get that now and then - try to trap it for debug.
++                   */
++                  if (addr & 0xffff0000) {
++                    printk("rxdesc 0x%08x\n", (u32) rxdesc);
++                    dump_acxmem (adev, 0, 0x10000);
++                    panic ("Bad access!");
++                  }
++                chaincopy_from_slavemem (adev, (u8 *) hostdesc->data, addr,
++                                         hostdesc->length +
++                                         (u32) &((rxbuffer_t *)0)->hdr_a3);
++              acx_l_process_rxbuf(adev, hostdesc->data);
++                }
++              }
++              else {
++                printk ("rx reclaim only!\n");
++              }
++
++              hostdesc->Status = 0;
++
++              /*
++               * Let the ACX know we're done.
++               */
++              CLEAR_BIT (Ctl_8, DESC_CTL_HOSTOWN);
++                SET_BIT (Ctl_8, DESC_CTL_HOSTDONE);
++              SET_BIT (Ctl_8, DESC_CTL_RECLAIM);
++              write_slavemem8 (adev, (u32) &rxdesc->Ctl_8, Ctl_8);
++
++              /*
++               * Now tell the ACX we've finished with the receive buffer so 
++               * it can finish the reclaim.
++               */
++              write_reg16 (adev, IO_ACX_INT_TRIG, INT_TRIG_RXPRC);
++
++              /* ok, descriptor is handled, now check the next descriptor */
++              hostdesc = &adev->rxhostdesc_start[tail];
++              rxdesc = &adev->rxdesc_start[tail];
++
++              Ctl_8 = hostdesc->Ctl_16 = read_slavemem8 (adev, (u32) &(rxdesc->Ctl_8));
++
++              /* if next descriptor is empty, then bail out */
++              if (!(Ctl_8 & DESC_CTL_HOSTOWN) || !(Ctl_8 & DESC_CTL_ACXDONE))
++                      break;
++
++              tail = (tail + 1) % RX_CNT;
++      }
++end:
++      adev->rx_tail = tail;
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++** acxmem_i_interrupt
++**
++** IRQ handler (atomic context, must not sleep, blah, blah)
++*/
++
++/* scan is complete. all frames now on the receive queue are valid */
++#define INFO_SCAN_COMPLETE      0x0001
++#define INFO_WEP_KEY_NOT_FOUND  0x0002
++/* hw has been reset as the result of a watchdog timer timeout */
++#define INFO_WATCH_DOG_RESET    0x0003
++/* failed to send out NULL frame from PS mode notification to AP */
++/* recommended action: try entering 802.11 PS mode again */
++#define INFO_PS_FAIL            0x0004
++/* encryption/decryption process on a packet failed */
++#define INFO_IV_ICV_FAILURE     0x0005
++
++/* Info mailbox format:
++2 bytes: type
++2 bytes: status
++more bytes may follow
++    rumors say about status:
++      0x0000 info available (set by hw)
++      0x0001 information received (must be set by host)
++      0x1000 info available, mailbox overflowed (messages lost) (set by hw)
++    but in practice we've seen:
++      0x9000 when we did not set status to 0x0001 on prev message
++      0x1001 when we did set it
++      0x0000 was never seen
++    conclusion: this is really a bitfield:
++    0x1000 is 'info available' bit
++    'mailbox overflowed' bit is 0x8000, not 0x1000
++    value of 0x0000 probably means that there are no messages at all
++    P.S. I dunno how in hell hw is supposed to notice that messages are lost -
++    it does NOT clear bit 0x0001, and this bit will probably stay forever set
++    after we set it once. Let's hope this will be fixed in firmware someday
++*/
++
++static void
++handle_info_irq(acx_device_t *adev)
++{
++#if ACX_DEBUG
++      static const char * const info_type_msg[] = {
++              "(unknown)",
++              "scan complete",
++              "WEP key not found",
++              "internal watchdog reset was done",
++              "failed to send powersave (NULL frame) notification to AP",
++              "encrypt/decrypt on a packet has failed",
++              "TKIP tx keys disabled",
++              "TKIP rx keys disabled",
++              "TKIP rx: key ID not found",
++              "???",
++              "???",
++              "???",
++              "???",
++              "???",
++              "???",
++              "???",
++              "TKIP IV value exceeds thresh"
++      };
++#endif
++      u32 info_type, info_status;
++
++      info_type = read_slavemem32 (adev, (u32) adev->info_area);
++
++      info_status = (info_type >> 16);
++      info_type = (u16)info_type;
++
++      /* inform fw that we have read this info message */
++      write_slavemem32(adev, (u32) adev->info_area, info_type | 0x00010000);
++      write_reg16(adev, IO_ACX_INT_TRIG, INT_TRIG_INFOACK);
++      write_flush(adev);
++
++      log(L_CTL, "info_type:%04X info_status:%04X\n",
++                      info_type, info_status);
++
++      log(L_IRQ, "got Info IRQ: status %04X type %04X: %s\n",
++              info_status, info_type,
++              info_type_msg[(info_type >= VEC_SIZE(info_type_msg)) ?
++                              0 : info_type]
++      );
++}
++
++
++static void
++log_unusual_irq(u16 irqtype) {
++      /*
++      if (!printk_ratelimit())
++              return;
++      */
++
++      printk("acx: got");
++      if (irqtype & HOST_INT_TX_XFER) {
++              printk(" Tx_Xfer");
++      }
++      if (irqtype & HOST_INT_RX_COMPLETE) {
++              printk(" Rx_Complete");
++      }
++      if (irqtype & HOST_INT_DTIM) {
++              printk(" DTIM");
++      }
++      if (irqtype & HOST_INT_BEACON) {
++              printk(" Beacon");
++      }
++      if (irqtype & HOST_INT_TIMER) {
++              log(L_IRQ, " Timer");
++      }
++      if (irqtype & HOST_INT_KEY_NOT_FOUND) {
++              printk(" Key_Not_Found");
++      }
++      if (irqtype & HOST_INT_IV_ICV_FAILURE) {
++              printk(" IV_ICV_Failure (crypto)");
++      }
++              /* HOST_INT_CMD_COMPLETE  */
++              /* HOST_INT_INFO          */
++      if (irqtype & HOST_INT_OVERFLOW) {
++              printk(" Overflow");
++      }
++      if (irqtype & HOST_INT_PROCESS_ERROR) {
++              printk(" Process_Error");
++      }
++              /* HOST_INT_SCAN_COMPLETE */
++      if (irqtype & HOST_INT_FCS_THRESHOLD) {
++              printk(" FCS_Threshold");
++      }
++      if (irqtype & HOST_INT_UNKNOWN) {
++              printk(" Unknown");
++      }
++      printk(" IRQ(s)\n");
++}
++
++
++static void
++update_link_quality_led(acx_device_t *adev)
++{
++      int qual;
++
++      qual = acx_signal_determine_quality(adev->wstats.qual.level, adev->wstats.qual.noise);
++      if (qual > adev->brange_max_quality)
++              qual = adev->brange_max_quality;
++
++      if (time_after(jiffies, adev->brange_time_last_state_change +
++                              (HZ/2 - HZ/2 * (unsigned long)qual / adev->brange_max_quality ) )) {
++              acxmem_l_power_led(adev, (adev->brange_last_state == 0));
++              adev->brange_last_state ^= 1; /* toggle */
++              adev->brange_time_last_state_change = jiffies;
++      }
++}
++
++
++#define MAX_IRQLOOPS_PER_JIFFY  (20000/HZ) /* a la orinoco.c */
++
++static irqreturn_t
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
++acxmem_i_interrupt(int irq, void *dev_id)
++#else
++acxmwm_i_interrupt(int irq, void *dev_id, struct pt_regs *regs)
++#endif
++{
++      acx_device_t *adev;
++      unsigned long flags;
++      unsigned int irqcount = MAX_IRQLOOPS_PER_JIFFY;
++      register u16 irqtype;
++      u16 unmasked;
++
++      adev = ndev2adev((struct net_device*)dev_id);
++
++      /* LOCKING: can just spin_lock() since IRQs are disabled anyway.
++       * I am paranoid */
++      acx_lock(adev, flags);
++
++      unmasked = read_reg16(adev, IO_ACX_IRQ_STATUS_CLEAR);
++      if (unlikely(0xffff == unmasked)) {
++              /* 0xffff value hints at missing hardware,
++               * so don't do anything.
++               * Not very clean, but other drivers do the same... */
++              log(L_IRQ, "IRQ type:FFFF - device removed? IRQ_NONE\n");
++              goto none;
++      }
++
++      /* We will check only "interesting" IRQ types */
++      irqtype = unmasked & ~adev->irq_mask;
++      if (!irqtype) {
++              /* We are on a shared IRQ line and it wasn't our IRQ */
++              log(L_IRQ, "IRQ type:%04X, mask:%04X - all are masked, IRQ_NONE\n",
++                      unmasked, adev->irq_mask);
++              goto none;
++      }
++
++      /* Done here because IRQ_NONEs taking three lines of log
++      ** drive me crazy */
++      FN_ENTER;
++
++#define IRQ_ITERATE 1
++#if IRQ_ITERATE
++if (jiffies != adev->irq_last_jiffies) {
++      adev->irq_loops_this_jiffy = 0;
++      adev->irq_last_jiffies = jiffies;
++}
++
++/* safety condition; we'll normally abort loop below
++ * in case no IRQ type occurred */
++while (likely(--irqcount)) {
++#endif
++      /* ACK all IRQs ASAP */
++      write_reg16(adev, IO_ACX_IRQ_ACK, 0xffff);
++
++      log(L_IRQ, "IRQ type:%04X, mask:%04X, type & ~mask:%04X\n",
++                              unmasked, adev->irq_mask, irqtype);
++
++      /* Handle most important IRQ types first */
++      if (irqtype & HOST_INT_RX_DATA) {
++              log(L_IRQ, "got Rx_Data IRQ\n");
++              acxmem_l_process_rxdesc(adev);
++      }
++      if (irqtype & HOST_INT_TX_COMPLETE) {
++              log(L_IRQ, "got Tx_Complete IRQ\n");
++              /* don't clean up on each Tx complete, wait a bit
++               * unless we're going towards full, in which case
++               * we do it immediately, too (otherwise we might lockup
++               * with a full Tx buffer if we go into
++               * acxmem_l_clean_txdesc() at a time when we won't wakeup
++               * the net queue in there for some reason...) */
++              if (adev->tx_free <= TX_START_CLEAN) {
++#if TX_CLEANUP_IN_SOFTIRQ
++                      acx_schedule_task(adev, ACX_AFTER_IRQ_TX_CLEANUP);
++#else
++                      acxmem_l_clean_txdesc(adev);
++#endif
++              }
++      }
++
++      /* Less frequent ones */
++      if (irqtype & (0
++              | HOST_INT_CMD_COMPLETE
++              | HOST_INT_INFO
++              | HOST_INT_SCAN_COMPLETE
++      )) {
++              if (irqtype & HOST_INT_CMD_COMPLETE) {
++                      log(L_IRQ, "got Command_Complete IRQ\n");
++                      /* save the state for the running issue_cmd() */
++                      SET_BIT(adev->irq_status, HOST_INT_CMD_COMPLETE);
++              }
++              if (irqtype & HOST_INT_INFO) {
++                      handle_info_irq(adev);
++              }
++              if (irqtype & HOST_INT_SCAN_COMPLETE) {
++                      log(L_IRQ, "got Scan_Complete IRQ\n");
++                      /* need to do that in process context */
++                      acx_schedule_task(adev, ACX_AFTER_IRQ_COMPLETE_SCAN);
++                      /* remember that fw is not scanning anymore */
++                      SET_BIT(adev->irq_status, HOST_INT_SCAN_COMPLETE);
++              }
++      }
++
++      /* These we just log, but either they happen rarely
++       * or we keep them masked out */
++      if (irqtype & (0
++              /* | HOST_INT_RX_DATA */
++              /* | HOST_INT_TX_COMPLETE   */
++              | HOST_INT_TX_XFER
++              | HOST_INT_RX_COMPLETE
++              | HOST_INT_DTIM
++              | HOST_INT_BEACON
++              | HOST_INT_TIMER
++              | HOST_INT_KEY_NOT_FOUND
++              | HOST_INT_IV_ICV_FAILURE
++              /* | HOST_INT_CMD_COMPLETE  */
++              /* | HOST_INT_INFO          */
++              | HOST_INT_OVERFLOW
++              | HOST_INT_PROCESS_ERROR
++              /* | HOST_INT_SCAN_COMPLETE */
++              | HOST_INT_FCS_THRESHOLD
++              | HOST_INT_UNKNOWN
++      )) {
++              log_unusual_irq(irqtype);
++      }
++
++#if IRQ_ITERATE
++      unmasked = read_reg16(adev, IO_ACX_IRQ_STATUS_CLEAR);
++      irqtype = unmasked & ~adev->irq_mask;
++      /* Bail out if no new IRQ bits or if all are masked out */
++      if (!irqtype)
++              break;
++
++      if (unlikely(++adev->irq_loops_this_jiffy > MAX_IRQLOOPS_PER_JIFFY)) {
++              printk(KERN_ERR "acx: too many interrupts per jiffy!\n");
++              /* Looks like card floods us with IRQs! Try to stop that */
++              write_reg16(adev, IO_ACX_IRQ_MASK, 0xffff);
++              /* This will short-circuit all future attempts to handle IRQ.
++               * We cant do much more... */
++              adev->irq_mask = 0;
++              break;
++      }
++}
++#endif
++      /* Routine to perform blink with range */
++      if (unlikely(adev->led_power == 2))
++              update_link_quality_led(adev);
++
++/* handled: */
++      /* write_flush(adev); - not needed, last op was read anyway */
++      acx_unlock(adev, flags);
++      FN_EXIT0;
++      return IRQ_HANDLED;
++
++none:
++      acx_unlock(adev, flags);
++      return IRQ_NONE;
++}
++
++
++/***********************************************************************
++** acxmem_l_power_led
++*/
++void
++acxmem_l_power_led(acx_device_t *adev, int enable)
++{
++      u16 gpio_pled = IS_ACX111(adev) ? 0x0040 : 0x0800;
++
++      /* A hack. Not moving message rate limiting to adev->xxx
++       * (it's only a debug message after all) */
++      static int rate_limit = 0;
++
++      if (rate_limit++ < 3)
++              log(L_IOCTL, "Please report in case toggling the power "
++                              "LED doesn't work for your card!\n");
++      if (enable)
++              write_reg16(adev, IO_ACX_GPIO_OUT,
++                      read_reg16(adev, IO_ACX_GPIO_OUT) & ~gpio_pled);
++      else
++              write_reg16(adev, IO_ACX_GPIO_OUT,
++                      read_reg16(adev, IO_ACX_GPIO_OUT) | gpio_pled);
++}
++
++
++/***********************************************************************
++** Ioctls
++*/
++
++/***********************************************************************
++*/
++int
++acx111pci_ioctl_info(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      struct iw_param *vwrq,
++      char *extra)
++{
++#if ACX_DEBUG > 1
++      acx_device_t *adev = ndev2adev(ndev);
++      rxdesc_t *rxdesc;
++      txdesc_t *txdesc;
++      rxhostdesc_t *rxhostdesc;
++      txhostdesc_t *txhostdesc;
++      struct acx111_ie_memoryconfig memconf;
++      struct acx111_ie_queueconfig queueconf;
++      unsigned long flags;
++      int i;
++      char memmap[0x34];
++      char rxconfig[0x8];
++      char fcserror[0x8];
++      char ratefallback[0x5];
++
++      if ( !(acx_debug & (L_IOCTL|L_DEBUG)) )
++              return OK;
++      /* using printk() since we checked debug flag already */
++
++      acx_sem_lock(adev);
++
++      if (!IS_ACX111(adev)) {
++              printk("acx111-specific function called "
++                      "with non-acx111 chip, aborting\n");
++              goto end_ok;
++      }
++
++      /* get Acx111 Memory Configuration */
++      memset(&memconf, 0, sizeof(memconf));
++      /* BTW, fails with 12 (Write only) error code.
++      ** Retained for easy testing of issue_cmd error handling :) */
++      printk ("Interrogating queue config\n");
++      acx_s_interrogate(adev, &memconf, ACX1xx_IE_QUEUE_CONFIG);
++      printk ("done with queue config\n");
++
++      /* get Acx111 Queue Configuration */
++      memset(&queueconf, 0, sizeof(queueconf));
++      printk ("Interrogating mem config options\n");
++      acx_s_interrogate(adev, &queueconf, ACX1xx_IE_MEMORY_CONFIG_OPTIONS);
++      printk ("done with mem config options\n");
++
++      /* get Acx111 Memory Map */
++      memset(memmap, 0, sizeof(memmap));
++      printk ("Interrogating mem map\n");
++      acx_s_interrogate(adev, &memmap, ACX1xx_IE_MEMORY_MAP);
++      printk ("done with mem map\n");
++
++      /* get Acx111 Rx Config */
++      memset(rxconfig, 0, sizeof(rxconfig));
++      printk ("Interrogating rxconfig\n");
++      acx_s_interrogate(adev, &rxconfig, ACX1xx_IE_RXCONFIG);
++      printk ("done with queue rxconfig\n");
++
++      /* get Acx111 fcs error count */
++      memset(fcserror, 0, sizeof(fcserror));
++      printk ("Interrogating fcs err count\n");
++      acx_s_interrogate(adev, &fcserror, ACX1xx_IE_FCS_ERROR_COUNT);
++      printk ("done with err count\n");
++
++      /* get Acx111 rate fallback */
++      memset(ratefallback, 0, sizeof(ratefallback));
++      printk ("Interrogating rate fallback\n");
++      acx_s_interrogate(adev, &ratefallback, ACX1xx_IE_RATE_FALLBACK);
++      printk ("done with rate fallback\n");
++
++      /* force occurrence of a beacon interrupt */
++      /* TODO: comment why is this necessary */
++      write_reg16(adev, IO_ACX_HINT_TRIG, HOST_INT_BEACON);
++
++      /* dump Acx111 Mem Configuration */
++      printk("dump mem config:\n"
++              "data read: %d, struct size: %d\n"
++              "Number of stations: %1X\n"
++              "Memory block size: %1X\n"
++              "tx/rx memory block allocation: %1X\n"
++              "count rx: %X / tx: %X queues\n"
++              "options %1X\n"
++              "fragmentation %1X\n"
++              "Rx Queue 1 Count Descriptors: %X\n"
++              "Rx Queue 1 Host Memory Start: %X\n"
++              "Tx Queue 1 Count Descriptors: %X\n"
++              "Tx Queue 1 Attributes: %X\n",
++              memconf.len, (int) sizeof(memconf),
++              memconf.no_of_stations,
++              memconf.memory_block_size,
++              memconf.tx_rx_memory_block_allocation,
++              memconf.count_rx_queues, memconf.count_tx_queues,
++              memconf.options,
++              memconf.fragmentation,
++              memconf.rx_queue1_count_descs,
++      acx2cpu(memconf.rx_queue1_host_rx_start),
++              memconf.tx_queue1_count_descs,
++              memconf.tx_queue1_attributes);
++
++      /* dump Acx111 Queue Configuration */
++      printk("dump queue head:\n"
++              "data read: %d, struct size: %d\n"
++              "tx_memory_block_address (from card): %X\n"
++              "rx_memory_block_address (from card): %X\n"
++              "rx1_queue address (from card): %X\n"
++              "tx1_queue address (from card): %X\n"
++              "tx1_queue attributes (from card): %X\n",
++              queueconf.len, (int) sizeof(queueconf),
++              queueconf.tx_memory_block_address,
++              queueconf.rx_memory_block_address,
++              queueconf.rx1_queue_address,
++              queueconf.tx1_queue_address,
++              queueconf.tx1_attributes);
++
++      /* dump Acx111 Mem Map */
++      printk("dump mem map:\n"
++              "data read: %d, struct size: %d\n"
++              "Code start: %X\n"
++              "Code end: %X\n"
++              "WEP default key start: %X\n"
++              "WEP default key end: %X\n"
++              "STA table start: %X\n"
++              "STA table end: %X\n"
++              "Packet template start: %X\n"
++              "Packet template end: %X\n"
++              "Queue memory start: %X\n"
++              "Queue memory end: %X\n"
++              "Packet memory pool start: %X\n"
++              "Packet memory pool end: %X\n"
++              "iobase: %p\n"
++              "iobase2: %p\n",
++              *((u16 *)&memmap[0x02]), (int) sizeof(memmap),
++              *((u32 *)&memmap[0x04]),
++              *((u32 *)&memmap[0x08]),
++              *((u32 *)&memmap[0x0C]),
++              *((u32 *)&memmap[0x10]),
++              *((u32 *)&memmap[0x14]),
++              *((u32 *)&memmap[0x18]),
++              *((u32 *)&memmap[0x1C]),
++              *((u32 *)&memmap[0x20]),
++              *((u32 *)&memmap[0x24]),
++              *((u32 *)&memmap[0x28]),
++              *((u32 *)&memmap[0x2C]),
++              *((u32 *)&memmap[0x30]),
++              adev->iobase,
++              adev->iobase2);
++
++      /* dump Acx111 Rx Config */
++      printk("dump rx config:\n"
++              "data read: %d, struct size: %d\n"
++              "rx config: %X\n"
++              "rx filter config: %X\n",
++              *((u16 *)&rxconfig[0x02]), (int) sizeof(rxconfig),
++              *((u16 *)&rxconfig[0x04]),
++              *((u16 *)&rxconfig[0x06]));
++
++      /* dump Acx111 fcs error */
++      printk("dump fcserror:\n"
++              "data read: %d, struct size: %d\n"
++              "fcserrors: %X\n",
++              *((u16 *)&fcserror[0x02]), (int) sizeof(fcserror),
++              *((u32 *)&fcserror[0x04]));
++
++      /* dump Acx111 rate fallback */
++      printk("dump rate fallback:\n"
++              "data read: %d, struct size: %d\n"
++              "ratefallback: %X\n",
++              *((u16 *)&ratefallback[0x02]), (int) sizeof(ratefallback),
++              *((u8 *)&ratefallback[0x04]));
++
++      /* protect against IRQ */
++      acx_lock(adev, flags);
++
++      /* dump acx111 internal rx descriptor ring buffer */
++      rxdesc = adev->rxdesc_start;
++
++      /* loop over complete receive pool */
++      if (rxdesc) for (i = 0; i < RX_CNT; i++) {
++              printk("\ndump internal rxdesc %d:\n"
++                      "mem pos %p\n"
++                      "next 0x%X\n"
++                      "acx mem pointer (dynamic) 0x%X\n"
++                      "CTL (dynamic) 0x%X\n"
++                      "Rate (dynamic) 0x%X\n"
++                      "RxStatus (dynamic) 0x%X\n"
++                      "Mod/Pre (dynamic) 0x%X\n",
++                      i,
++                      rxdesc,
++                      acx2cpu(rxdesc->pNextDesc),
++                      acx2cpu(rxdesc->ACXMemPtr),
++                      rxdesc->Ctl_8,
++                      rxdesc->rate,
++                      rxdesc->error,
++                      rxdesc->SNR);
++              rxdesc++;
++      }
++
++      /* dump host rx descriptor ring buffer */
++
++      rxhostdesc = adev->rxhostdesc_start;
++
++      /* loop over complete receive pool */
++      if (rxhostdesc) for (i = 0; i < RX_CNT; i++) {
++              printk("\ndump host rxdesc %d:\n"
++                      "mem pos %p\n"
++                      "buffer mem pos 0x%X\n"
++                      "buffer mem offset 0x%X\n"
++                      "CTL 0x%X\n"
++                      "Length 0x%X\n"
++                      "next 0x%X\n"
++                      "Status 0x%X\n",
++                      i,
++                      rxhostdesc,
++                      acx2cpu(rxhostdesc->data_phy),
++                      rxhostdesc->data_offset,
++                      le16_to_cpu(rxhostdesc->Ctl_16),
++                      le16_to_cpu(rxhostdesc->length),
++                      acx2cpu(rxhostdesc->desc_phy_next),
++                      rxhostdesc->Status);
++              rxhostdesc++;
++      }
++
++      /* dump acx111 internal tx descriptor ring buffer */
++      txdesc = adev->txdesc_start;
++
++      /* loop over complete transmit pool */
++      if (txdesc) for (i = 0; i < TX_CNT; i++) {
++              printk("\ndump internal txdesc %d:\n"
++                      "size 0x%X\n"
++                      "mem pos %p\n"
++                      "next 0x%X\n"
++                      "acx mem pointer (dynamic) 0x%X\n"
++                      "host mem pointer (dynamic) 0x%X\n"
++                      "length (dynamic) 0x%X\n"
++                      "CTL (dynamic) 0x%X\n"
++                      "CTL2 (dynamic) 0x%X\n"
++                      "Status (dynamic) 0x%X\n"
++                      "Rate (dynamic) 0x%X\n",
++                      i,
++                      (int) sizeof(struct txdesc),
++                      txdesc,
++                      acx2cpu(txdesc->pNextDesc),
++                      acx2cpu(txdesc->AcxMemPtr),
++                      acx2cpu(txdesc->HostMemPtr),
++                      le16_to_cpu(txdesc->total_length),
++                      txdesc->Ctl_8,
++                      txdesc->Ctl2_8, txdesc->error,
++                      txdesc->u.r1.rate);
++              txdesc = advance_txdesc(adev, txdesc, 1);
++      }
++
++      /* dump host tx descriptor ring buffer */
++
++      txhostdesc = adev->txhostdesc_start;
++
++      /* loop over complete host send pool */
++      if (txhostdesc) for (i = 0; i < TX_CNT * 2; i++) {
++              printk("\ndump host txdesc %d:\n"
++                      "mem pos %p\n"
++                      "buffer mem pos 0x%X\n"
++                      "buffer mem offset 0x%X\n"
++                      "CTL 0x%X\n"
++                      "Length 0x%X\n"
++                      "next 0x%X\n"
++                      "Status 0x%X\n",
++                      i,
++                      txhostdesc,
++                      acx2cpu(txhostdesc->data_phy),
++                      txhostdesc->data_offset,
++                      le16_to_cpu(txhostdesc->Ctl_16),
++                      le16_to_cpu(txhostdesc->length),
++                      acx2cpu(txhostdesc->desc_phy_next),
++                      le32_to_cpu(txhostdesc->Status));
++              txhostdesc++;
++      }
++
++      /* write_reg16(adev, 0xb4, 0x4); */
++
++      acx_unlock(adev, flags);
++end_ok:
++
++      acx_sem_unlock(adev);
++#endif /* ACX_DEBUG */
++      return OK;
++}
++
++
++/***********************************************************************
++*/
++int
++acx100mem_ioctl_set_phy_amp_bias(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      struct iw_param *vwrq,
++      char *extra)
++{
++      acx_device_t *adev = ndev2adev(ndev);
++      unsigned long flags;
++      u16 gpio_old;
++
++      if (!IS_ACX100(adev)) {
++              /* WARNING!!!
++               * Removing this check *might* damage
++               * hardware, since we're tweaking GPIOs here after all!!!
++               * You've been warned...
++               * WARNING!!! */
++              printk("acx: sorry, setting bias level for non-acx100 "
++                      "is not supported yet\n");
++              return OK;
++      }
++
++      if (*extra > 7) {
++              printk("acx: invalid bias parameter, range is 0-7\n");
++              return -EINVAL;
++      }
++
++      acx_sem_lock(adev);
++
++      /* Need to lock accesses to [IO_ACX_GPIO_OUT]:
++       * IRQ handler uses it to update LED */
++      acx_lock(adev, flags);
++      gpio_old = read_reg16(adev, IO_ACX_GPIO_OUT);
++      write_reg16(adev, IO_ACX_GPIO_OUT, (gpio_old & 0xf8ff) | ((u16)*extra << 8));
++      acx_unlock(adev, flags);
++
++      log(L_DEBUG, "gpio_old: 0x%04X\n", gpio_old);
++      printk("%s: PHY power amplifier bias: old:%d, new:%d\n",
++              ndev->name,
++              (gpio_old & 0x0700) >> 8, (unsigned char)*extra);
++
++      acx_sem_unlock(adev);
++
++      return OK;
++}
++
++/***************************************************************
++** acxmem_l_alloc_tx
++** Actually returns a txdesc_t* ptr
++**
++** FIXME: in case of fragments, should allocate multiple descrs
++** after figuring out how many we need and whether we still have
++** sufficiently many.
++*/
++tx_t*
++acxmem_l_alloc_tx(acx_device_t *adev)
++{
++      struct txdesc *txdesc;
++      unsigned head;
++      u8 ctl8;
++      static int txattempts = 0;
++
++      FN_ENTER;
++
++      if (unlikely(!adev->tx_free)) {
++              printk("acx: BUG: no free txdesc left\n");
++              /*
++               * Probably the ACX ignored a transmit attempt and now there's a packet
++               * sitting in the queue we think should be transmitting but the ACX doesn't
++               * know about.
++               * On the first pass, send the ACX a TxProc interrupt to try moving
++               * things along, and if that doesn't work (ie, we get called again) completely
++               * flush the transmit queue.
++               */
++              if (txattempts < 10) {
++                txattempts++;
++                printk ("acx: trying to wake up ACX\n");
++                write_reg16(adev, IO_ACX_INT_TRIG, INT_TRIG_TXPRC);
++                write_flush(adev);            }
++              else  {
++                txattempts = 0;
++                printk ("acx: flushing transmit queue.\n");
++                acxmem_l_clean_txdesc_emergency (adev);
++              }
++              txdesc = NULL;
++              goto end;
++      }
++
++      /*
++       * Make a quick check to see if there is transmit buffer space on
++       * the ACX.  This can't guarantee there is enough space for the packet
++       * since we don't yet know how big it is, but it will prevent at least some
++       * annoyances.
++       */
++      if (!adev->acx_txbuf_blocks_free) {
++        txdesc = NULL;
++        goto end;
++      }
++
++      head = adev->tx_head;
++      /*
++       * txdesc points to ACX memory
++       */
++      txdesc = get_txdesc(adev, head);
++      ctl8 = read_slavemem8 (adev, (u32) &(txdesc->Ctl_8));
++
++      /* 
++       * If we don't own the buffer (HOSTOWN) it is certainly not free; however,
++       * we may have previously thought we had enough memory to send
++       * a packet, allocated the buffer then gave up when we found not enough
++       * transmit buffer space on the ACX. In that case, HOSTOWN and
++       * ACXDONE will both be set.
++       */
++      if (unlikely(DESC_CTL_HOSTOWN != (ctl8 & DESC_CTL_HOSTOWN))) {
++              /* whoops, descr at current index is not free, so probably
++               * ring buffer already full */
++                printk("acx: BUG: tx_head:%d Ctl8:0x%02X - failed to find "
++                        "free txdesc\n", head, ctl8);
++              txdesc = NULL;
++              goto end;
++      }
++
++      /* Needed in case txdesc won't be eventually submitted for tx */
++      write_slavemem8 (adev, (u32) &(txdesc->Ctl_8), DESC_CTL_ACXDONE_HOSTOWN);
++
++      adev->tx_free--;
++      log(L_BUFT, "tx: got desc %u, %u remain\n",
++                      head, adev->tx_free);
++      /* Keep a few free descs between head and tail of tx ring.
++      ** It is not absolutely needed, just feels safer */
++      if (adev->tx_free < TX_STOP_QUEUE) {
++              log(L_BUF, "stop queue (%u tx desc left)\n",
++                              adev->tx_free);
++              acx_stop_queue(adev->ndev, NULL);
++      }
++
++      /* returning current descriptor, so advance to next free one */
++      adev->tx_head = (head + 1) % TX_CNT;
++end:
++      FN_EXIT0;
++
++      return (tx_t*)txdesc;
++}
++
++
++/***************************************************************
++** acxmem_l_dealloc_tx
++** Clears out a previously allocatedvoid acxmem_l_dealloc_tx(tx_t *tx_opaque);
++ transmit descriptor.  The ACX
++** can get confused if we skip transmit descriptors in the queue,
++** so when we don't need a descriptor return it to its original
++** state and move the queue head pointer back.
++**
++*/
++void
++acxmem_l_dealloc_tx(acx_device_t *adev, tx_t *tx_opaque)
++{
++  /*
++   * txdesc is the address of the descriptor on the ACX.
++   */
++  txdesc_t *txdesc = (txdesc_t*)tx_opaque;
++  txdesc_t tmptxdesc;
++  int index;
++
++  memset (&tmptxdesc, 0, sizeof(tmptxdesc));
++  tmptxdesc.Ctl_8 = DESC_CTL_HOSTOWN | DESC_CTL_FIRSTFRAG;
++  tmptxdesc.u.r1.rate = 0x0a;
++
++  /*
++   * Clear out all of the transmit descriptor except for the next pointer
++   */
++  copy_to_slavemem (adev, (u32) &(txdesc->HostMemPtr),
++                  (u8 *) &(tmptxdesc.HostMemPtr),
++                  sizeof (tmptxdesc) - sizeof(tmptxdesc.pNextDesc));
++  
++  /*
++   * This is only called immediately after we've allocated, so we should
++   * be able to set the head back to this descriptor.
++   */
++  index = ((u8*) txdesc - (u8*)adev->txdesc_start) / adev->txdesc_size;
++  printk ("acx_dealloc: moving head from %d to %d\n", adev->tx_head, index);
++  adev->tx_head = index;
++}
++
++
++/***********************************************************************
++*/
++void*
++acxmem_l_get_txbuf(acx_device_t *adev, tx_t* tx_opaque)
++{
++      return get_txhostdesc(adev, (txdesc_t*)tx_opaque)->data;
++}
++
++
++/***********************************************************************
++** acxmem_l_tx_data
++**
++** Can be called from IRQ (rx -> (AP bridging or mgmt response) -> tx).
++** Can be called from acx_i_start_xmit (data frames from net core).
++**
++** FIXME: in case of fragments, should loop over the number of
++** pre-allocated tx descrs, properly setting up transfer data and
++** CTL_xxx flags according to fragment number.
++*/
++void
++acxmem_update_queue_indicator (acx_device_t *adev, int txqueue)
++{
++#ifdef USING_MORE_THAN_ONE_TRANSMIT_QUEUE
++  u32 indicator;
++  unsigned long flags;
++  int count;
++
++  /*
++   * Can't handle an interrupt while we're fiddling with the ACX's lock,
++   * according to TI.  The ACX is supposed to hold fw_lock for at most
++   * 500ns.
++   */
++  local_irq_save (flags);
++
++  /*
++   * Wait for ACX to release the lock (at most 500ns).
++   */
++  count = 0;
++  while (read_slavemem16 (adev, (u32) &(adev->acx_queue_indicator->fw_lock))
++       && (count++ < 50)) {
++    ndelay (10);
++  }
++  if (count < 50) {
++
++    /*
++     * Take out the host lock - anything non-zero will work, so don't worry about
++     * be/le
++     */
++    write_slavemem16 (adev, (u32) &(adev->acx_queue_indicator->host_lock), 1);
++
++    /*
++     * Avoid a race condition
++     */
++    count = 0;
++    while (read_slavemem16 (adev, (u32) &(adev->acx_queue_indicator->fw_lock))
++         && (count++ < 50)) {
++      ndelay (10);
++    }
++
++    if (count < 50) {
++      /*
++       * Mark the queue active
++       */
++      indicator = read_slavemem32 (adev, (u32) &(adev->acx_queue_indicator->indicator));
++      indicator |= cpu_to_le32 (1 << txqueue);
++      write_slavemem32 (adev, (u32) &(adev->acx_queue_indicator->indicator), indicator);
++    }
++
++    /*
++     * Release the host lock
++     */
++    write_slavemem16 (adev, (u32) &(adev->acx_queue_indicator->host_lock), 0);
++
++  }
++
++  /*
++   * Restore interrupts
++   */
++  local_irq_restore (flags);
++#endif
++}
++
++void
++acxmem_l_tx_data(acx_device_t *adev, tx_t* tx_opaque, int len)
++{
++  /*
++   * txdesc is the address on the ACX
++   */
++      txdesc_t *txdesc = (txdesc_t*)tx_opaque;
++      txhostdesc_t *hostdesc1, *hostdesc2;
++      client_t *clt;
++      u16 rate_cur;
++      u8 Ctl_8, Ctl2_8;
++      u32 addr;
++
++      FN_ENTER;
++      /* fw doesn't tx such packets anyhow */
++      if (unlikely(len < WLAN_HDR_A3_LEN))
++              goto end;
++
++      hostdesc1 = get_txhostdesc(adev, txdesc);
++      /* modify flag status in separate variable to be able to write it back
++       * in one big swoop later (also in order to have less device memory
++       * accesses) */
++      Ctl_8 = read_slavemem8 (adev, (u32) &(txdesc->Ctl_8));
++      Ctl2_8 = 0; /* really need to init it to 0, not txdesc->Ctl2_8, it seems */
++
++      hostdesc2 = hostdesc1 + 1;
++
++      /* DON'T simply set Ctl field to 0 here globally,
++       * it needs to maintain a consistent flag status (those are state flags!!),
++       * otherwise it may lead to severe disruption. Only set or reset particular
++       * flags at the exact moment this is needed... */
++
++      /* let chip do RTS/CTS handshaking before sending
++       * in case packet size exceeds threshold */
++      if (len > adev->rts_threshold)
++              SET_BIT(Ctl2_8, DESC_CTL2_RTS);
++      else
++              CLEAR_BIT(Ctl2_8, DESC_CTL2_RTS);
++
++      switch (adev->mode) {
++      case ACX_MODE_0_ADHOC:
++      case ACX_MODE_3_AP:
++              clt = acx_l_sta_list_get(adev, ((wlan_hdr_t*)hostdesc1->data)->a1);
++              break;
++      case ACX_MODE_2_STA:
++              clt = adev->ap_client;
++              break;
++#if 0
++/* testing was done on acx111: */
++      case ACX_MODE_MONITOR:
++              SET_BIT(Ctl2_8, 0
++/* sends CTS to self before packet */
++                      + DESC_CTL2_SEQ         /* don't increase sequence field */
++/* not working (looks like good fcs is still added) */
++                      + DESC_CTL2_FCS         /* don't add the FCS */
++/* not tested */
++                      + DESC_CTL2_MORE_FRAG
++/* not tested */
++                      + DESC_CTL2_RETRY       /* don't increase retry field */
++/* not tested */
++                      + DESC_CTL2_POWER       /* don't increase power mgmt. field */
++/* no effect */
++                      + DESC_CTL2_WEP         /* encrypt this frame */
++/* not tested */
++                      + DESC_CTL2_DUR         /* don't increase duration field */
++                      );
++              /* fallthrough */
++#endif
++      default: /* ACX_MODE_OFF, ACX_MODE_MONITOR */
++              clt = NULL;
++              break;
++      }
++
++      rate_cur = clt ? clt->rate_cur : adev->rate_bcast;
++      if (unlikely(!rate_cur)) {
++              printk("acx: driver bug! bad ratemask\n");
++              goto end;
++      }
++
++      /* used in tx cleanup routine for auto rate and accounting: */
++      put_txcr(adev, txdesc, clt, rate_cur);
++
++      write_slavemem16 (adev, (u32) &(txdesc->total_length), cpu_to_le16(len));
++      hostdesc2->length = cpu_to_le16(len - WLAN_HDR_A3_LEN);
++      if (IS_ACX111(adev)) {
++              /* note that if !txdesc->do_auto, txrate->cur
++              ** has only one nonzero bit */
++              txdesc->u.r2.rate111 = cpu_to_le16(
++                      rate_cur
++                      /* WARNING: I was never able to make it work with prism54 AP.
++                      ** It was falling down to 1Mbit where shortpre is not applicable,
++                      ** and not working at all at "5,11 basic rates only" setting.
++                      ** I even didn't see tx packets in radio packet capture.
++                      ** Disabled for now --vda */
++                      /*| ((clt->shortpre && clt->cur!=RATE111_1) ? RATE111_SHORTPRE : 0) */
++                      );
++#ifdef TODO_FIGURE_OUT_WHEN_TO_SET_THIS
++                      /* should add this to rate111 above as necessary */
++                      | (clt->pbcc511 ? RATE111_PBCC511 : 0)
++#endif
++              hostdesc1->length = cpu_to_le16(len);
++      } else { /* ACX100 */
++              u8 rate_100 = clt ? clt->rate_100 : adev->rate_bcast100;
++              write_slavemem8 (adev, (u32) &(txdesc->u.r1.rate), rate_100);
++#ifdef TODO_FIGURE_OUT_WHEN_TO_SET_THIS
++              if (clt->pbcc511) {
++                      if (n == RATE100_5 || n == RATE100_11)
++                              n |= RATE100_PBCC511;
++              }
++
++              if (clt->shortpre && (clt->cur != RATE111_1))
++                      SET_BIT(Ctl_8, DESC_CTL_SHORT_PREAMBLE); /* set Short Preamble */
++#endif
++              /* set autodma and reclaim and 1st mpdu */
++              SET_BIT(Ctl_8, DESC_CTL_FIRSTFRAG);
++
++#if ACX_FRAGMENTATION
++              /* SET_BIT(Ctl2_8, DESC_CTL2_MORE_FRAG); cannot set it unconditionally, needs to be set for all non-last fragments */
++#endif
++              hostdesc1->length = cpu_to_le16(WLAN_HDR_A3_LEN);
++
++              /*
++               * Since we're not using autodma copy the packet data to the acx now.
++               * Even host descriptors point to the packet header, and the odd indexed
++               * descriptor following points to the packet data.
++               *
++               * The first step is to find free memory in the ACX transmit buffers.
++               * They don't necessarily map one to one with the transmit queue entries,
++               * so search through them starting just after the last one used.
++               */
++              addr = allocate_acx_txbuf_space (adev, len);
++              if (addr) {
++                chaincopy_to_slavemem (adev, addr, hostdesc1->data, len);
++              }
++              else {
++                /*
++                 * Bummer.  We thought we might have enough room in the transmit
++                 * buffers to send this packet, but it turns out we don't.  alloc_tx
++                 * has already marked this transmit descriptor as HOSTOWN and ACXDONE,
++                 * which means the ACX will hang when it gets to this descriptor unless
++                 * we do something about it.  Having a bubble in the transmit queue just
++                 * doesn't seem to work, so we have to reset this transmit queue entry's
++                 * state to its original value and back up our head pointer to point
++                 * back to this entry.
++                 */
++                hostdesc1->length = 0;
++                hostdesc2->length = 0;
++                write_slavemem16 (adev, (u32) &(txdesc->total_length), 0);
++                write_slavemem8 (adev, (u32) &(txdesc->Ctl_8), DESC_CTL_HOSTOWN | DESC_CTL_FIRSTFRAG);
++                adev->tx_head  = ((u8*) txdesc - (u8*) adev->txdesc_start) / adev->txdesc_size;
++                goto end;
++              }
++              /*
++               * Tell the ACX where the packet is.
++               */
++              write_slavemem32 (adev, (u32) &(txdesc->AcxMemPtr), addr);
++
++      }
++      /* don't need to clean ack/rts statistics here, already
++       * done on descr cleanup */
++
++      /* clears HOSTOWN and ACXDONE bits, thus telling that the descriptors
++       * are now owned by the acx100; do this as LAST operation */
++      CLEAR_BIT(Ctl_8, DESC_CTL_ACXDONE_HOSTOWN);
++      /* flush writes before we release hostdesc to the adapter here */
++      //wmb();
++
++      /* write back modified flags */
++      /*
++       * At this point Ctl_8 should just be FIRSTFRAG
++       */
++      write_slavemem8 (adev, (u32) &(txdesc->Ctl2_8),Ctl2_8);
++      write_slavemem8 (adev, (u32) &(txdesc->Ctl_8), Ctl_8);
++      /* unused: txdesc->tx_time = cpu_to_le32(jiffies); */
++
++      /*
++       * Update the queue indicator to say there's data on the first queue.
++       */
++      acxmem_update_queue_indicator (adev, 0);
++
++      /* flush writes before we tell the adapter that it's its turn now */
++      mmiowb();
++      write_reg16(adev, IO_ACX_INT_TRIG, INT_TRIG_TXPRC);
++      write_flush(adev);
++
++      /* log the packet content AFTER sending it,
++       * in order to not delay sending any further than absolutely needed
++       * Do separate logs for acx100/111 to have human-readable rates */
++      if (unlikely(acx_debug & (L_XFER|L_DATA))) {
++              u16 fc = ((wlan_hdr_t*)hostdesc1->data)->fc;
++              if (IS_ACX111(adev))
++                      printk("tx: pkt (%s): len %d "
++                              "rate %04X%s status %u\n",
++                              acx_get_packet_type_string(le16_to_cpu(fc)), len,
++                              le16_to_cpu(txdesc->u.r2.rate111),
++                              (le16_to_cpu(txdesc->u.r2.rate111) & RATE111_SHORTPRE) ? "(SPr)" : "",
++                              adev->status);
++              else
++                      printk("tx: pkt (%s): len %d rate %03u%s status %u\n",
++                              acx_get_packet_type_string(fc), len,
++                              read_slavemem8 (adev, (u32) &(txdesc->u.r1.rate)),
++                              (Ctl_8 & DESC_CTL_SHORT_PREAMBLE) ? "(SPr)" : "",
++                              adev->status);
++
++              if (acx_debug & L_DATA) {
++                      printk("tx: 802.11 [%d]: ", len);
++                      acx_dump_bytes(hostdesc1->data, len);
++              }
++      }
++end:
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++** acxmem_l_clean_txdesc
++**
++** This function resets the txdescs' status when the ACX100
++** signals the TX done IRQ (txdescs have been processed), starting with
++** the pool index of the descriptor which we would use next,
++** in order to make sure that we can be as fast as possible
++** in filling new txdescs.
++** Everytime we get called we know where the next packet to be cleaned is.
++*/
++
++#if !ACX_DEBUG
++static inline void log_txbuffer(const acx_device_t *adev) {}
++#else
++static void
++log_txbuffer(acx_device_t *adev)
++{
++      txdesc_t *txdesc;
++      int i;
++      u8 Ctl_8;
++
++      /* no FN_ENTER here, we don't want that */
++      /* no locks here, since it's entirely non-critical code */
++      txdesc = adev->txdesc_start;
++      if (unlikely(!txdesc)) return;
++      printk("tx: desc->Ctl8's:");
++      for (i = 0; i < TX_CNT; i++) {
++        Ctl_8 = read_slavemem8 (adev, (u32) &(txdesc->Ctl_8));
++              printk(" %02X", Ctl_8);
++              txdesc = advance_txdesc(adev, txdesc, 1);
++      }
++      printk("\n");
++}
++#endif
++
++
++static void
++handle_tx_error(acx_device_t *adev, u8 error, unsigned int finger)
++{
++      const char *err = "unknown error";
++
++      /* hmm, should we handle this as a mask
++       * of *several* bits?
++       * For now I think only caring about
++       * individual bits is ok... */
++      switch (error) {
++      case 0x01:
++              err = "no Tx due to error in other fragment";
++              adev->wstats.discard.fragment++;
++              break;
++      case 0x02:
++              err = "Tx aborted";
++              adev->stats.tx_aborted_errors++;
++              break;
++      case 0x04:
++              err = "Tx desc wrong parameters";
++              adev->wstats.discard.misc++;
++              break;
++      case 0x08:
++              err = "WEP key not found";
++              adev->wstats.discard.misc++;
++              break;
++      case 0x10:
++              err = "MSDU lifetime timeout? - try changing "
++                              "'iwconfig retry lifetime XXX'";
++              adev->wstats.discard.misc++;
++              break;
++      case 0x20:
++              err = "excessive Tx retries due to either distance "
++                      "too high or unable to Tx or Tx frame error - "
++                      "try changing 'iwconfig txpower XXX' or "
++                      "'sens'itivity or 'retry'";
++              adev->wstats.discard.retries++;
++              /* Tx error 0x20 also seems to occur on
++               * overheating, so I'm not sure whether we
++               * actually want to do aggressive radio recalibration,
++               * since people maybe won't notice then that their hardware
++               * is slowly getting cooked...
++               * Or is it still a safe long distance from utter
++               * radio non-functionality despite many radio recalibs
++               * to final destructive overheating of the hardware?
++               * In this case we really should do recalib here...
++               * I guess the only way to find out is to do a
++               * potentially fatal self-experiment :-\
++               * Or maybe only recalib in case we're using Tx
++               * rate auto (on errors switching to lower speed
++               * --> less heat?) or 802.11 power save mode?
++               *
++               * ok, just do it. */
++              if (++adev->retry_errors_msg_ratelimit % 4 == 0) {
++                      if (adev->retry_errors_msg_ratelimit <= 20) {
++                              printk("%s: several excessive Tx "
++                                      "retry errors occurred, attempting "
++                                      "to recalibrate radio. Radio "
++                                      "drift might be caused by increasing "
++                                      "card temperature, please check the card "
++                                      "before it's too late!\n",
++                                      adev->ndev->name);
++                              if (adev->retry_errors_msg_ratelimit == 20)
++                                      printk("disabling above message\n");
++                      }
++
++                      acx_schedule_task(adev, ACX_AFTER_IRQ_CMD_RADIO_RECALIB);
++              }
++              break;
++      case 0x40:
++              err = "Tx buffer overflow";
++              adev->stats.tx_fifo_errors++;
++              break;
++      case 0x80:
++              err = "DMA error";
++              adev->wstats.discard.misc++;
++              break;
++      }
++      adev->stats.tx_errors++;
++      if (adev->stats.tx_errors <= 20)
++              printk("%s: tx error 0x%02X, buf %02u! (%s)\n",
++                              adev->ndev->name, error, finger, err);
++      else
++              printk("%s: tx error 0x%02X, buf %02u!\n",
++                              adev->ndev->name, error, finger);
++}
++
++
++unsigned int
++acxmem_l_clean_txdesc(acx_device_t *adev)
++{
++      txdesc_t *txdesc;
++      unsigned finger;
++      int num_cleaned;
++      u16 r111;
++      u8 error, ack_failures, rts_failures, rts_ok, r100, Ctl_8;
++      u32 acxmem;
++      txdesc_t tmptxdesc;
++
++      FN_ENTER;
++
++      /*
++       * Set up a template descriptor for re-initialization.  The only
++       * things that get set are Ctl_8 and the rate, and the rate defaults
++       * to 1Mbps.
++       */
++      memset (&tmptxdesc, 0, sizeof (tmptxdesc));
++      tmptxdesc.Ctl_8 = DESC_CTL_HOSTOWN | DESC_CTL_FIRSTFRAG;
++      tmptxdesc.u.r1.rate = 0x0a;
++
++      if (unlikely(acx_debug & L_DEBUG))
++              log_txbuffer(adev);
++
++      log(L_BUFT, "tx: cleaning up bufs from %u\n", adev->tx_tail);
++
++      /* We know first descr which is not free yet. We advance it as far
++      ** as we see correct bits set in following descs (if next desc
++      ** is NOT free, we shouldn't advance at all). We know that in
++      ** front of tx_tail may be "holes" with isolated free descs.
++      ** We will catch up when all intermediate descs will be freed also */
++
++      finger = adev->tx_tail;
++      num_cleaned = 0;
++      while (likely(finger != adev->tx_head)) {
++              txdesc = get_txdesc(adev, finger);
++
++              /* If we allocated txdesc on tx path but then decided
++              ** to NOT use it, then it will be left as a free "bubble"
++              ** in the "allocated for tx" part of the ring.
++              ** We may meet it on the next ring pass here. */
++
++              /* stop if not marked as "tx finished" and "host owned" */
++              Ctl_8 = read_slavemem8 (adev, (u32) &(txdesc->Ctl_8));
++              if ((Ctl_8 & DESC_CTL_ACXDONE_HOSTOWN)
++                                      != DESC_CTL_ACXDONE_HOSTOWN) {
++                      if (unlikely(!num_cleaned)) { /* maybe remove completely */
++                              log(L_BUFT, "clean_txdesc: tail isn't free. "
++                                      "tail:%d head:%d\n",
++                                      adev->tx_tail, adev->tx_head);
++                      }
++                      break;
++              }
++
++              /* remember desc values... */
++              error = read_slavemem8 (adev, (u32) &(txdesc->error));
++              ack_failures = read_slavemem8 (adev, (u32) &(txdesc->ack_failures));
++              rts_failures = read_slavemem8 (adev, (u32) &(txdesc->u.rts.rts_failures));
++              rts_ok = read_slavemem8 (adev, (u32) &(txdesc->u.rts.rts_ok));
++              r100 = read_slavemem8 (adev, (u32) &(txdesc->u.r1.rate));
++              r111 = le16_to_cpu(read_slavemem16 (adev, (u32) &(txdesc->u.r2.rate111)));
++
++              /* need to check for certain error conditions before we
++               * clean the descriptor: we still need valid descr data here */
++              if (unlikely(0x30 & error)) {
++                      /* only send IWEVTXDROP in case of retry or lifetime exceeded;
++                       * all other errors mean we screwed up locally */
++                      union iwreq_data wrqu;
++                      wlan_hdr_t *hdr;
++                      txhostdesc_t *hostdesc;
++
++                      hostdesc = get_txhostdesc(adev, txdesc);
++                      hdr = (wlan_hdr_t *)hostdesc->data;
++                      MAC_COPY(wrqu.addr.sa_data, hdr->a1);
++                      wireless_send_event(adev->ndev, IWEVTXDROP, &wrqu, NULL);
++              }
++
++              /*
++               * Free up the transmit data buffers
++               */
++              acxmem = read_slavemem32 (adev, (u32) &(txdesc->AcxMemPtr));
++              if (acxmem) {
++                reclaim_acx_txbuf_space (adev, acxmem);
++              }
++
++              /* ...and free the desc by clearing all the fields 
++                 except the next pointer */
++              copy_to_slavemem (adev,
++                                (u32) &(txdesc->HostMemPtr), 
++                                (u8 *) &(tmptxdesc.HostMemPtr),
++                                sizeof (tmptxdesc) - sizeof(tmptxdesc.pNextDesc)
++                                );
++
++              adev->tx_free++;
++              num_cleaned++;
++
++              if ((adev->tx_free >= TX_START_QUEUE)
++               && (adev->status == ACX_STATUS_4_ASSOCIATED)
++               && (acx_queue_stopped(adev->ndev))
++              ) {
++                      log(L_BUF, "tx: wake queue (avail. Tx desc %u)\n",
++                                      adev->tx_free);
++                      acx_wake_queue(adev->ndev, NULL);
++              }
++
++              /* do error checking, rate handling and logging
++               * AFTER having done the work, it's faster */
++
++              /* do rate handling */
++              if (adev->rate_auto) {
++                      struct client *clt = get_txc(adev, txdesc);
++                      if (clt) {
++                              u16 cur = get_txr(adev, txdesc);
++                              if (clt->rate_cur == cur) {
++                                      acx_l_handle_txrate_auto(adev, clt,
++                                              cur, /* intended rate */
++                                              r100, r111, /* actually used rate */
++                                              (error & 0x30), /* was there an error? */
++                                              TX_CNT + TX_CLEAN_BACKLOG - adev->tx_free);
++                              }
++                      }
++              }
++
++              if (unlikely(error))
++                      handle_tx_error(adev, error, finger);
++
++              if (IS_ACX111(adev))
++                      log(L_BUFT, "tx: cleaned %u: !ACK=%u !RTS=%u RTS=%u r111=%04X\n",
++                              finger, ack_failures, rts_failures, rts_ok, r111);
++              else
++                      log(L_BUFT, "tx: cleaned %u: !ACK=%u !RTS=%u RTS=%u rate=%u\n",
++                              finger, ack_failures, rts_failures, rts_ok, r100);
++
++              /* update pointer for descr to be cleaned next */
++              finger = (finger + 1) % TX_CNT;
++      }
++
++      /* remember last position */
++      adev->tx_tail = finger;
++/* end: */
++      FN_EXIT1(num_cleaned);
++      return num_cleaned;
++}
++
++/* clean *all* Tx descriptors, and regardless of their previous state.
++ * Used for brute-force reset handling. */
++void
++acxmem_l_clean_txdesc_emergency(acx_device_t *adev)
++{
++      txdesc_t *txdesc;
++      int i;
++      u32 acxmem;
++
++      FN_ENTER;
++
++      for (i = 0; i < TX_CNT; i++) {
++              txdesc = get_txdesc(adev, i);
++
++              /* free it */
++              write_slavemem8 (adev, (u32) &(txdesc->ack_failures), 0);
++              write_slavemem8 (adev, (u32) &(txdesc->u.rts.rts_failures), 0);
++              write_slavemem8 (adev, (u32) &(txdesc->u.rts.rts_ok), 0);
++              write_slavemem8 (adev, (u32) &(txdesc->error), 0);
++              write_slavemem8 (adev, (u32) &(txdesc->Ctl_8), DESC_CTL_HOSTOWN);
++
++              /*
++               * Clean up the memory allocated on the ACX for this transmit descriptor.
++               */
++              acxmem = read_slavemem32 (adev, (u32) &(txdesc->AcxMemPtr));
++              if (acxmem) {
++                reclaim_acx_txbuf_space (adev, acxmem);
++              }               
++              
++              write_slavemem32 (adev, (u32) &(txdesc->AcxMemPtr), 0);
++      }
++
++      adev->tx_free = TX_CNT;
++
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++** acxmem_s_create_tx_host_desc_queue
++*/
++
++static void*
++allocate(acx_device_t *adev, size_t size, dma_addr_t *phy, const char *msg)
++{
++      void *ptr;
++        ptr = kmalloc (size, GFP_KERNEL);
++      /*
++       * The ACX can't use the physical address, so we'll have to fake it
++       * later and it might be handy to have the virtual address.
++       */
++      *phy = (dma_addr_t) NULL;
++
++      if (ptr) {
++              log(L_DEBUG, "%s sz=%d adr=0x%p phy=0x%08llx\n",
++                              msg, (int)size, ptr, (unsigned long long)*phy);
++              memset(ptr, 0, size);
++              return ptr;
++      }
++      printk(KERN_ERR "acx: %s allocation FAILED (%d bytes)\n",
++                                      msg, (int)size);
++      return NULL;
++}
++
++
++/*
++ * In the generic slave memory access mode, most of the stuff in
++ * the txhostdesc_t is unused.  It's only here because the rest of
++ * the ACX driver expects it to be since the PCI version uses indirect
++ * host memory organization with DMA.  Since we're not using DMA the
++ * only use we have for the host descriptors is to store the packets
++ * on the way out.
++ */
++static int
++acxmem_s_create_tx_host_desc_queue(acx_device_t *adev)
++{
++      txhostdesc_t *hostdesc;
++      u8 *txbuf;
++      int i;
++
++      FN_ENTER;
++
++      /* allocate TX buffer */
++      adev->txbuf_area_size = TX_CNT * WLAN_A4FR_MAXLEN_WEP_FCS;
++
++      adev->txbuf_start = allocate(adev, adev->txbuf_area_size,
++                                   &adev->txbuf_startphy, "txbuf_start");
++      if (!adev->txbuf_start)
++        goto fail;
++
++      /* allocate the TX host descriptor queue pool */
++      adev->txhostdesc_area_size = TX_CNT * 2*sizeof(*hostdesc);
++
++      adev->txhostdesc_start = allocate(adev, adev->txhostdesc_area_size,
++                                        &adev->txhostdesc_startphy, "txhostdesc_start");
++      if (!adev->txhostdesc_start)
++        goto fail;
++
++      /* check for proper alignment of TX host descriptor pool */
++      if ((long) adev->txhostdesc_start & 3) {
++              printk("acx: driver bug: dma alloc returns unaligned address\n");
++              goto fail;
++      }
++
++      hostdesc = adev->txhostdesc_start;
++      txbuf = adev->txbuf_start;
++
++#if 0
++/* Each tx buffer is accessed by hardware via
++** txdesc -> txhostdesc(s) -> txbuffer(s).
++** We use only one txhostdesc per txdesc, but it looks like
++** acx111 is buggy: it accesses second txhostdesc
++** (via hostdesc.desc_phy_next field) even if
++** txdesc->length == hostdesc->length and thus
++** entire packet was placed into first txhostdesc.
++** Due to this bug acx111 hangs unless second txhostdesc
++** has le16_to_cpu(hostdesc.length) = 3 (or larger)
++** Storing NULL into hostdesc.desc_phy_next
++** doesn't seem to help.
++**
++** Update: although it worked on Xterasys XN-2522g
++** with len=3 trick, WG311v2 is even more bogus, doesn't work.
++** Keeping this code (#ifdef'ed out) for documentational purposes.
++*/
++      for (i = 0; i < TX_CNT*2; i++) {
++              hostdesc_phy += sizeof(*hostdesc);
++              if (!(i & 1)) {
++                      hostdesc->data_phy = cpu2acx(txbuf_phy);
++                      /* hostdesc->data_offset = ... */
++                      /* hostdesc->reserved = ... */
++                      hostdesc->Ctl_16 = cpu_to_le16(DESC_CTL_HOSTOWN);
++                      /* hostdesc->length = ... */
++                      hostdesc->desc_phy_next = cpu2acx(hostdesc_phy);
++                      hostdesc->pNext = ptr2acx(NULL);
++                      /* hostdesc->Status = ... */
++                      /* below: non-hardware fields */
++                      hostdesc->data = txbuf;
++
++                      txbuf += WLAN_A4FR_MAXLEN_WEP_FCS;
++                      txbuf_phy += WLAN_A4FR_MAXLEN_WEP_FCS;
++              } else {
++                      /* hostdesc->data_phy = ... */
++                      /* hostdesc->data_offset = ... */
++                      /* hostdesc->reserved = ... */
++                      /* hostdesc->Ctl_16 = ... */
++                      hostdesc->length = cpu_to_le16(3); /* bug workaround */
++                      /* hostdesc->desc_phy_next = ... */
++                      /* hostdesc->pNext = ... */
++                      /* hostdesc->Status = ... */
++                      /* below: non-hardware fields */
++                      /* hostdesc->data = ... */
++              }
++              hostdesc++;
++      }
++#endif
++/* We initialize two hostdescs so that they point to adjacent
++** memory areas. Thus txbuf is really just a contiguous memory area */
++      for (i = 0; i < TX_CNT*2; i++) {
++              /* ->data is a non-hardware field: */
++              hostdesc->data = txbuf;
++
++              if (!(i & 1)) {
++                      txbuf += WLAN_HDR_A3_LEN;
++              } else {
++                      txbuf += WLAN_A4FR_MAXLEN_WEP_FCS - WLAN_HDR_A3_LEN;
++              }
++              hostdesc++;
++      }
++      hostdesc--;
++
++      FN_EXIT1(OK);
++      return OK;
++fail:
++      printk("acx: create_tx_host_desc_queue FAILED\n");
++      /* dealloc will be done by free function on error case */
++      FN_EXIT1(NOT_OK);
++      return NOT_OK;
++}
++
++
++/***************************************************************
++** acxmem_s_create_rx_host_desc_queue
++*/
++/* the whole size of a data buffer (header plus data body)
++ * plus 32 bytes safety offset at the end */
++#define RX_BUFFER_SIZE (sizeof(rxbuffer_t) + 32)
++
++static int
++acxmem_s_create_rx_host_desc_queue(acx_device_t *adev)
++{
++      rxhostdesc_t *hostdesc;
++      rxbuffer_t *rxbuf;
++      int i;
++
++      FN_ENTER;
++
++      /* allocate the RX host descriptor queue pool */
++      adev->rxhostdesc_area_size = RX_CNT * sizeof(*hostdesc);
++
++      adev->rxhostdesc_start = allocate(adev, adev->rxhostdesc_area_size,
++                                        &adev->rxhostdesc_startphy, "rxhostdesc_start");
++      if (!adev->rxhostdesc_start)
++        goto fail;
++
++      /* check for proper alignment of RX host descriptor pool */
++      if ((long) adev->rxhostdesc_start & 3) {
++              printk("acx: driver bug: dma alloc returns unaligned address\n");
++              goto fail;
++      }
++
++      /* allocate Rx buffer pool which will be used by the acx
++       * to store the whole content of the received frames in it */
++      adev->rxbuf_area_size = RX_CNT * RX_BUFFER_SIZE;
++
++      adev->rxbuf_start = allocate(adev, adev->rxbuf_area_size,
++                                   &adev->rxbuf_startphy, "rxbuf_start");
++      if (!adev->rxbuf_start)
++        goto fail;
++
++      rxbuf = adev->rxbuf_start;
++      hostdesc = adev->rxhostdesc_start;
++
++      /* don't make any popular C programming pointer arithmetic mistakes
++       * here, otherwise I'll kill you...
++       * (and don't dare asking me why I'm warning you about that...) */
++      for (i = 0; i < RX_CNT; i++) {
++              hostdesc->data = rxbuf;
++              hostdesc->length = cpu_to_le16(RX_BUFFER_SIZE);
++              rxbuf++;
++              hostdesc++;
++      }
++      hostdesc--;
++      FN_EXIT1(OK);
++      return OK;
++fail:
++      printk("acx: create_rx_host_desc_queue FAILED\n");
++      /* dealloc will be done by free function on error case */
++      FN_EXIT1(NOT_OK);
++      return NOT_OK;
++}
++
++
++/***************************************************************
++** acxmem_s_create_hostdesc_queues
++*/
++int
++acxmem_s_create_hostdesc_queues(acx_device_t *adev)
++{
++      int result;
++      result = acxmem_s_create_tx_host_desc_queue(adev);
++      if (OK != result) return result;
++      result = acxmem_s_create_rx_host_desc_queue(adev);
++      return result;
++}
++
++
++/***************************************************************
++** acxmem_create_tx_desc_queue
++*/
++static void
++acxmem_create_tx_desc_queue(acx_device_t *adev, u32 tx_queue_start)
++{
++      txdesc_t *txdesc;
++      u32 clr;
++      int i;
++
++      FN_ENTER;
++
++      if (IS_ACX100(adev))
++              adev->txdesc_size = sizeof(*txdesc);
++      else
++              /* the acx111 txdesc is 4 bytes larger */
++              adev->txdesc_size = sizeof(*txdesc) + 4;
++
++      /*
++       * This refers to an ACX address, not one of ours
++       */
++      adev->txdesc_start = (txdesc_t *) tx_queue_start;
++
++      log(L_DEBUG, "adev->txdesc_start=%p\n",
++                      adev->txdesc_start);
++
++      adev->tx_free = TX_CNT;
++      /* done by memset: adev->tx_head = 0; */
++      /* done by memset: adev->tx_tail = 0; */
++      txdesc = adev->txdesc_start;
++
++      if (IS_ACX111(adev)) {
++              /* ACX111 has a preinitialized Tx buffer! */
++              /* loop over whole send pool */
++              /* FIXME: do we have to do the hostmemptr stuff here?? */
++              for (i = 0; i < TX_CNT; i++) {
++                      txdesc->Ctl_8 = DESC_CTL_HOSTOWN;
++                      /* reserve two (hdr desc and payload desc) */
++                      txdesc = advance_txdesc(adev, txdesc, 1);
++              }
++      } else {
++              /* ACX100 Tx buffer needs to be initialized by us */
++              /* clear whole send pool. sizeof is safe here (we are acx100) */
++
++              /*
++               * adev->txdesc_start refers to device memory, so we can't write
++               * directly to it.
++               */
++              clr = (u32) adev->txdesc_start;
++              while (clr < (u32) adev->txdesc_start + (TX_CNT * sizeof(*txdesc))) {
++                write_slavemem32 (adev, clr, 0);
++                clr += 4;
++              }
++
++              /* loop over whole send pool */
++              for (i = 0; i < TX_CNT; i++) {
++                      log(L_DEBUG, "configure card tx descriptor: 0x%p, "
++                              "size: 0x%X\n", txdesc, adev->txdesc_size);
++
++                      /* initialise ctl */
++                      /*
++                       * No auto DMA here
++                       */
++                      write_slavemem8 (adev, (u32) &(txdesc->Ctl_8),
++                                      (u8) (DESC_CTL_HOSTOWN | DESC_CTL_FIRSTFRAG));
++                      /* done by memset(0): txdesc->Ctl2_8 = 0; */
++
++                      /* point to next txdesc */
++                      write_slavemem32 (adev, (u32) &(txdesc->pNextDesc),
++                                        (u32) cpu_to_le32 ((u8 *) txdesc + adev->txdesc_size));
++
++                      /* go to the next one */
++                      /* ++ is safe here (we are acx100) */
++                      txdesc++;
++              }
++              /* go back to the last one */
++              txdesc--;
++              /* and point to the first making it a ring buffer */
++              write_slavemem32 (adev, (u32) &(txdesc->pNextDesc),
++                                (u32) cpu_to_le32 (tx_queue_start));
++      }
++      FN_EXIT0;
++}
++
++
++/***************************************************************
++** acxmem_create_rx_desc_queue
++*/
++static void
++acxmem_create_rx_desc_queue(acx_device_t *adev, u32 rx_queue_start)
++{
++      rxdesc_t *rxdesc;
++      u32 mem_offs;
++      int i;
++
++      FN_ENTER;
++
++      /* done by memset: adev->rx_tail = 0; */
++
++      /* ACX111 doesn't need any further config: preconfigures itself.
++       * Simply print ring buffer for debugging */
++      if (IS_ACX111(adev)) {
++              /* rxdesc_start already set here */
++
++              adev->rxdesc_start = (rxdesc_t *) rx_queue_start;
++
++              rxdesc = adev->rxdesc_start;
++              for (i = 0; i < RX_CNT; i++) {
++                      log(L_DEBUG, "rx descriptor %d @ 0x%p\n", i, rxdesc);
++                      rxdesc = adev->rxdesc_start = (rxdesc_t *)
++                        acx2cpu(rxdesc->pNextDesc);
++              }
++      } else {
++              /* we didn't pre-calculate rxdesc_start in case of ACX100 */
++              /* rxdesc_start should be right AFTER Tx pool */
++              adev->rxdesc_start = (rxdesc_t *)
++                      ((u8 *) adev->txdesc_start + (TX_CNT * sizeof(txdesc_t)));
++              /* NB: sizeof(txdesc_t) above is valid because we know
++              ** we are in if (acx100) block. Beware of cut-n-pasting elsewhere!
++              ** acx111's txdesc is larger! */
++
++              mem_offs = (u32) adev->rxdesc_start;
++              while (mem_offs < (u32) adev->rxdesc_start + (RX_CNT * sizeof (*rxdesc))) {
++                write_slavemem32 (adev, mem_offs, 0);
++                mem_offs += 4;
++              }
++
++              /* loop over whole receive pool */
++              rxdesc = adev->rxdesc_start;
++              for (i = 0; i < RX_CNT; i++) {
++                      log(L_DEBUG, "rx descriptor @ 0x%p\n", rxdesc);
++                      /* point to next rxdesc */
++                      write_slavemem32 (adev, (u32) &(rxdesc->pNextDesc),
++                                        (u32) cpu_to_le32 ((u8 *) rxdesc + sizeof(*rxdesc)));
++                      /* go to the next one */
++                      rxdesc++;
++              }
++              /* go to the last one */
++              rxdesc--;
++
++              /* and point to the first making it a ring buffer */
++              write_slavemem32 (adev, (u32) &(rxdesc->pNextDesc),
++                                (u32) cpu_to_le32 (rx_queue_start));
++      }
++      FN_EXIT0;
++}
++
++
++/***************************************************************
++** acxmem_create_desc_queues
++*/
++void
++acxmem_create_desc_queues(acx_device_t *adev, u32 tx_queue_start, u32 rx_queue_start)
++{
++  u32 *p;
++  int i;
++
++      acxmem_create_tx_desc_queue(adev, tx_queue_start);
++      acxmem_create_rx_desc_queue(adev, rx_queue_start);
++      p = (u32 *) adev->acx_queue_indicator;
++      for (i = 0; i < 4; i++) {
++        write_slavemem32 (adev, (u32) p, 0);
++        p++;
++      }
++}
++
++
++/***************************************************************
++** acxmem_s_proc_diag_output
++*/
++char*
++acxmem_s_proc_diag_output(char *p, acx_device_t *adev)
++{
++      const char *rtl, *thd, *ttl;
++      txdesc_t *txdesc;
++      u8 Ctl_8;
++      rxdesc_t *rxdesc;
++      int i;
++      u32 tmp;
++      txdesc_t txd;
++      u8 buf[0x200];
++      int j, k;
++
++      FN_ENTER;
++
++#if DUMP_MEM_DURING_DIAG > 0
++      dump_acxmem (adev, 0, 0x10000);
++      panic ("dump finished");
++#endif
++      
++      p += sprintf(p, "** Rx buf **\n");
++      rxdesc = adev->rxdesc_start;
++      if (rxdesc) for (i = 0; i < RX_CNT; i++) {
++              rtl = (i == adev->rx_tail) ? " [tail]" : "";
++              Ctl_8 = read_slavemem8 (adev, (u32) &(rxdesc->Ctl_8));
++              if (Ctl_8 & DESC_CTL_HOSTOWN)
++                      p += sprintf(p, "%02u (%02x) FULL%s\n", i, Ctl_8, rtl);
++              else
++                      p += sprintf(p, "%02u (%02x) empty%s\n", i, Ctl_8, rtl);
++              rxdesc++;
++      }
++      p += sprintf(p, "** Tx buf (free %d, Linux netqueue %s) **\n", adev->tx_free,
++                              acx_queue_stopped(adev->ndev) ? "STOPPED" : "running");
++      
++      p += sprintf(p, "** Tx buf %d blocks total, %d available, free list head %04x\n",
++                   adev->acx_txbuf_numblocks, adev->acx_txbuf_blocks_free, adev->acx_txbuf_free);
++      txdesc = adev->txdesc_start;
++      if (txdesc) {
++        for (i = 0; i < TX_CNT; i++) {
++          thd = (i == adev->tx_head) ? " [head]" : "";
++          ttl = (i == adev->tx_tail) ? " [tail]" : "";
++          copy_from_slavemem (adev, (u8 *) &txd, (u32) txdesc, sizeof (txd));
++          Ctl_8 = read_slavemem8 (adev, (u32) &(txdesc->Ctl_8));
++          if (Ctl_8 & DESC_CTL_ACXDONE)
++            p += sprintf(p, "%02u ready to free (%02X)%s%s", i, Ctl_8, thd, ttl);
++          else if (Ctl_8 & DESC_CTL_HOSTOWN)
++            p += sprintf(p, "%02u available     (%02X)%s%s", i, Ctl_8, thd, ttl);
++          else
++            p += sprintf(p, "%02u busy          (%02X)%s%s", i, Ctl_8, thd, ttl);
++          tmp = read_slavemem32 (adev, (u32) &(txdesc->AcxMemPtr));
++          if (tmp) {
++            p += sprintf (p, " %04x", tmp);
++            while ((tmp = read_slavemem32 (adev, (u32) tmp)) != 0x02000000) {
++              tmp <<= 5;
++              p += sprintf (p, " %04x", tmp);
++            }
++          }
++          p += sprintf (p, "\n");
++          p += sprintf (p, "  %04x: %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %02x %02x %02x %02x\n"
++                           "%02x %02x %02x %02x %04x\n",
++                        (u32) txdesc,
++                        txd.pNextDesc.v, txd.HostMemPtr.v, txd.AcxMemPtr.v, txd.tx_time,
++                        txd.total_length, txd.Reserved,
++                        txd.dummy[0], txd.dummy[1], txd.dummy[2], txd.dummy[3],
++                        txd.Ctl_8, txd.Ctl2_8, txd.error, txd.ack_failures,
++                        txd.u.rts.rts_failures, txd.u.rts.rts_ok, txd.u.r1.rate, txd.u.r1.queue_ctrl,
++                        txd.queue_info
++                        );
++          if (txd.AcxMemPtr.v) {
++            copy_from_slavemem (adev, buf, txd.AcxMemPtr.v, sizeof (buf));
++            for (j = 0; (j < txd.total_length) && (j<(sizeof(buf)-4)); j+=16) {
++              p += sprintf (p, "    ");
++              for (k = 0; (k < 16) && (j+k < txd.total_length); k++) {
++                p += sprintf (p, " %02x", buf[j+k+4]);
++              }
++              p += sprintf (p, "\n");
++            }
++          }
++          txdesc = advance_txdesc(adev, txdesc, 1);
++        }
++      }
++      
++      p += sprintf(p,
++              "\n"
++              "** Generic slave data **\n"
++                "irq_mask 0x%04x irq_status 0x%04x irq on acx 0x%04x\n"
++              "txbuf_start 0x%p, txbuf_area_size %u\n"
++              "txdesc_size %u, txdesc_start 0x%p\n"
++              "txhostdesc_start 0x%p, txhostdesc_area_size %u\n"
++              "txbuf start 0x%04x, txbuf size %d\n"
++              "rxdesc_start 0x%p\n"
++              "rxhostdesc_start 0x%p, rxhostdesc_area_size %u\n"
++              "rxbuf_start 0x%p, rxbuf_area_size %u\n",
++              adev->irq_mask, adev->irq_status, read_reg32(adev, IO_ACX_IRQ_STATUS_NON_DES),
++              adev->txbuf_start, adev->txbuf_area_size,
++              adev->txdesc_size, adev->txdesc_start,
++              adev->txhostdesc_start, adev->txhostdesc_area_size,
++                adev->acx_txbuf_start, adev->acx_txbuf_numblocks * adev->memblocksize,
++              adev->rxdesc_start,
++              adev->rxhostdesc_start, adev->rxhostdesc_area_size,
++              adev->rxbuf_start, adev->rxbuf_area_size);
++      FN_EXIT0;
++      return p;
++}
++
++
++/***********************************************************************
++*/
++int
++acxmem_proc_eeprom_output(char *buf, acx_device_t *adev)
++{
++      char *p = buf;
++      int i;
++
++      FN_ENTER;
++
++      for (i = 0; i < 0x400; i++) {
++              acxmem_read_eeprom_byte(adev, i, p++);
++      }
++
++      FN_EXIT1(p - buf);
++      return p - buf;
++}
++
++
++/***********************************************************************
++*/
++void
++acxmem_set_interrupt_mask(acx_device_t *adev)
++{
++      if (IS_ACX111(adev)) {
++              adev->irq_mask = (u16) ~(0
++                              | HOST_INT_RX_DATA       
++                              | HOST_INT_TX_COMPLETE
++                              /* | HOST_INT_TX_XFER        */
++                              /* | HOST_INT_RX_COMPLETE    */
++                              /* | HOST_INT_DTIM           */
++                              /* | HOST_INT_BEACON         */
++                              /* | HOST_INT_TIMER          */
++                              /* | HOST_INT_KEY_NOT_FOUND  */
++                              | HOST_INT_IV_ICV_FAILURE
++                              | HOST_INT_CMD_COMPLETE
++                              | HOST_INT_INFO
++                              | HOST_INT_OVERFLOW    
++                              /* | HOST_INT_PROCESS_ERROR  */
++                              | HOST_INT_SCAN_COMPLETE
++                              | HOST_INT_FCS_THRESHOLD
++                              | HOST_INT_UNKNOWN
++                              );
++              /* Or else acx100 won't signal cmd completion, right? */
++              adev->irq_mask_off = (u16)~( HOST_INT_CMD_COMPLETE ); /* 0xfdff */
++      } else {
++              adev->irq_mask = (u16) ~(0
++                              | HOST_INT_RX_DATA 
++                              | HOST_INT_TX_COMPLETE
++                              /* | HOST_INT_TX_XFER        */
++                              /* | HOST_INT_RX_COMPLETE    */
++                              /* | HOST_INT_DTIM           */
++                              /* | HOST_INT_BEACON         */
++                              /* | HOST_INT_TIMER          */
++                              /* | HOST_INT_KEY_NOT_FOUND  */
++                              /* | HOST_INT_IV_ICV_FAILURE */
++                              | HOST_INT_CMD_COMPLETE
++                              | HOST_INT_INFO
++                              /* | HOST_INT_OVERFLOW       */
++                              /* | HOST_INT_PROCESS_ERROR  */
++                              | HOST_INT_SCAN_COMPLETE
++                              /* | HOST_INT_FCS_THRESHOLD  */
++                              /* | HOST_INT_BEACON_MISSED        */
++                              );
++              adev->irq_mask_off = (u16)~( HOST_INT_UNKNOWN ); /* 0x7fff */
++      }
++}
++
++
++/***********************************************************************
++*/
++int
++acx100mem_s_set_tx_level(acx_device_t *adev, u8 level_dbm)
++{
++      struct acx111_ie_tx_level tx_level;
++
++      /* since it can be assumed that at least the Maxim radio has a
++       * maximum power output of 20dBm and since it also can be
++       * assumed that these values drive the DAC responsible for
++       * setting the linear Tx level, I'd guess that these values
++       * should be the corresponding linear values for a dBm value,
++       * in other words: calculate the values from that formula:
++       * Y [dBm] = 10 * log (X [mW])
++       * then scale the 0..63 value range onto the 1..100mW range (0..20 dBm)
++       * and you're done...
++       * Hopefully that's ok, but you never know if we're actually
++       * right... (especially since Windows XP doesn't seem to show
++       * actual Tx dBm values :-P) */
++
++      /* NOTE: on Maxim, value 30 IS 30mW, and value 10 IS 10mW - so the
++       * values are EXACTLY mW!!! Not sure about RFMD and others,
++       * though... */
++      static const u8 dbm2val_maxim[21] = {
++              63, 63, 63, 62,
++              61, 61, 60, 60,
++              59, 58, 57, 55,
++              53, 50, 47, 43,
++              38, 31, 23, 13,
++              0
++      };
++      static const u8 dbm2val_rfmd[21] = {
++               0,  0,  0,  1,
++               2,  2,  3,  3,
++               4,  5,  6,  8,
++              10, 13, 16, 20,
++              25, 32, 41, 50,
++              63
++      };
++      const u8 *table;
++
++      switch (adev->radio_type) {
++      case RADIO_MAXIM_0D:
++              table = &dbm2val_maxim[0];
++              break;
++      case RADIO_RFMD_11:
++      case RADIO_RALINK_15:
++              table = &dbm2val_rfmd[0];
++              break;
++      default:
++              printk("%s: unknown/unsupported radio type, "
++                      "cannot modify tx power level yet!\n",
++                              adev->ndev->name);
++              return NOT_OK;
++      }
++      /*
++       * The hx4700 EEPROM, at least, only supports 1 power setting.  The configure
++       * routine matches the PA bias with the gain, so just use its default value.
++       * The values are: 0x2b for the gain and 0x03 for the PA bias.  The firmware
++       * writes the gain level to the Tx gain control DAC and the PA bias to the Maxim
++       * radio's PA bias register.  The firmware limits itself to 0 - 64 when writing to the
++       * gain control DAC.
++       *
++       * Physically between the ACX and the radio, higher Tx gain control DAC values result
++       * in less power output; 0 volts to the Maxim radio results in the highest output power
++       * level, which I'm assuming matches up with 0 in the Tx Gain DAC register.
++       *
++       * Although there is only the 1 power setting, one of the radio firmware functions adjusts
++       * the transmit power level up and down.  That function is called by the ACX FIQ handler
++       * under certain conditions.
++       */
++      tx_level.level = 1;
++      //return acx_s_configure(adev, &tx_level, ACX1xx_IE_DOT11_TX_POWER_LEVEL);
++
++      printk("%s: changing radio power level to %u dBm (%u)\n",
++                      adev->ndev->name, level_dbm, table[level_dbm]);
++      acxmem_s_write_phy_reg(adev, 0x11, table[level_dbm]);
++
++      return 0;
++}
++
++
++static struct platform_driver
++acxmem_drv_id = {
++      .driver      = {
++              .name = "acx-mem",
++      },
++      .probe       = acxmem_e_probe,
++      .remove      = __devexit_p(acxmem_e_remove),
++#ifdef CONFIG_PM
++      .suspend     = acxmem_e_suspend,
++      .resume      = acxmem_e_resume
++#endif /* CONFIG_PM */
++};
++
++
++/***********************************************************************
++** acxmem_e_init_module
++**
++** Module initialization routine, called once at module load time
++*/
++int __init
++acxmem_e_init_module(void)
++{
++      int res;
++
++      FN_ENTER;
++
++#if (ACX_IO_WIDTH==32)
++      printk("acx: compiled to use 32bit I/O access. "
++              "I/O timing issues might occur, such as "
++              "non-working firmware upload. Report them\n");
++#else
++      printk("acx: compiled to use 16bit I/O access only "
++              "(compatibility mode)\n");
++#endif
++
++#ifdef __LITTLE_ENDIAN
++#define ENDIANNESS_STRING "running on a little-endian CPU\n"
++#else
++#define ENDIANNESS_STRING "running on a BIG-ENDIAN CPU\n"
++#endif
++      log(L_INIT,
++              ENDIANNESS_STRING
++              "PCI module " ACX_RELEASE " initialized, "
++              "waiting for cards to probe...\n"
++      );
++
++      res = platform_driver_register (&acxmem_drv_id);
++      FN_EXIT1(res);
++      return res;
++}
++
++
++/***********************************************************************
++** acxmem_e_cleanup_module
++**
++** Called at module unload time. This is our last chance to
++** clean up after ourselves.
++*/
++void __exit
++acxmem_e_cleanup_module(void)
++{
++      FN_ENTER;
++
++      printk ("cleanup_module\n");
++      platform_driver_unregister( &acxmem_drv_id );
++
++      FN_EXIT0;
++}
++
++void acxmem_e_release(struct device *dev) {
++}
++
++MODULE_AUTHOR( "Todd Blumer <todd@sdgsystems.com>" );
++MODULE_DESCRIPTION( "ACX Slave Memory Driver" );
++MODULE_LICENSE( "GPL" );
++
+Index: linux-2.6.22/drivers/net/wireless/acx/pci.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/drivers/net/wireless/acx/pci.c        2007-08-23 18:34:19.000000000 +0200
+@@ -0,0 +1,4234 @@
++/***********************************************************************
++** Copyright (C) 2003  ACX100 Open Source Project
++**
++** The contents of this file are subject to the Mozilla Public
++** License Version 1.1 (the "License"); you may not use this file
++** except in compliance with the License. You may obtain a copy of
++** the License at http://www.mozilla.org/MPL/
++**
++** Software distributed under the License is distributed on an "AS
++** IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
++** implied. See the License for the specific language governing
++** rights and limitations under the License.
++**
++** Alternatively, the contents of this file may be used under the
++** terms of the GNU Public License version 2 (the "GPL"), in which
++** case the provisions of the GPL are applicable instead of the
++** above.  If you wish to allow the use of your version of this file
++** only under the terms of the GPL and not to allow others to use
++** your version of this file under the MPL, indicate your decision
++** by deleting the provisions above and replace them with the notice
++** and other provisions required by the GPL.  If you do not delete
++** the provisions above, a recipient may use your version of this
++** file under either the MPL or the GPL.
++** ---------------------------------------------------------------------
++** Inquiries regarding the ACX100 Open Source Project can be
++** made directly to:
++**
++** acx100-users@lists.sf.net
++** http://acx100.sf.net
++** ---------------------------------------------------------------------
++*/
++#define ACX_PCI 1
++
++#include <linux/version.h>
++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18)
++#include <linux/config.h>
++#endif
++
++/* Linux 2.6.18+ uses <linux/utsrelease.h> */
++#ifndef UTS_RELEASE
++#include <linux/utsrelease.h>
++#endif
++
++#include <linux/compiler.h> /* required for Lx 2.6.8 ?? */
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/sched.h>
++#include <linux/types.h>
++#include <linux/skbuff.h>
++#include <linux/slab.h>
++#include <linux/if_arp.h>
++#include <linux/rtnetlink.h>
++#include <linux/wireless.h>
++#include <net/iw_handler.h>
++#include <linux/netdevice.h>
++#include <linux/ioport.h>
++#include <linux/pci.h>
++#include <linux/pm.h>
++#include <linux/vmalloc.h>
++#include <linux/dma-mapping.h>
++
++#include "acx.h"
++
++
++/***********************************************************************
++*/
++#define PCI_TYPE              (PCI_USES_MEM | PCI_ADDR0 | PCI_NO_ACPI_WAKE)
++#define PCI_ACX100_REGION1            0x01
++#define PCI_ACX100_REGION1_SIZE               0x1000  /* Memory size - 4K bytes */
++#define PCI_ACX100_REGION2            0x02
++#define PCI_ACX100_REGION2_SIZE               0x10000 /* Memory size - 64K bytes */
++
++#define PCI_ACX111_REGION1            0x00
++#define PCI_ACX111_REGION1_SIZE               0x2000  /* Memory size - 8K bytes */
++#define PCI_ACX111_REGION2            0x01
++#define PCI_ACX111_REGION2_SIZE               0x20000 /* Memory size - 128K bytes */
++
++/* Texas Instruments Vendor ID */
++#define PCI_VENDOR_ID_TI              0x104c
++
++/* ACX100 22Mb/s WLAN controller */
++#define PCI_DEVICE_ID_TI_TNETW1100A   0x8400
++#define PCI_DEVICE_ID_TI_TNETW1100B   0x8401
++
++/* ACX111 54Mb/s WLAN controller */
++#define PCI_DEVICE_ID_TI_TNETW1130    0x9066
++
++/* PCI Class & Sub-Class code, Network-'Other controller' */
++#define PCI_CLASS_NETWORK_OTHERS      0x0280
++
++#define CARD_EEPROM_ID_SIZE 6
++
++#ifndef PCI_D0
++/* From include/linux/pci.h */
++#define PCI_D0                0
++#define PCI_D1                1
++#define PCI_D2                2
++#define PCI_D3hot     3
++#define PCI_D3cold    4
++#define PCI_UNKNOWN   5
++#define PCI_POWER_ERROR       -1
++#endif
++
++
++/***********************************************************************
++*/
++static void acxpci_i_tx_timeout(struct net_device *ndev);
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
++static irqreturn_t acxpci_i_interrupt(int irq, void *dev_id);
++#else
++static irqreturn_t acxpci_i_interrupt(int irq, void *dev_id, struct pt_regs *regs);
++#endif
++static void acxpci_i_set_multicast_list(struct net_device *ndev);
++
++static int acxpci_e_open(struct net_device *ndev);
++static int acxpci_e_close(struct net_device *ndev);
++static void acxpci_s_up(struct net_device *ndev);
++static void acxpci_s_down(struct net_device *ndev);
++
++
++/***********************************************************************
++** Register access
++*/
++
++/* Pick one */
++/* #define INLINE_IO static */
++#define INLINE_IO static inline
++
++INLINE_IO u32
++read_reg32(acx_device_t *adev, unsigned int offset)
++{
++#if ACX_IO_WIDTH == 32
++      return readl((u8 *)adev->iobase + adev->io[offset]);
++#else
++      return readw((u8 *)adev->iobase + adev->io[offset])
++          + (readw((u8 *)adev->iobase + adev->io[offset] + 2) << 16);
++#endif
++}
++
++INLINE_IO u16
++read_reg16(acx_device_t *adev, unsigned int offset)
++{
++      return readw((u8 *)adev->iobase + adev->io[offset]);
++}
++
++INLINE_IO u8
++read_reg8(acx_device_t *adev, unsigned int offset)
++{
++      return readb((u8 *)adev->iobase + adev->io[offset]);
++}
++
++INLINE_IO void
++write_reg32(acx_device_t *adev, unsigned int offset, u32 val)
++{
++#if ACX_IO_WIDTH == 32
++      writel(val, (u8 *)adev->iobase + adev->io[offset]);
++#else
++      writew(val & 0xffff, (u8 *)adev->iobase + adev->io[offset]);
++      writew(val >> 16, (u8 *)adev->iobase + adev->io[offset] + 2);
++#endif
++}
++
++INLINE_IO void
++write_reg16(acx_device_t *adev, unsigned int offset, u16 val)
++{
++      writew(val, (u8 *)adev->iobase + adev->io[offset]);
++}
++
++INLINE_IO void
++write_reg8(acx_device_t *adev, unsigned int offset, u8 val)
++{
++      writeb(val, (u8 *)adev->iobase + adev->io[offset]);
++}
++
++/* Handle PCI posting properly:
++ * Make sure that writes reach the adapter in case they require to be executed
++ * *before* the next write, by reading a random (and safely accessible) register.
++ * This call has to be made if there is no read following (which would flush the data
++ * to the adapter), yet the written data has to reach the adapter immediately. */
++INLINE_IO void
++write_flush(acx_device_t *adev)
++{
++      /* readb(adev->iobase + adev->io[IO_ACX_INFO_MAILBOX_OFFS]); */
++      /* faster version (accesses the first register, IO_ACX_SOFT_RESET,
++       * which should also be safe): */
++      readb(adev->iobase);
++}
++
++INLINE_IO int
++adev_present(acx_device_t *adev)
++{
++      /* fast version (accesses the first register, IO_ACX_SOFT_RESET,
++       * which should be safe): */
++      return readl(adev->iobase) != 0xffffffff;
++}
++
++
++/***********************************************************************
++*/
++static inline txdesc_t*
++get_txdesc(acx_device_t *adev, int index)
++{
++      return (txdesc_t*) (((u8*)adev->txdesc_start) + index * adev->txdesc_size);
++}
++
++static inline txdesc_t*
++advance_txdesc(acx_device_t *adev, txdesc_t* txdesc, int inc)
++{
++      return (txdesc_t*) (((u8*)txdesc) + inc * adev->txdesc_size);
++}
++
++static txhostdesc_t*
++get_txhostdesc(acx_device_t *adev, txdesc_t* txdesc)
++{
++      int index = (u8*)txdesc - (u8*)adev->txdesc_start;
++      if (unlikely(ACX_DEBUG && (index % adev->txdesc_size))) {
++              printk("bad txdesc ptr %p\n", txdesc);
++              return NULL;
++      }
++      index /= adev->txdesc_size;
++      if (unlikely(ACX_DEBUG && (index >= TX_CNT))) {
++              printk("bad txdesc ptr %p\n", txdesc);
++              return NULL;
++      }
++      return &adev->txhostdesc_start[index*2];
++}
++
++static inline client_t*
++get_txc(acx_device_t *adev, txdesc_t* txdesc)
++{
++      int index = (u8*)txdesc - (u8*)adev->txdesc_start;
++      if (unlikely(ACX_DEBUG && (index % adev->txdesc_size))) {
++              printk("bad txdesc ptr %p\n", txdesc);
++              return NULL;
++      }
++      index /= adev->txdesc_size;
++      if (unlikely(ACX_DEBUG && (index >= TX_CNT))) {
++              printk("bad txdesc ptr %p\n", txdesc);
++              return NULL;
++      }
++      return adev->txc[index];
++}
++
++static inline u16
++get_txr(acx_device_t *adev, txdesc_t* txdesc)
++{
++      int index = (u8*)txdesc - (u8*)adev->txdesc_start;
++      index /= adev->txdesc_size;
++      return adev->txr[index];
++}
++
++static inline void
++put_txcr(acx_device_t *adev, txdesc_t* txdesc, client_t* c, u16 r111)
++{
++      int index = (u8*)txdesc - (u8*)adev->txdesc_start;
++      if (unlikely(ACX_DEBUG && (index % adev->txdesc_size))) {
++              printk("bad txdesc ptr %p\n", txdesc);
++              return;
++      }
++      index /= adev->txdesc_size;
++      if (unlikely(ACX_DEBUG && (index >= TX_CNT))) {
++              printk("bad txdesc ptr %p\n", txdesc);
++              return;
++      }
++      adev->txc[index] = c;
++      adev->txr[index] = r111;
++}
++
++
++/***********************************************************************
++** EEPROM and PHY read/write helpers
++*/
++/***********************************************************************
++** acxpci_read_eeprom_byte
++**
++** Function called to read an octet in the EEPROM.
++**
++** This function is used by acxpci_e_probe to check if the
++** connected card is a legal one or not.
++**
++** Arguments:
++**    adev            ptr to acx_device structure
++**    addr            address to read in the EEPROM
++**    charbuf         ptr to a char. This is where the read octet
++**                    will be stored
++*/
++int
++acxpci_read_eeprom_byte(acx_device_t *adev, u32 addr, u8 *charbuf)
++{
++      int result;
++      int count;
++
++      write_reg32(adev, IO_ACX_EEPROM_CFG, 0);
++      write_reg32(adev, IO_ACX_EEPROM_ADDR, addr);
++      write_flush(adev);
++      write_reg32(adev, IO_ACX_EEPROM_CTL, 2);
++
++      count = 0xffff;
++      while (read_reg16(adev, IO_ACX_EEPROM_CTL)) {
++              /* scheduling away instead of CPU burning loop
++               * doesn't seem to work here at all:
++               * awful delay, sometimes also failure.
++               * Doesn't matter anyway (only small delay). */
++              if (unlikely(!--count)) {
++                      printk("%s: timeout waiting for EEPROM read\n",
++                                                      adev->ndev->name);
++                      result = NOT_OK;
++                      goto fail;
++              }
++              cpu_relax();
++      }
++
++      *charbuf = read_reg8(adev, IO_ACX_EEPROM_DATA);
++      log(L_DEBUG, "EEPROM at 0x%04X = 0x%02X\n", addr, *charbuf);
++      result = OK;
++
++fail:
++      return result;
++}
++
++
++/***********************************************************************
++** We don't lock hw accesses here since we never r/w eeprom in IRQ
++** Note: this function sleeps only because of GFP_KERNEL alloc
++*/
++#ifdef UNUSED
++int
++acxpci_s_write_eeprom(acx_device_t *adev, u32 addr, u32 len, const u8 *charbuf)
++{
++      u8 *data_verify = NULL;
++      unsigned long flags;
++      int count, i;
++      int result = NOT_OK;
++      u16 gpio_orig;
++
++      printk("acx: WARNING! I would write to EEPROM now. "
++              "Since I really DON'T want to unless you know "
++              "what you're doing (THIS CODE WILL PROBABLY "
++              "NOT WORK YET!), I will abort that now. And "
++              "definitely make sure to make a "
++              "/proc/driver/acx_wlan0_eeprom backup copy first!!! "
++              "(the EEPROM content includes the PCI config header!! "
++              "If you kill important stuff, then you WILL "
++              "get in trouble and people DID get in trouble already)\n");
++      return OK;
++
++      FN_ENTER;
++
++      data_verify = kmalloc(len, GFP_KERNEL);
++      if (!data_verify) {
++              goto end;
++      }
++
++      /* first we need to enable the OE (EEPROM Output Enable) GPIO line
++       * to be able to write to the EEPROM.
++       * NOTE: an EEPROM writing success has been reported,
++       * but you probably have to modify GPIO_OUT, too,
++       * and you probably need to activate a different GPIO
++       * line instead! */
++      gpio_orig = read_reg16(adev, IO_ACX_GPIO_OE);
++      write_reg16(adev, IO_ACX_GPIO_OE, gpio_orig & ~1);
++      write_flush(adev);
++
++      /* ok, now start writing the data out */
++      for (i = 0; i < len; i++) {
++              write_reg32(adev, IO_ACX_EEPROM_CFG, 0);
++              write_reg32(adev, IO_ACX_EEPROM_ADDR, addr + i);
++              write_reg32(adev, IO_ACX_EEPROM_DATA, *(charbuf + i));
++              write_flush(adev);
++              write_reg32(adev, IO_ACX_EEPROM_CTL, 1);
++
++              count = 0xffff;
++              while (read_reg16(adev, IO_ACX_EEPROM_CTL)) {
++                      if (unlikely(!--count)) {
++                              printk("WARNING, DANGER!!! "
++                                      "Timeout waiting for EEPROM write\n");
++                              goto end;
++                      }
++                      cpu_relax();
++              }
++      }
++
++      /* disable EEPROM writing */
++      write_reg16(adev, IO_ACX_GPIO_OE, gpio_orig);
++      write_flush(adev);
++
++      /* now start a verification run */
++      for (i = 0; i < len; i++) {
++              write_reg32(adev, IO_ACX_EEPROM_CFG, 0);
++              write_reg32(adev, IO_ACX_EEPROM_ADDR, addr + i);
++              write_flush(adev);
++              write_reg32(adev, IO_ACX_EEPROM_CTL, 2);
++
++              count = 0xffff;
++              while (read_reg16(adev, IO_ACX_EEPROM_CTL)) {
++                      if (unlikely(!--count)) {
++                              printk("timeout waiting for EEPROM read\n");
++                              goto end;
++                      }
++                      cpu_relax();
++              }
++
++              data_verify[i] = read_reg16(adev, IO_ACX_EEPROM_DATA);
++      }
++
++      if (0 == memcmp(charbuf, data_verify, len))
++              result = OK; /* read data matches, success */
++
++end:
++      kfree(data_verify);
++      FN_EXIT1(result);
++      return result;
++}
++#endif /* UNUSED */
++
++
++/***********************************************************************
++** acxpci_s_read_phy_reg
++**
++** Messing with rx/tx disabling and enabling here
++** (write_reg32(adev, IO_ACX_ENABLE, 0b000000xx)) kills traffic
++*/
++int
++acxpci_s_read_phy_reg(acx_device_t *adev, u32 reg, u8 *charbuf)
++{
++      int result = NOT_OK;
++      int count;
++
++      FN_ENTER;
++
++      write_reg32(adev, IO_ACX_PHY_ADDR, reg);
++      write_flush(adev);
++      write_reg32(adev, IO_ACX_PHY_CTL, 2);
++
++      count = 0xffff;
++      while (read_reg32(adev, IO_ACX_PHY_CTL)) {
++              /* scheduling away instead of CPU burning loop
++               * doesn't seem to work here at all:
++               * awful delay, sometimes also failure.
++               * Doesn't matter anyway (only small delay). */
++              if (unlikely(!--count)) {
++                      printk("%s: timeout waiting for phy read\n",
++                                                      adev->ndev->name);
++                      *charbuf = 0;
++                      goto fail;
++              }
++              cpu_relax();
++      }
++
++      log(L_DEBUG, "count was %u\n", count);
++      *charbuf = read_reg8(adev, IO_ACX_PHY_DATA);
++
++      log(L_DEBUG, "radio PHY at 0x%04X = 0x%02X\n", *charbuf, reg);
++      result = OK;
++      goto fail; /* silence compiler warning */
++fail:
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/***********************************************************************
++*/
++int
++acxpci_s_write_phy_reg(acx_device_t *adev, u32 reg, u8 value)
++{
++      FN_ENTER;
++
++      /* mprusko said that 32bit accesses result in distorted sensitivity
++       * on his card. Unconfirmed, looks like it's not true (most likely since we
++       * now properly flush writes). */
++      write_reg32(adev, IO_ACX_PHY_DATA, value);
++      write_reg32(adev, IO_ACX_PHY_ADDR, reg);
++      write_flush(adev);
++      write_reg32(adev, IO_ACX_PHY_CTL, 1);
++      write_flush(adev);
++      log(L_DEBUG, "radio PHY write 0x%02X at 0x%04X\n", value, reg);
++
++      FN_EXIT1(OK);
++      return OK;
++}
++
++
++#define NO_AUTO_INCREMENT     1
++
++/***********************************************************************
++** acxpci_s_write_fw
++**
++** Write the firmware image into the card.
++**
++** Arguments:
++**    adev            wlan device structure
++**    fw_image        firmware image.
++**
++** Returns:
++**    1       firmware image corrupted
++**    0       success
++*/
++static int
++acxpci_s_write_fw(acx_device_t *adev, const firmware_image_t *fw_image, u32 offset)
++{
++      int len, size;
++      u32 sum, v32;
++      /* we skip the first four bytes which contain the control sum */
++      const u8 *p = (u8*)fw_image + 4;
++
++      /* start the image checksum by adding the image size value */
++      sum = p[0]+p[1]+p[2]+p[3];
++      p += 4;
++
++      write_reg32(adev, IO_ACX_SLV_END_CTL, 0);
++
++#if NO_AUTO_INCREMENT
++      write_reg32(adev, IO_ACX_SLV_MEM_CTL, 0); /* use basic mode */
++#else
++      write_reg32(adev, IO_ACX_SLV_MEM_CTL, 1); /* use autoincrement mode */
++      write_reg32(adev, IO_ACX_SLV_MEM_ADDR, offset); /* configure start address */
++      write_flush(adev);
++#endif
++
++      len = 0;
++      size = le32_to_cpu(fw_image->size) & (~3);
++
++      while (likely(len < size)) {
++              v32 = be32_to_cpu(*(u32*)p);
++              sum += p[0]+p[1]+p[2]+p[3];
++              p += 4;
++              len += 4;
++
++#if NO_AUTO_INCREMENT
++              write_reg32(adev, IO_ACX_SLV_MEM_ADDR, offset + len - 4);
++              write_flush(adev);
++#endif
++              write_reg32(adev, IO_ACX_SLV_MEM_DATA, v32);
++      }
++
++      log(L_DEBUG, "firmware written, size:%d sum1:%x sum2:%x\n",
++                      size, sum, le32_to_cpu(fw_image->chksum));
++
++      /* compare our checksum with the stored image checksum */
++      return (sum != le32_to_cpu(fw_image->chksum));
++}
++
++
++/***********************************************************************
++** acxpci_s_validate_fw
++**
++** Compare the firmware image given with
++** the firmware image written into the card.
++**
++** Arguments:
++**    adev            wlan device structure
++**   fw_image  firmware image.
++**
++** Returns:
++**    NOT_OK  firmware image corrupted or not correctly written
++**    OK      success
++*/
++static int
++acxpci_s_validate_fw(acx_device_t *adev, const firmware_image_t *fw_image,
++                              u32 offset)
++{
++      u32 sum, v32, w32;
++      int len, size;
++      int result = OK;
++      /* we skip the first four bytes which contain the control sum */
++      const u8 *p = (u8*)fw_image + 4;
++
++      /* start the image checksum by adding the image size value */
++      sum = p[0]+p[1]+p[2]+p[3];
++      p += 4;
++
++      write_reg32(adev, IO_ACX_SLV_END_CTL, 0);
++
++#if NO_AUTO_INCREMENT
++      write_reg32(adev, IO_ACX_SLV_MEM_CTL, 0); /* use basic mode */
++#else
++      write_reg32(adev, IO_ACX_SLV_MEM_CTL, 1); /* use autoincrement mode */
++      write_reg32(adev, IO_ACX_SLV_MEM_ADDR, offset); /* configure start address */
++#endif
++
++      len = 0;
++      size = le32_to_cpu(fw_image->size) & (~3);
++
++      while (likely(len < size)) {
++              v32 = be32_to_cpu(*(u32*)p);
++              p += 4;
++              len += 4;
++
++#if NO_AUTO_INCREMENT
++              write_reg32(adev, IO_ACX_SLV_MEM_ADDR, offset + len - 4);
++#endif
++              w32 = read_reg32(adev, IO_ACX_SLV_MEM_DATA);
++
++              if (unlikely(w32 != v32)) {
++                      printk("acx: FATAL: firmware upload: "
++                      "data parts at offset %d don't match (0x%08X vs. 0x%08X)! "
++                      "I/O timing issues or defective memory, with DWL-xx0+? "
++                      "ACX_IO_WIDTH=16 may help. Please report\n",
++                              len, v32, w32);
++                      result = NOT_OK;
++                      break;
++              }
++
++              sum += (u8)w32 + (u8)(w32>>8) + (u8)(w32>>16) + (u8)(w32>>24);
++      }
++
++      /* sum control verification */
++      if (result != NOT_OK) {
++              if (sum != le32_to_cpu(fw_image->chksum)) {
++                      printk("acx: FATAL: firmware upload: "
++                              "checksums don't match!\n");
++                      result = NOT_OK;
++              }
++      }
++
++      return result;
++}
++
++
++/***********************************************************************
++** acxpci_s_upload_fw
++**
++** Called from acx_reset_dev
++*/
++static int
++acxpci_s_upload_fw(acx_device_t *adev)
++{
++      firmware_image_t *fw_image = NULL;
++      int res = NOT_OK;
++      int try;
++      u32 file_size;
++      char filename[sizeof("tiacx1NNcNN")];
++
++      FN_ENTER;
++
++      /* print exact chipset and radio ID to make sure people really get a clue on which files exactly they are supposed to provide,
++       * since firmware loading is the biggest enduser PITA with these chipsets.
++       * Not printing radio ID in 0xHEX in order to not confuse them into wrong file naming */
++      printk( "acx: need to load firmware for acx1%02d chipset with radio ID %02x, please provide via firmware hotplug:\n"
++              "acx: either one file only (<c>ombined firmware image file, radio-specific) or two files (radio-less base image file *plus* separate <r>adio-specific extension file)\n",
++              IS_ACX111(adev)*11, adev->radio_type);
++
++      /* Try combined, then main image */
++      adev->need_radio_fw = 0;
++      snprintf(filename, sizeof(filename), "tiacx1%02dc%02X",
++              IS_ACX111(adev)*11, adev->radio_type);
++
++      fw_image = acx_s_read_fw(&adev->pdev->dev, filename, &file_size);
++      if (!fw_image) {
++              adev->need_radio_fw = 1;
++              filename[sizeof("tiacx1NN")-1] = '\0';
++              fw_image = acx_s_read_fw(&adev->pdev->dev, filename, &file_size);
++              if (!fw_image) {
++                      FN_EXIT1(NOT_OK);
++                      return NOT_OK;
++              }
++      }
++
++      for (try = 1; try <= 5; try++) {
++              res = acxpci_s_write_fw(adev, fw_image, 0);
++              log(L_DEBUG|L_INIT, "acx_write_fw (main/combined): %d\n", res);
++              if (OK == res) {
++                      res = acxpci_s_validate_fw(adev, fw_image, 0);
++                      log(L_DEBUG|L_INIT, "acx_validate_fw "
++                                      "(main/combined): %d\n", res);
++              }
++
++              if (OK == res) {
++                      SET_BIT(adev->dev_state_mask, ACX_STATE_FW_LOADED);
++                      break;
++              }
++              printk("acx: firmware upload attempt #%d FAILED, "
++                      "retrying...\n", try);
++              acx_s_msleep(1000); /* better wait for a while... */
++      }
++
++      vfree(fw_image);
++
++      FN_EXIT1(res);
++      return res;
++}
++
++
++/***********************************************************************
++** acxpci_s_upload_radio
++**
++** Uploads the appropriate radio module firmware into the card.
++*/
++int
++acxpci_s_upload_radio(acx_device_t *adev)
++{
++      acx_ie_memmap_t mm;
++      firmware_image_t *radio_image;
++      acx_cmd_radioinit_t radioinit;
++      int res = NOT_OK;
++      int try;
++      u32 offset;
++      u32 size;
++      char filename[sizeof("tiacx1NNrNN")];
++
++      if (!adev->need_radio_fw) return OK;
++
++      FN_ENTER;
++
++      acx_s_interrogate(adev, &mm, ACX1xx_IE_MEMORY_MAP);
++      offset = le32_to_cpu(mm.CodeEnd);
++
++      snprintf(filename, sizeof(filename), "tiacx1%02dr%02X",
++              IS_ACX111(adev)*11,
++              adev->radio_type);
++      radio_image = acx_s_read_fw(&adev->pdev->dev, filename, &size);
++      if (!radio_image) {
++              printk("acx: can't load radio module '%s'\n", filename);
++              goto fail;
++      }
++
++      acx_s_issue_cmd(adev, ACX1xx_CMD_SLEEP, NULL, 0);
++
++      for (try = 1; try <= 5; try++) {
++              res = acxpci_s_write_fw(adev, radio_image, offset);
++              log(L_DEBUG|L_INIT, "acx_write_fw (radio): %d\n", res);
++              if (OK == res) {
++                      res = acxpci_s_validate_fw(adev, radio_image, offset);
++                      log(L_DEBUG|L_INIT, "acx_validate_fw (radio): %d\n", res);
++              }
++
++              if (OK == res)
++                      break;
++              printk("acx: radio firmware upload attempt #%d FAILED, "
++                      "retrying...\n", try);
++              acx_s_msleep(1000); /* better wait for a while... */
++      }
++
++      acx_s_issue_cmd(adev, ACX1xx_CMD_WAKE, NULL, 0);
++      radioinit.offset = cpu_to_le32(offset);
++      /* no endian conversion needed, remains in card CPU area: */
++      radioinit.len = radio_image->size;
++
++      vfree(radio_image);
++
++      if (OK != res)
++              goto fail;
++
++      /* will take a moment so let's have a big timeout */
++      acx_s_issue_cmd_timeo(adev, ACX1xx_CMD_RADIOINIT,
++              &radioinit, sizeof(radioinit), CMD_TIMEOUT_MS(1000));
++
++      res = acx_s_interrogate(adev, &mm, ACX1xx_IE_MEMORY_MAP);
++fail:
++      FN_EXIT1(res);
++      return res;
++}
++
++
++/***********************************************************************
++** acxpci_l_reset_mac
++**
++** MAC will be reset
++** Call context: reset_dev
++*/
++static void
++acxpci_l_reset_mac(acx_device_t *adev)
++{
++      u16 temp;
++
++      FN_ENTER;
++
++      /* halt eCPU */
++      temp = read_reg16(adev, IO_ACX_ECPU_CTRL) | 0x1;
++      write_reg16(adev, IO_ACX_ECPU_CTRL, temp);
++
++      /* now do soft reset of eCPU, set bit */
++      temp = read_reg16(adev, IO_ACX_SOFT_RESET) | 0x1;
++      log(L_DEBUG, "%s: enable soft reset...\n", __func__);
++      write_reg16(adev, IO_ACX_SOFT_RESET, temp);
++      write_flush(adev);
++
++      /* now clear bit again: deassert eCPU reset */
++      log(L_DEBUG, "%s: disable soft reset and go to init mode...\n", __func__);
++      write_reg16(adev, IO_ACX_SOFT_RESET, temp & ~0x1);
++
++      /* now start a burst read from initial EEPROM */
++      temp = read_reg16(adev, IO_ACX_EE_START) | 0x1;
++      write_reg16(adev, IO_ACX_EE_START, temp);
++      write_flush(adev);
++
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++** acxpci_s_verify_init
++*/
++static int
++acxpci_s_verify_init(acx_device_t *adev)
++{
++      int result = NOT_OK;
++      unsigned long timeout;
++
++      FN_ENTER;
++
++      timeout = jiffies + 2*HZ;
++      for (;;) {
++              u16 irqstat = read_reg16(adev, IO_ACX_IRQ_STATUS_NON_DES);
++              if (irqstat & HOST_INT_FCS_THRESHOLD) {
++                      result = OK;
++                      write_reg16(adev, IO_ACX_IRQ_ACK, HOST_INT_FCS_THRESHOLD);
++                      break;
++              }
++              if (time_after(jiffies, timeout))
++                      break;
++              /* Init may take up to ~0.5 sec total */
++              acx_s_msleep(50);
++      }
++
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/***********************************************************************
++** A few low-level helpers
++**
++** Note: these functions are not protected by lock
++** and thus are never allowed to be called from IRQ.
++** Also they must not race with fw upload which uses same hw regs
++*/
++
++/***********************************************************************
++** acxpci_write_cmd_type_status
++*/
++
++static inline void
++acxpci_write_cmd_type_status(acx_device_t *adev, u16 type, u16 status)
++{
++      writel(type | (status << 16), adev->cmd_area);
++      write_flush(adev);
++}
++
++
++/***********************************************************************
++** acxpci_read_cmd_type_status
++*/
++static u32
++acxpci_read_cmd_type_status(acx_device_t *adev)
++{
++      u32 cmd_type, cmd_status;
++
++      cmd_type = readl(adev->cmd_area);
++      cmd_status = (cmd_type >> 16);
++      cmd_type = (u16)cmd_type;
++
++      log(L_CTL, "cmd_type:%04X cmd_status:%04X [%s]\n",
++              cmd_type, cmd_status,
++              acx_cmd_status_str(cmd_status));
++
++      return cmd_status;
++}
++
++
++/***********************************************************************
++** acxpci_s_reset_dev
++**
++** Arguments:
++**    netdevice that contains the adev variable
++** Returns:
++**    NOT_OK on fail
++**    OK on success
++** Side effects:
++**    device is hard reset
++** Call context:
++**    acxpci_e_probe
++** Comment:
++**    This resets the device using low level hardware calls
++**    as well as uploads and verifies the firmware to the card
++*/
++
++static inline void
++init_mboxes(acx_device_t *adev)
++{
++      u32 cmd_offs, info_offs;
++
++      cmd_offs = read_reg32(adev, IO_ACX_CMD_MAILBOX_OFFS);
++      info_offs = read_reg32(adev, IO_ACX_INFO_MAILBOX_OFFS);
++      adev->cmd_area = (u8 *)adev->iobase2 + cmd_offs;
++      adev->info_area = (u8 *)adev->iobase2 + info_offs;
++      log(L_DEBUG, "iobase2=%p\n"
++              "cmd_mbox_offset=%X cmd_area=%p\n"
++              "info_mbox_offset=%X info_area=%p\n",
++              adev->iobase2,
++              cmd_offs, adev->cmd_area,
++              info_offs, adev->info_area);
++}
++
++
++static inline void
++read_eeprom_area(acx_device_t *adev)
++{
++#if ACX_DEBUG > 1
++      int offs;
++      u8 tmp;
++
++      for (offs = 0x8c; offs < 0xb9; offs++)
++              acxpci_read_eeprom_byte(adev, offs, &tmp);
++#endif
++}
++
++
++static int
++acxpci_s_reset_dev(acx_device_t *adev)
++{
++      const char* msg = "";
++      unsigned long flags;
++      int result = NOT_OK;
++      u16 hardware_info;
++      u16 ecpu_ctrl;
++      int count;
++
++      FN_ENTER;
++
++      /* reset the device to make sure the eCPU is stopped
++       * to upload the firmware correctly */
++
++      acx_lock(adev, flags);
++
++      acxpci_l_reset_mac(adev);
++
++      ecpu_ctrl = read_reg16(adev, IO_ACX_ECPU_CTRL) & 1;
++      if (!ecpu_ctrl) {
++              msg = "eCPU is already running. ";
++              goto end_unlock;
++      }
++
++#ifdef WE_DONT_NEED_THAT_DO_WE
++      if (read_reg16(adev, IO_ACX_SOR_CFG) & 2) {
++              /* eCPU most likely means "embedded CPU" */
++              msg = "eCPU did not start after boot from flash. ";
++              goto end_unlock;
++      }
++
++      /* check sense on reset flags */
++      if (read_reg16(adev, IO_ACX_SOR_CFG) & 0x10) {
++              printk("%s: eCPU did not start after boot (SOR), "
++                      "is this fatal?\n", adev->ndev->name);
++      }
++#endif
++      /* scan, if any, is stopped now, setting corresponding IRQ bit */
++      adev->irq_status |= HOST_INT_SCAN_COMPLETE;
++
++      acx_unlock(adev, flags);
++
++      /* need to know radio type before fw load */
++      /* Need to wait for arrival of this information in a loop,
++       * most probably since eCPU runs some init code from EEPROM
++       * (started burst read in reset_mac()) which also
++       * sets the radio type ID */
++
++      count = 0xffff;
++      do {
++              hardware_info = read_reg16(adev, IO_ACX_EEPROM_INFORMATION);
++              if (!--count) {
++                      msg = "eCPU didn't indicate radio type";
++                      goto end_fail;
++              }
++              cpu_relax();
++      } while (!(hardware_info & 0xff00)); /* radio type still zero? */
++
++      /* printk("DEBUG: count %d\n", count); */
++      adev->form_factor = hardware_info & 0xff;
++      adev->radio_type = hardware_info >> 8;
++
++      /* load the firmware */
++      if (OK != acxpci_s_upload_fw(adev))
++              goto end_fail;
++
++      /* acx_s_msleep(10);    this one really shouldn't be required */
++
++      /* now start eCPU by clearing bit */
++      write_reg16(adev, IO_ACX_ECPU_CTRL, ecpu_ctrl & ~0x1);
++      log(L_DEBUG, "booted eCPU up and waiting for completion...\n");
++
++      /* wait for eCPU bootup */
++      if (OK != acxpci_s_verify_init(adev)) {
++              msg = "timeout waiting for eCPU. ";
++              goto end_fail;
++      }
++      log(L_DEBUG, "eCPU has woken up, card is ready to be configured\n");
++
++      init_mboxes(adev);
++      acxpci_write_cmd_type_status(adev, 0, 0);
++
++      /* test that EEPROM is readable */
++      read_eeprom_area(adev);
++
++      result = OK;
++      goto end;
++
++/* Finish error message. Indicate which function failed */
++end_unlock:
++      acx_unlock(adev, flags);
++end_fail:
++      printk("acx: %sreset_dev() FAILED\n", msg);
++end:
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/***********************************************************************
++** acxpci_s_issue_cmd_timeo
++**
++** Sends command to fw, extract result
++**
++** NB: we do _not_ take lock inside, so be sure to not touch anything
++** which may interfere with IRQ handler operation
++**
++** TODO: busy wait is a bit silly, so:
++** 1) stop doing many iters - go to sleep after first
++** 2) go to waitqueue based approach: wait, not poll!
++*/
++#undef FUNC
++#define FUNC "issue_cmd"
++
++#if !ACX_DEBUG
++int
++acxpci_s_issue_cmd_timeo(
++      acx_device_t *adev,
++      unsigned int cmd,
++      void *buffer,
++      unsigned buflen,
++      unsigned cmd_timeout)
++{
++#else
++int
++acxpci_s_issue_cmd_timeo_debug(
++      acx_device_t *adev,
++      unsigned cmd,
++      void *buffer,
++      unsigned buflen,
++      unsigned cmd_timeout,
++      const char* cmdstr)
++{
++      unsigned long start = jiffies;
++#endif
++      const char *devname;
++      unsigned counter;
++      u16 irqtype;
++      u16 cmd_status;
++      unsigned long timeout;
++
++      FN_ENTER;
++
++      devname = adev->ndev->name;
++      if (!devname || !devname[0] || devname[4]=='%')
++              devname = "acx";
++
++      log(L_CTL, FUNC"(cmd:%s,buflen:%u,timeout:%ums,type:0x%04X)\n",
++              cmdstr, buflen, cmd_timeout,
++              buffer ? le16_to_cpu(((acx_ie_generic_t *)buffer)->type) : -1);
++
++      if (!(adev->dev_state_mask & ACX_STATE_FW_LOADED)) {
++              printk("%s: "FUNC"(): firmware is not loaded yet, "
++                      "cannot execute commands!\n", devname);
++              goto bad;
++      }
++
++      if ((acx_debug & L_DEBUG) && (cmd != ACX1xx_CMD_INTERROGATE)) {
++              printk("input buffer (len=%u):\n", buflen);
++              acx_dump_bytes(buffer, buflen);
++      }
++
++      /* wait for firmware to become idle for our command submission */
++      timeout = HZ/5;
++      counter = (timeout * 1000 / HZ) - 1; /* in ms */
++      timeout += jiffies;
++      do {
++              cmd_status = acxpci_read_cmd_type_status(adev);
++              /* Test for IDLE state */
++              if (!cmd_status)
++                      break;
++              if (counter % 8 == 0) {
++                      if (time_after(jiffies, timeout)) {
++                              counter = 0;
++                              break;
++                      }
++                      /* we waited 8 iterations, no luck. Sleep 8 ms */
++                      acx_s_msleep(8);
++              }
++      } while (likely(--counter));
++
++      if (!counter) {
++              /* the card doesn't get idle, we're in trouble */
++              printk("%s: "FUNC"(): cmd_status is not IDLE: 0x%04X!=0\n",
++                      devname, cmd_status);
++              goto bad;
++      } else if (counter < 190) { /* if waited >10ms... */
++              log(L_CTL|L_DEBUG, FUNC"(): waited for IDLE %dms. "
++                      "Please report\n", 199 - counter);
++      }
++
++      /* now write the parameters of the command if needed */
++      if (buffer && buflen) {
++              /* if it's an INTERROGATE command, just pass the length
++               * of parameters to read, as data */
++#if CMD_DISCOVERY
++              if (cmd == ACX1xx_CMD_INTERROGATE)
++                      memset_io(adev->cmd_area + 4, 0xAA, buflen);
++#endif
++              /* adev->cmd_area points to PCI device's memory, not to RAM! */
++              memcpy_toio(adev->cmd_area + 4, buffer,
++                      (cmd == ACX1xx_CMD_INTERROGATE) ? 4 : buflen);
++      }
++      /* now write the actual command type */
++      acxpci_write_cmd_type_status(adev, cmd, 0);
++      /* execute command */
++      write_reg16(adev, IO_ACX_INT_TRIG, INT_TRIG_CMD);
++      write_flush(adev);
++
++      /* wait for firmware to process command */
++
++      /* Ensure nonzero and not too large timeout.
++      ** Also converts e.g. 100->99, 200->199
++      ** which is nice but not essential */
++      cmd_timeout = (cmd_timeout-1) | 1;
++      if (unlikely(cmd_timeout > 1199))
++              cmd_timeout = 1199;
++      /* clear CMD_COMPLETE bit. can be set only by IRQ handler: */
++      adev->irq_status &= ~HOST_INT_CMD_COMPLETE;
++
++      /* we schedule away sometimes (timeout can be large) */
++      counter = cmd_timeout;
++      timeout = jiffies + cmd_timeout * HZ / 1000;
++      do {
++              if (!adev->irqs_active) { /* IRQ disabled: poll */
++                      irqtype = read_reg16(adev, IO_ACX_IRQ_STATUS_NON_DES);
++                      if (irqtype & HOST_INT_CMD_COMPLETE) {
++                              write_reg16(adev, IO_ACX_IRQ_ACK,
++                                              HOST_INT_CMD_COMPLETE);
++                              break;
++                      }
++              } else { /* Wait when IRQ will set the bit */
++                      irqtype = adev->irq_status;
++                      if (irqtype & HOST_INT_CMD_COMPLETE)
++                              break;
++              }
++
++              if (counter % 8 == 0) {
++                      if (time_after(jiffies, timeout)) {
++                              counter = 0;
++                              break;
++                      }
++                      /* we waited 8 iterations, no luck. Sleep 8 ms */
++                      acx_s_msleep(8);
++              }
++      } while (likely(--counter));
++
++      /* save state for debugging */
++      cmd_status = acxpci_read_cmd_type_status(adev);
++
++      /* put the card in IDLE state */
++      acxpci_write_cmd_type_status(adev, 0, 0);
++
++      if (!counter) { /* timed out! */
++              printk("%s: "FUNC"(): timed out %s for CMD_COMPLETE. "
++                      "irq bits:0x%04X irq_status:0x%04X timeout:%dms "
++                      "cmd_status:%d (%s)\n",
++                      devname, (adev->irqs_active) ? "waiting" : "polling",
++                      irqtype, adev->irq_status, cmd_timeout,
++                      cmd_status, acx_cmd_status_str(cmd_status));
++              goto bad;
++      } else if (cmd_timeout - counter > 30) { /* if waited >30ms... */
++              log(L_CTL|L_DEBUG, FUNC"(): %s for CMD_COMPLETE %dms. "
++                      "count:%d. Please report\n",
++                      (adev->irqs_active) ? "waited" : "polled",
++                      cmd_timeout - counter, counter);
++      }
++
++      if (1 != cmd_status) { /* it is not a 'Success' */
++              printk("%s: "FUNC"(): cmd_status is not SUCCESS: %d (%s). "
++                      "Took %dms of %d\n",
++                      devname, cmd_status, acx_cmd_status_str(cmd_status),
++                      cmd_timeout - counter, cmd_timeout);
++              /* zero out result buffer
++               * WARNING: this will trash stack in case of illegally large input
++               * length! */
++              if (buffer && buflen)
++                      memset(buffer, 0, buflen);
++              goto bad;
++      }
++
++      /* read in result parameters if needed */
++      if (buffer && buflen && (cmd == ACX1xx_CMD_INTERROGATE)) {
++              /* adev->cmd_area points to PCI device's memory, not to RAM! */
++              memcpy_fromio(buffer, adev->cmd_area + 4, buflen);
++              if (acx_debug & L_DEBUG) {
++                      printk("output buffer (len=%u): ", buflen);
++                      acx_dump_bytes(buffer, buflen);
++              }
++      }
++/* ok: */
++      log(L_CTL, FUNC"(%s): took %ld jiffies to complete\n",
++                       cmdstr, jiffies - start);
++      FN_EXIT1(OK);
++      return OK;
++
++bad:
++      /* Give enough info so that callers can avoid
++      ** printing their own diagnostic messages */
++#if ACX_DEBUG
++      printk("%s: "FUNC"(cmd:%s) FAILED\n", devname, cmdstr);
++#else
++      printk("%s: "FUNC"(cmd:0x%04X) FAILED\n", devname, cmd);
++#endif
++      dump_stack();
++      FN_EXIT1(NOT_OK);
++      return NOT_OK;
++}
++
++
++/***********************************************************************
++*/
++#ifdef NONESSENTIAL_FEATURES
++typedef struct device_id {
++      unsigned char id[6];
++      char *descr;
++      char *type;
++} device_id_t;
++
++static const device_id_t
++device_ids[] =
++{
++      {
++              {'G', 'l', 'o', 'b', 'a', 'l'},
++              NULL,
++              NULL,
++      },
++      {
++              {0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
++              "uninitialized",
++              "SpeedStream SS1021 or Gigafast WF721-AEX"
++      },
++      {
++              {0x80, 0x81, 0x82, 0x83, 0x84, 0x85},
++              "non-standard",
++              "DrayTek Vigor 520"
++      },
++      {
++              {'?', '?', '?', '?', '?', '?'},
++              "non-standard",
++              "Level One WPC-0200"
++      },
++      {
++              {0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
++              "empty",
++              "DWL-650+ variant"
++      }
++};
++
++static void
++acx_show_card_eeprom_id(acx_device_t *adev)
++{
++      unsigned char buffer[CARD_EEPROM_ID_SIZE];
++      int i;
++
++      memset(&buffer, 0, CARD_EEPROM_ID_SIZE);
++      /* use direct EEPROM access */
++      for (i = 0; i < CARD_EEPROM_ID_SIZE; i++) {
++              if (OK != acxpci_read_eeprom_byte(adev,
++                                       ACX100_EEPROM_ID_OFFSET + i,
++                                       &buffer[i])) {
++                      printk("acx: reading EEPROM FAILED\n");
++                      break;
++              }
++      }
++
++      for (i = 0; i < VEC_SIZE(device_ids); i++) {
++              if (!memcmp(&buffer, device_ids[i].id, CARD_EEPROM_ID_SIZE)) {
++                      if (device_ids[i].descr) {
++                              printk("acx: EEPROM card ID string check "
++                                      "found %s card ID: is this %s?\n",
++                                      device_ids[i].descr, device_ids[i].type);
++                      }
++                      break;
++              }
++      }
++      if (i == VEC_SIZE(device_ids)) {
++              printk("acx: EEPROM card ID string check found "
++                      "unknown card: expected 'Global', got '%.*s\'. "
++                      "Please report\n", CARD_EEPROM_ID_SIZE, buffer);
++      }
++}
++#endif /* NONESSENTIAL_FEATURES */
++
++
++/***********************************************************************
++** acxpci_free_desc_queues
++**
++** Releases the queues that have been allocated, the
++** others have been initialised to NULL so this
++** function can be used if only part of the queues were allocated.
++*/
++
++static inline void
++free_coherent(struct pci_dev *hwdev, size_t size,
++                      void *vaddr, dma_addr_t dma_handle)
++{
++      dma_free_coherent(hwdev == NULL ? NULL : &hwdev->dev,
++                      size, vaddr, dma_handle);
++}
++
++void
++acxpci_free_desc_queues(acx_device_t *adev)
++{
++#define ACX_FREE_QUEUE(size, ptr, phyaddr) \
++      if (ptr) { \
++              free_coherent(0, size, ptr, phyaddr); \
++              ptr = NULL; \
++              size = 0; \
++      }
++
++      FN_ENTER;
++
++      ACX_FREE_QUEUE(adev->txhostdesc_area_size, adev->txhostdesc_start, adev->txhostdesc_startphy);
++      ACX_FREE_QUEUE(adev->txbuf_area_size, adev->txbuf_start, adev->txbuf_startphy);
++
++      adev->txdesc_start = NULL;
++
++      ACX_FREE_QUEUE(adev->rxhostdesc_area_size, adev->rxhostdesc_start, adev->rxhostdesc_startphy);
++      ACX_FREE_QUEUE(adev->rxbuf_area_size, adev->rxbuf_start, adev->rxbuf_startphy);
++
++      adev->rxdesc_start = NULL;
++
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++** acxpci_s_delete_dma_regions
++*/
++static void
++acxpci_s_delete_dma_regions(acx_device_t *adev)
++{
++      unsigned long flags;
++
++      FN_ENTER;
++      /* disable radio Tx/Rx. Shouldn't we use the firmware commands
++       * here instead? Or are we that much down the road that it's no
++       * longer possible here? */
++      write_reg16(adev, IO_ACX_ENABLE, 0);
++
++      acx_s_msleep(100);
++
++      acx_lock(adev, flags);
++      acxpci_free_desc_queues(adev);
++      acx_unlock(adev, flags);
++
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++** acxpci_e_probe
++**
++** Probe routine called when a PCI device w/ matching ID is found.
++** Here's the sequence:
++**   - Allocate the PCI resources.
++**   - Read the PCMCIA attribute memory to make sure we have a WLAN card
++**   - Reset the MAC
++**   - Initialize the dev and wlan data
++**   - Initialize the MAC
++**
++** pdev       - ptr to pci device structure containing info about pci configuration
++** id - ptr to the device id entry that matched this device
++*/
++static const u16
++IO_ACX100[] =
++{
++      0x0000, /* IO_ACX_SOFT_RESET */
++
++      0x0014, /* IO_ACX_SLV_MEM_ADDR */
++      0x0018, /* IO_ACX_SLV_MEM_DATA */
++      0x001c, /* IO_ACX_SLV_MEM_CTL */
++      0x0020, /* IO_ACX_SLV_END_CTL */
++
++      0x0034, /* IO_ACX_FEMR */
++
++      0x007c, /* IO_ACX_INT_TRIG */
++      0x0098, /* IO_ACX_IRQ_MASK */
++      0x00a4, /* IO_ACX_IRQ_STATUS_NON_DES */
++      0x00a8, /* IO_ACX_IRQ_STATUS_CLEAR */
++      0x00ac, /* IO_ACX_IRQ_ACK */
++      0x00b0, /* IO_ACX_HINT_TRIG */
++
++      0x0104, /* IO_ACX_ENABLE */
++
++      0x0250, /* IO_ACX_EEPROM_CTL */
++      0x0254, /* IO_ACX_EEPROM_ADDR */
++      0x0258, /* IO_ACX_EEPROM_DATA */
++      0x025c, /* IO_ACX_EEPROM_CFG */
++
++      0x0268, /* IO_ACX_PHY_ADDR */
++      0x026c, /* IO_ACX_PHY_DATA */
++      0x0270, /* IO_ACX_PHY_CTL */
++
++      0x0290, /* IO_ACX_GPIO_OE */
++
++      0x0298, /* IO_ACX_GPIO_OUT */
++
++      0x02a4, /* IO_ACX_CMD_MAILBOX_OFFS */
++      0x02a8, /* IO_ACX_INFO_MAILBOX_OFFS */
++      0x02ac, /* IO_ACX_EEPROM_INFORMATION */
++
++      0x02d0, /* IO_ACX_EE_START */
++      0x02d4, /* IO_ACX_SOR_CFG */
++      0x02d8 /* IO_ACX_ECPU_CTRL */
++};
++
++static const u16
++IO_ACX111[] =
++{
++      0x0000, /* IO_ACX_SOFT_RESET */
++
++      0x0014, /* IO_ACX_SLV_MEM_ADDR */
++      0x0018, /* IO_ACX_SLV_MEM_DATA */
++      0x001c, /* IO_ACX_SLV_MEM_CTL */
++      0x0020, /* IO_ACX_SLV_END_CTL */
++
++      0x0034, /* IO_ACX_FEMR */
++
++      0x00b4, /* IO_ACX_INT_TRIG */
++      0x00d4, /* IO_ACX_IRQ_MASK */
++      /* we do mean NON_DES (0xf0), not NON_DES_MASK which is at 0xe0: */
++      0x00f0, /* IO_ACX_IRQ_STATUS_NON_DES */
++      0x00e4, /* IO_ACX_IRQ_STATUS_CLEAR */
++      0x00e8, /* IO_ACX_IRQ_ACK */
++      0x00ec, /* IO_ACX_HINT_TRIG */
++
++      0x01d0, /* IO_ACX_ENABLE */
++
++      0x0338, /* IO_ACX_EEPROM_CTL */
++      0x033c, /* IO_ACX_EEPROM_ADDR */
++      0x0340, /* IO_ACX_EEPROM_DATA */
++      0x0344, /* IO_ACX_EEPROM_CFG */
++
++      0x0350, /* IO_ACX_PHY_ADDR */
++      0x0354, /* IO_ACX_PHY_DATA */
++      0x0358, /* IO_ACX_PHY_CTL */
++
++      0x0374, /* IO_ACX_GPIO_OE */
++
++      0x037c, /* IO_ACX_GPIO_OUT */
++
++      0x0388, /* IO_ACX_CMD_MAILBOX_OFFS */
++      0x038c, /* IO_ACX_INFO_MAILBOX_OFFS */
++      0x0390, /* IO_ACX_EEPROM_INFORMATION */
++
++      0x0100, /* IO_ACX_EE_START */
++      0x0104, /* IO_ACX_SOR_CFG */
++      0x0108, /* IO_ACX_ECPU_CTRL */
++};
++
++static void
++dummy_netdev_init(struct net_device *ndev) {}
++
++static int __devinit
++acxpci_e_probe(struct pci_dev *pdev, const struct pci_device_id *id)
++{
++      acx111_ie_configoption_t co;
++      unsigned long mem_region1 = 0;
++      unsigned long mem_region2 = 0;
++      unsigned long mem_region1_size;
++      unsigned long mem_region2_size;
++      unsigned long phymem1;
++      unsigned long phymem2;
++      void *mem1 = NULL;
++      void *mem2 = NULL;
++      acx_device_t *adev = NULL;
++      struct net_device *ndev = NULL;
++      const char *chip_name;
++      int result = -EIO;
++      int err;
++      u8 chip_type;
++
++      FN_ENTER;
++
++      /* Enable the PCI device */
++      if (pci_enable_device(pdev)) {
++              printk("acx: pci_enable_device() FAILED\n");
++              result = -ENODEV;
++              goto fail_pci_enable_device;
++      }
++
++      /* enable busmastering (required for CardBus) */
++      pci_set_master(pdev);
++
++      /* FIXME: prism54 calls pci_set_mwi() here,
++       * should we do/support the same? */
++
++      /* chiptype is u8 but id->driver_data is ulong
++      ** Works for now (possible values are 1 and 2) */
++      chip_type = (u8)id->driver_data;
++      /* acx100 and acx111 have different PCI memory regions */
++      if (chip_type == CHIPTYPE_ACX100) {
++              chip_name = "ACX100";
++              mem_region1 = PCI_ACX100_REGION1;
++              mem_region1_size  = PCI_ACX100_REGION1_SIZE;
++
++              mem_region2 = PCI_ACX100_REGION2;
++              mem_region2_size  = PCI_ACX100_REGION2_SIZE;
++      } else if (chip_type == CHIPTYPE_ACX111) {
++              chip_name = "ACX111";
++              mem_region1 = PCI_ACX111_REGION1;
++              mem_region1_size  = PCI_ACX111_REGION1_SIZE;
++
++              mem_region2 = PCI_ACX111_REGION2;
++              mem_region2_size  = PCI_ACX111_REGION2_SIZE;
++      } else {
++              printk("acx: unknown chip type 0x%04X\n", chip_type);
++              goto fail_unknown_chiptype;
++      }
++
++      /* Figure out our resources */
++      phymem1 = pci_resource_start(pdev, mem_region1);
++      phymem2 = pci_resource_start(pdev, mem_region2);
++      if (!request_mem_region(phymem1, pci_resource_len(pdev, mem_region1), "acx_1")) {
++              printk("acx: cannot reserve PCI memory region 1 (are you sure "
++                      "you have CardBus support in kernel?)\n");
++              goto fail_request_mem_region1;
++      }
++      if (!request_mem_region(phymem2, pci_resource_len(pdev, mem_region2), "acx_2")) {
++              printk("acx: cannot reserve PCI memory region 2\n");
++              goto fail_request_mem_region2;
++      }
++      
++      /* this used to be ioremap(), but ioremap_nocache()
++       * is much less risky, right? (and slower?)
++       * FIXME: we may want to go back to cached variant if it's
++       * certain that our code really properly handles
++       * cached operation (memory barriers, volatile?, ...)
++       * (but always keep this comment here regardless!)
++       * Possibly make this a driver config setting? */
++      
++      mem1 = ioremap_nocache(phymem1, mem_region1_size);
++      if (!mem1) {
++              printk("acx: ioremap() FAILED\n");
++              goto fail_ioremap1;
++      }
++      mem2 = ioremap_nocache(phymem2, mem_region2_size);
++      if (!mem2) {
++              printk("acx: ioremap() #2 FAILED\n");
++              goto fail_ioremap2;
++      }
++
++      printk("acx: found %s-based wireless network card at %s, irq:%d, "
++              "phymem1:0x%lX, phymem2:0x%lX, mem1:0x%p, mem1_size:%ld, "
++              "mem2:0x%p, mem2_size:%ld\n",
++              chip_name, pci_name(pdev), pdev->irq, phymem1, phymem2,
++              mem1, mem_region1_size,
++              mem2, mem_region2_size);
++      log(L_ANY, "initial debug setting is 0x%04X\n", acx_debug);
++
++      if (0 == pdev->irq) {
++              printk("acx: can't use IRQ 0\n");
++              goto fail_irq;
++      }
++
++      ndev = alloc_netdev(sizeof(*adev), "wlan%d", dummy_netdev_init);
++      /* (NB: memsets to 0 entire area) */
++      if (!ndev) {
++              printk("acx: no memory for netdevice struct\n");
++              goto fail_alloc_netdev;
++      }
++
++      ether_setup(ndev);
++      ndev->open = &acxpci_e_open;
++      ndev->stop = &acxpci_e_close;
++      ndev->hard_start_xmit = &acx_i_start_xmit;
++      ndev->get_stats = &acx_e_get_stats;
++#if IW_HANDLER_VERSION <= 5
++      ndev->get_wireless_stats = &acx_e_get_wireless_stats;
++#endif
++      ndev->wireless_handlers = (struct iw_handler_def *)&acx_ioctl_handler_def;
++      ndev->set_multicast_list = &acxpci_i_set_multicast_list;
++      ndev->tx_timeout = &acxpci_i_tx_timeout;
++      ndev->change_mtu = &acx_e_change_mtu;
++      ndev->watchdog_timeo = 4 * HZ;
++      ndev->irq = pdev->irq;
++      ndev->base_addr = pci_resource_start(pdev, 0);
++
++      adev = ndev2adev(ndev);
++      spin_lock_init(&adev->lock);    /* initial state: unlocked */
++      /* We do not start with downed sem: we want PARANOID_LOCKING to work */
++      sema_init(&adev->sem, 1);       /* initial state: 1 (upped) */
++      /* since nobody can see new netdev yet, we can as well
++      ** just _presume_ that we're under sem (instead of actually taking it): */
++      /* acx_sem_lock(adev); */
++      adev->pdev = pdev;
++      adev->ndev = ndev;
++      adev->dev_type = DEVTYPE_PCI;
++      adev->chip_type = chip_type;
++      adev->chip_name = chip_name;
++      adev->io = (CHIPTYPE_ACX100 == chip_type) ? IO_ACX100 : IO_ACX111;
++      adev->membase = phymem1;
++      adev->iobase = mem1;
++      adev->membase2 = phymem2;
++      adev->iobase2 = mem2;
++      /* to find crashes due to weird driver access
++       * to unconfigured interface (ifup) */
++      adev->mgmt_timer.function = (void (*)(unsigned long))0x0000dead;
++
++#ifdef NONESSENTIAL_FEATURES
++      acx_show_card_eeprom_id(adev);
++#endif /* NONESSENTIAL_FEATURES */
++
++#ifdef SET_MODULE_OWNER
++      SET_MODULE_OWNER(ndev);
++#endif
++      SET_NETDEV_DEV(ndev, &pdev->dev);
++
++      log(L_IRQ|L_INIT, "using IRQ %d\n", pdev->irq);
++
++      /* need to be able to restore PCI state after a suspend */
++      pci_save_state(pdev);
++      pci_set_drvdata(pdev, ndev);
++
++      /* ok, pci setup is finished, now start initializing the card */
++
++      /* NB: read_reg() reads may return bogus data before reset_dev(),
++       * since the firmware which directly controls large parts of the I/O
++       * registers isn't initialized yet.
++       * acx100 seems to be more affected than acx111 */
++      if (OK != acxpci_s_reset_dev(adev))
++              goto fail_reset;
++
++      if (IS_ACX100(adev)) {
++              /* ACX100: configopt struct in cmd mailbox - directly after reset */
++              memcpy_fromio(&co, adev->cmd_area, sizeof(co));
++      }
++
++      if (OK != acx_s_init_mac(adev))
++              goto fail_init_mac;
++
++      if (IS_ACX111(adev)) {
++              /* ACX111: configopt struct needs to be queried after full init */
++              acx_s_interrogate(adev, &co, ACX111_IE_CONFIG_OPTIONS);
++      }
++
++/* TODO: merge them into one function, they are called just once and are the same for pci & usb */
++      if (OK != acxpci_read_eeprom_byte(adev, 0x05, &adev->eeprom_version))
++              goto fail_read_eeprom_version;
++
++      acx_s_parse_configoption(adev, &co);
++      acx_s_set_defaults(adev);
++      acx_s_get_firmware_version(adev); /* needs to be after acx_s_init_mac() */
++      acx_display_hardware_details(adev);
++
++      /* Register the card, AFTER everything else has been set up,
++       * since otherwise an ioctl could step on our feet due to
++       * firmware operations happening in parallel or uninitialized data */
++      err = register_netdev(ndev);
++      if (OK != err) {
++              printk("acx: register_netdev() FAILED: %d\n", err);
++              goto fail_register_netdev;
++      }
++
++      acx_proc_register_entries(ndev);
++
++      /* Now we have our device, so make sure the kernel doesn't try
++       * to send packets even though we're not associated to a network yet */
++      acx_stop_queue(ndev, "on probe");
++      acx_carrier_off(ndev, "on probe");
++
++      /* after register_netdev() userspace may start working with dev
++       * (in particular, on other CPUs), we only need to up the sem */
++      /* acx_sem_unlock(adev); */
++
++      printk("acx "ACX_RELEASE": net device %s, driver compiled "
++              "against wireless extensions %d and Linux %s\n",
++              ndev->name, WIRELESS_EXT, UTS_RELEASE);
++
++#if CMD_DISCOVERY
++      great_inquisitor(adev);
++#endif
++
++      result = OK;
++      goto done;
++
++      /* error paths: undo everything in reverse order... */
++
++fail_register_netdev:
++
++      acxpci_s_delete_dma_regions(adev);
++      pci_set_drvdata(pdev, NULL);
++
++fail_init_mac:
++fail_read_eeprom_version:
++fail_reset:
++
++      free_netdev(ndev);
++fail_alloc_netdev:
++fail_irq:
++
++      iounmap(mem2);
++fail_ioremap2:
++
++      iounmap(mem1);
++fail_ioremap1:
++
++      release_mem_region(pci_resource_start(pdev, mem_region2),
++                         pci_resource_len(pdev, mem_region2));
++fail_request_mem_region2:
++
++      release_mem_region(pci_resource_start(pdev, mem_region1),
++                         pci_resource_len(pdev, mem_region1));
++fail_request_mem_region1:
++fail_unknown_chiptype:
++
++      pci_disable_device(pdev);
++fail_pci_enable_device:
++
++      pci_set_power_state(pdev, PCI_D3hot);
++
++done:
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/***********************************************************************
++** acxpci_e_remove
++**
++** Shut device down (if not hot unplugged)
++** and deallocate PCI resources for the acx chip.
++**
++** pdev - ptr to PCI device structure containing info about pci configuration
++*/
++static void __devexit
++acxpci_e_remove(struct pci_dev *pdev)
++{
++      struct net_device *ndev;
++      acx_device_t *adev;
++      unsigned long mem_region1, mem_region2;
++      unsigned long flags;
++
++      FN_ENTER;
++
++      ndev = (struct net_device*) pci_get_drvdata(pdev);
++      if (!ndev) {
++              log(L_DEBUG, "%s: card is unused. Skipping any release code\n",
++                      __func__);
++              goto end;
++      }
++
++      adev = ndev2adev(ndev);
++
++      /* If device wasn't hot unplugged... */
++      if (adev_present(adev)) {
++
++              acx_sem_lock(adev);
++
++              /* disable both Tx and Rx to shut radio down properly */
++              acx_s_issue_cmd(adev, ACX1xx_CMD_DISABLE_TX, NULL, 0);
++              acx_s_issue_cmd(adev, ACX1xx_CMD_DISABLE_RX, NULL, 0);
++
++#ifdef REDUNDANT
++              /* put the eCPU to sleep to save power
++               * Halting is not possible currently,
++               * since not supported by all firmware versions */
++              acx_s_issue_cmd(adev, ACX100_CMD_SLEEP, NULL, 0);
++#endif
++              acx_lock(adev, flags);
++              /* disable power LED to save power :-) */
++              log(L_INIT, "switching off power LED to save power\n");
++              acxpci_l_power_led(adev, 0);
++              /* stop our eCPU */
++              if (IS_ACX111(adev)) {
++                      /* FIXME: does this actually keep halting the eCPU?
++                       * I don't think so...
++                       */
++                      acxpci_l_reset_mac(adev);
++              } else {
++                      u16 temp;
++                      /* halt eCPU */
++                      temp = read_reg16(adev, IO_ACX_ECPU_CTRL) | 0x1;
++                      write_reg16(adev, IO_ACX_ECPU_CTRL, temp);
++                      write_flush(adev);
++              }
++              acx_unlock(adev, flags);
++
++              acx_sem_unlock(adev);
++      }
++
++      /* unregister the device to not let the kernel
++       * (e.g. ioctls) access a half-deconfigured device
++       * NB: this will cause acxpci_e_close() to be called,
++       * thus we shouldn't call it under sem! */
++      log(L_INIT, "removing device %s\n", ndev->name);
++      unregister_netdev(ndev);
++
++      /* unregister_netdev ensures that no references to us left.
++       * For paranoid reasons we continue to follow the rules */
++      acx_sem_lock(adev);
++
++      if (adev->dev_state_mask & ACX_STATE_IFACE_UP) {
++              acxpci_s_down(ndev);
++              CLEAR_BIT(adev->dev_state_mask, ACX_STATE_IFACE_UP);
++      }
++
++      acx_proc_unregister_entries(ndev);
++
++      if (IS_ACX100(adev)) {
++              mem_region1 = PCI_ACX100_REGION1;
++              mem_region2 = PCI_ACX100_REGION2;
++      } else {
++              mem_region1 = PCI_ACX111_REGION1;
++              mem_region2 = PCI_ACX111_REGION2;
++      }
++
++      /* finally, clean up PCI bus state */
++      acxpci_s_delete_dma_regions(adev);
++      if (adev->iobase) iounmap(adev->iobase);
++      if (adev->iobase2) iounmap(adev->iobase2);
++      release_mem_region(pci_resource_start(pdev, mem_region1),
++                         pci_resource_len(pdev, mem_region1));
++      release_mem_region(pci_resource_start(pdev, mem_region2),
++                         pci_resource_len(pdev, mem_region2));
++      pci_disable_device(pdev);
++
++      /* remove dev registration */
++      pci_set_drvdata(pdev, NULL);
++
++      acx_sem_unlock(adev);
++
++      /* Free netdev (quite late,
++       * since otherwise we might get caught off-guard
++       * by a netdev timeout handler execution
++       * expecting to see a working dev...) */
++      free_netdev(ndev);
++
++      /* put device into ACPI D3 mode (shutdown) */
++      pci_set_power_state(pdev, PCI_D3hot);
++
++end:
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++** TODO: PM code needs to be fixed / debugged / tested.
++*/
++#ifdef CONFIG_PM
++static int
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11)
++acxpci_e_suspend(struct pci_dev *pdev, pm_message_t state)
++#else
++acxpci_e_suspend(struct pci_dev *pdev, u32 state)
++#endif
++{
++      struct net_device *ndev = pci_get_drvdata(pdev);
++      acx_device_t *adev;
++
++      FN_ENTER;
++      printk("acx: suspend handler is experimental!\n");
++      printk("sus: dev %p\n", ndev);
++
++      if (!netif_running(ndev))
++              goto end;
++
++      adev = ndev2adev(ndev);
++      printk("sus: adev %p\n", adev);
++
++      acx_sem_lock(adev);
++
++      netif_device_detach(ndev);      /* this one cannot sleep */
++      acxpci_s_down(ndev);
++      /* down() does not set it to 0xffff, but here we really want that */
++      write_reg16(adev, IO_ACX_IRQ_MASK, 0xffff);
++      write_reg16(adev, IO_ACX_FEMR, 0x0);
++      acxpci_s_delete_dma_regions(adev);
++      pci_save_state(pdev);
++      pci_set_power_state(pdev, PCI_D3hot);
++
++      acx_sem_unlock(adev);
++end:
++      FN_EXIT0;
++      return OK;
++}
++
++
++static int
++acxpci_e_resume(struct pci_dev *pdev)
++{
++      struct net_device *ndev = pci_get_drvdata(pdev);
++      acx_device_t *adev;
++
++      FN_ENTER;
++
++      printk("acx: resume handler is experimental!\n");
++      printk("rsm: got dev %p\n", ndev);
++
++      if (!netif_running(ndev))
++              goto end;
++
++      adev = ndev2adev(ndev);
++      printk("rsm: got adev %p\n", adev);
++
++      acx_sem_lock(adev);
++
++      pci_set_power_state(pdev, PCI_D0);
++      printk("rsm: power state PCI_D0 set\n");
++      pci_restore_state(pdev);
++      printk("rsm: PCI state restored\n");
++
++      if (OK != acxpci_s_reset_dev(adev))
++              goto end_unlock;
++      printk("rsm: device reset done\n");
++      if (OK != acx_s_init_mac(adev))
++              goto end_unlock;
++      printk("rsm: init MAC done\n");
++
++      acxpci_s_up(ndev);
++      printk("rsm: acx up done\n");
++
++      /* now even reload all card parameters as they were before suspend,
++       * and possibly be back in the network again already :-) */
++      if (ACX_STATE_IFACE_UP & adev->dev_state_mask) {
++              adev->set_mask = GETSET_ALL;
++              acx_s_update_card_settings(adev);
++              printk("rsm: settings updated\n");
++      }
++      netif_device_attach(ndev);
++      printk("rsm: device attached\n");
++
++end_unlock:
++      acx_sem_unlock(adev);
++end:
++      /* we need to return OK here anyway, right? */
++      FN_EXIT0;
++      return OK;
++}
++#endif /* CONFIG_PM */
++
++
++/***********************************************************************
++** acxpci_s_up
++**
++** This function is called by acxpci_e_open (when ifconfig sets the device as up)
++**
++** Side effects:
++** - Enables on-card interrupt requests
++** - calls acx_s_start
++*/
++
++static void
++enable_acx_irq(acx_device_t *adev)
++{
++      FN_ENTER;
++      write_reg16(adev, IO_ACX_IRQ_MASK, adev->irq_mask);
++      write_reg16(adev, IO_ACX_FEMR, 0x8000);
++      adev->irqs_active = 1;
++      FN_EXIT0;
++}
++
++static void
++acxpci_s_up(struct net_device *ndev)
++{
++      acx_device_t *adev = ndev2adev(ndev);
++      unsigned long flags;
++
++      FN_ENTER;
++
++      acx_lock(adev, flags);
++      enable_acx_irq(adev);
++      acx_unlock(adev, flags);
++
++      /* acx fw < 1.9.3.e has a hardware timer, and older drivers
++      ** used to use it. But we don't do that anymore, our OS
++      ** has reliable software timers */
++      init_timer(&adev->mgmt_timer);
++      adev->mgmt_timer.function = acx_i_timer;
++      adev->mgmt_timer.data = (unsigned long)adev;
++
++      /* Need to set ACX_STATE_IFACE_UP first, or else
++      ** timer won't be started by acx_set_status() */
++      SET_BIT(adev->dev_state_mask, ACX_STATE_IFACE_UP);
++      switch (adev->mode) {
++      case ACX_MODE_0_ADHOC:
++      case ACX_MODE_2_STA:
++              /* actual scan cmd will happen in start() */
++              acx_set_status(adev, ACX_STATUS_1_SCANNING); break;
++      case ACX_MODE_3_AP:
++      case ACX_MODE_MONITOR:
++              acx_set_status(adev, ACX_STATUS_4_ASSOCIATED); break;
++      }
++
++      acx_s_start(adev);
++
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++** acxpci_s_down
++**
++** NB: device may be already hot unplugged if called from acxpci_e_remove()
++**
++** Disables on-card interrupt request, stops softirq and timer, stops queue,
++** sets status == STOPPED
++*/
++
++static void
++disable_acx_irq(acx_device_t *adev)
++{
++      FN_ENTER;
++
++      /* I guess mask is not 0xffff because acx100 won't signal
++      ** cmd completion then (needed for ifup).
++      ** Someone with acx100 please confirm */
++      write_reg16(adev, IO_ACX_IRQ_MASK, adev->irq_mask_off);
++      write_reg16(adev, IO_ACX_FEMR, 0x0);
++      adev->irqs_active = 0;
++      FN_EXIT0;
++}
++
++static void
++acxpci_s_down(struct net_device *ndev)
++{
++      acx_device_t *adev = ndev2adev(ndev);
++      unsigned long flags;
++
++      FN_ENTER;
++
++      /* Disable IRQs first, so that IRQs cannot race with us */
++      /* then wait until interrupts have finished executing on other CPUs */
++      acx_lock(adev, flags);
++      disable_acx_irq(adev);
++      synchronize_irq(adev->pdev->irq);
++      acx_unlock(adev, flags);
++
++      /* we really don't want to have an asynchronous tasklet disturb us
++      ** after something vital for its job has been shut down, so
++      ** end all remaining work now.
++      **
++      ** NB: carrier_off (done by set_status below) would lead to
++      ** not yet fully understood deadlock in FLUSH_SCHEDULED_WORK().
++      ** That's why we do FLUSH first.
++      **
++      ** NB2: we have a bad locking bug here: FLUSH_SCHEDULED_WORK()
++      ** waits for acx_e_after_interrupt_task to complete if it is running
++      ** on another CPU, but acx_e_after_interrupt_task
++      ** will sleep on sem forever, because it is taken by us!
++      ** Work around that by temporary sem unlock.
++      ** This will fail miserably if we'll be hit by concurrent
++      ** iwconfig or something in between. TODO! */
++      acx_sem_unlock(adev);
++      FLUSH_SCHEDULED_WORK();
++      acx_sem_lock(adev);
++
++      /* This is possible:
++      ** FLUSH_SCHEDULED_WORK -> acx_e_after_interrupt_task ->
++      ** -> set_status(ASSOCIATED) -> wake_queue()
++      ** That's why we stop queue _after_ FLUSH_SCHEDULED_WORK
++      ** lock/unlock is just paranoia, maybe not needed */
++      acx_lock(adev, flags);
++      acx_stop_queue(ndev, "on ifdown");
++      acx_set_status(adev, ACX_STATUS_0_STOPPED);
++      acx_unlock(adev, flags);
++
++      /* kernel/timer.c says it's illegal to del_timer_sync()
++      ** a timer which restarts itself. We guarantee this cannot
++      ** ever happen because acx_i_timer() never does this if
++      ** status is ACX_STATUS_0_STOPPED */
++      del_timer_sync(&adev->mgmt_timer);
++
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++** acxpci_e_open
++**
++** Called as a result of SIOCSIFFLAGS ioctl changing the flags bit IFF_UP
++** from clear to set. In other words: ifconfig up.
++**
++** Returns:
++**    0       success
++**    >0      f/w reported error
++**    <0      driver reported error
++*/
++static int
++acxpci_e_open(struct net_device *ndev)
++{
++      acx_device_t *adev = ndev2adev(ndev);
++      int result = OK;
++
++      FN_ENTER;
++
++      acx_sem_lock(adev);
++
++      acx_init_task_scheduler(adev);
++
++/* TODO: pci_set_power_state(pdev, PCI_D0); ? */
++
++      /* request shared IRQ handler */
++      if (request_irq(ndev->irq, acxpci_i_interrupt, SA_SHIRQ, ndev->name, ndev)) {
++              printk("%s: request_irq FAILED\n", ndev->name);
++              result = -EAGAIN;
++              goto done;
++      }
++      log(L_DEBUG|L_IRQ, "request_irq %d successful\n", ndev->irq);
++
++      /* ifup device */
++      acxpci_s_up(ndev);
++
++      /* We don't currently have to do anything else.
++       * The setup of the MAC should be subsequently completed via
++       * the mlme commands.
++       * Higher layers know we're ready from dev->start==1 and
++       * dev->tbusy==0.  Our rx path knows to pass up received/
++       * frames because of dev->flags&IFF_UP is true.
++       */
++done:
++      acx_sem_unlock(adev);
++
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/***********************************************************************
++** acxpci_e_close
++**
++** Called as a result of SIOCSIIFFLAGS ioctl changing the flags bit IFF_UP
++** from set to clear. I.e. called by "ifconfig DEV down"
++**
++** Returns:
++**    0       success
++**    >0      f/w reported error
++**    <0      driver reported error
++*/
++static int
++acxpci_e_close(struct net_device *ndev)
++{
++      acx_device_t *adev = ndev2adev(ndev);
++
++      FN_ENTER;
++
++      acx_sem_lock(adev);
++
++      /* ifdown device */
++      CLEAR_BIT(adev->dev_state_mask, ACX_STATE_IFACE_UP);
++      if (netif_device_present(ndev)) {
++              acxpci_s_down(ndev);
++      }
++
++      /* disable all IRQs, release shared IRQ handler */
++      write_reg16(adev, IO_ACX_IRQ_MASK, 0xffff);
++      write_reg16(adev, IO_ACX_FEMR, 0x0);
++      free_irq(ndev->irq, ndev);
++
++/* TODO: pci_set_power_state(pdev, PCI_D3hot); ? */
++
++      /* We currently don't have to do anything else.
++       * Higher layers know we're not ready from dev->start==0 and
++       * dev->tbusy==1.  Our rx path knows to not pass up received
++       * frames because of dev->flags&IFF_UP is false.
++       */
++      acx_sem_unlock(adev);
++
++      log(L_INIT, "closed device\n");
++      FN_EXIT0;
++      return OK;
++}
++
++
++/***********************************************************************
++** acxpci_i_tx_timeout
++**
++** Called from network core. Must not sleep!
++*/
++static void
++acxpci_i_tx_timeout(struct net_device *ndev)
++{
++      acx_device_t *adev = ndev2adev(ndev);
++      unsigned long flags;
++      unsigned int tx_num_cleaned;
++
++      FN_ENTER;
++
++      acx_lock(adev, flags);
++
++      /* clean processed tx descs, they may have been completely full */
++      tx_num_cleaned = acxpci_l_clean_txdesc(adev);
++
++      /* nothing cleaned, yet (almost) no free buffers available?
++       * --> clean all tx descs, no matter which status!!
++       * Note that I strongly suspect that doing emergency cleaning
++       * may confuse the firmware. This is a last ditch effort to get
++       * ANYTHING to work again...
++       *
++       * TODO: it's best to simply reset & reinit hw from scratch...
++       */
++      if ((adev->tx_free <= TX_EMERG_CLEAN) && (tx_num_cleaned == 0)) {
++              printk("%s: FAILED to free any of the many full tx buffers. "
++                      "Switching to emergency freeing. "
++                      "Please report!\n", ndev->name);
++              acxpci_l_clean_txdesc_emergency(adev);
++      }
++
++      if (acx_queue_stopped(ndev) && (ACX_STATUS_4_ASSOCIATED == adev->status))
++              acx_wake_queue(ndev, "after tx timeout");
++
++      /* stall may have happened due to radio drift, so recalib radio */
++      acx_schedule_task(adev, ACX_AFTER_IRQ_CMD_RADIO_RECALIB);
++
++      /* do unimportant work last */
++      printk("%s: tx timeout!\n", ndev->name);
++      adev->stats.tx_errors++;
++
++      acx_unlock(adev, flags);
++
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++** acxpci_i_set_multicast_list
++** FIXME: most likely needs refinement
++*/
++static void
++acxpci_i_set_multicast_list(struct net_device *ndev)
++{
++      acx_device_t *adev = ndev2adev(ndev);
++      unsigned long flags;
++
++      FN_ENTER;
++
++      acx_lock(adev, flags);
++
++      /* firmwares don't have allmulti capability,
++       * so just use promiscuous mode instead in this case. */
++      if (ndev->flags & (IFF_PROMISC|IFF_ALLMULTI)) {
++              SET_BIT(adev->rx_config_1, RX_CFG1_RCV_PROMISCUOUS);
++              CLEAR_BIT(adev->rx_config_1, RX_CFG1_FILTER_ALL_MULTI);
++              SET_BIT(adev->set_mask, SET_RXCONFIG);
++              /* let kernel know in case *we* needed to set promiscuous */
++              ndev->flags |= (IFF_PROMISC|IFF_ALLMULTI);
++      } else {
++              CLEAR_BIT(adev->rx_config_1, RX_CFG1_RCV_PROMISCUOUS);
++              SET_BIT(adev->rx_config_1, RX_CFG1_FILTER_ALL_MULTI);
++              SET_BIT(adev->set_mask, SET_RXCONFIG);
++              ndev->flags &= ~(IFF_PROMISC|IFF_ALLMULTI);
++      }
++
++      /* cannot update card settings directly here, atomic context */
++      acx_schedule_task(adev, ACX_AFTER_IRQ_UPDATE_CARD_CFG);
++
++      acx_unlock(adev, flags);
++
++      FN_EXIT0;
++}
++
++
++/***************************************************************
++** acxpci_l_process_rxdesc
++**
++** Called directly and only from the IRQ handler
++*/
++
++#if !ACX_DEBUG
++static inline void log_rxbuffer(const acx_device_t *adev) {}
++#else
++static void
++log_rxbuffer(const acx_device_t *adev)
++{
++      register const struct rxhostdesc *rxhostdesc;
++      int i;
++      /* no FN_ENTER here, we don't want that */
++
++      rxhostdesc = adev->rxhostdesc_start;
++      if (unlikely(!rxhostdesc)) return;
++      for (i = 0; i < RX_CNT; i++) {
++              if ((rxhostdesc->Ctl_16 & cpu_to_le16(DESC_CTL_HOSTOWN))
++               && (rxhostdesc->Status & cpu_to_le32(DESC_STATUS_FULL)))
++                      printk("rx: buf %d full\n", i);
++              rxhostdesc++;
++      }
++}
++#endif
++
++static void
++acxpci_l_process_rxdesc(acx_device_t *adev)
++{
++      register rxhostdesc_t *hostdesc;
++      unsigned count, tail;
++
++      FN_ENTER;
++
++      if (unlikely(acx_debug & L_BUFR))
++              log_rxbuffer(adev);
++
++      /* First, have a loop to determine the first descriptor that's
++       * full, just in case there's a mismatch between our current
++       * rx_tail and the full descriptor we're supposed to handle. */
++      tail = adev->rx_tail;
++      count = RX_CNT;
++      while (1) {
++              hostdesc = &adev->rxhostdesc_start[tail];
++              /* advance tail regardless of outcome of the below test */
++              tail = (tail + 1) % RX_CNT;
++
++              if ((hostdesc->Ctl_16 & cpu_to_le16(DESC_CTL_HOSTOWN))
++               && (hostdesc->Status & cpu_to_le32(DESC_STATUS_FULL)))
++                      break;          /* found it! */
++
++              if (unlikely(!--count)) /* hmm, no luck: all descs empty, bail out */
++                      goto end;
++      }
++
++      /* now process descriptors, starting with the first we figured out */
++      while (1) {
++              log(L_BUFR, "rx: tail=%u Ctl_16=%04X Status=%08X\n",
++                      tail, hostdesc->Ctl_16, hostdesc->Status);
++
++              acx_l_process_rxbuf(adev, hostdesc->data);
++
++              hostdesc->Status = 0;
++              /* flush all writes before adapter sees CTL_HOSTOWN change */
++              wmb();
++              /* Host no longer owns this, needs to be LAST */
++              CLEAR_BIT(hostdesc->Ctl_16, cpu_to_le16(DESC_CTL_HOSTOWN));
++
++              /* ok, descriptor is handled, now check the next descriptor */
++              hostdesc = &adev->rxhostdesc_start[tail];
++
++              /* if next descriptor is empty, then bail out */
++              if (!(hostdesc->Ctl_16 & cpu_to_le16(DESC_CTL_HOSTOWN))
++               || !(hostdesc->Status & cpu_to_le32(DESC_STATUS_FULL)))
++                      break;
++
++              tail = (tail + 1) % RX_CNT;
++      }
++end:
++      adev->rx_tail = tail;
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++** acxpci_i_interrupt
++**
++** IRQ handler (atomic context, must not sleep, blah, blah)
++*/
++
++/* scan is complete. all frames now on the receive queue are valid */
++#define INFO_SCAN_COMPLETE      0x0001
++#define INFO_WEP_KEY_NOT_FOUND  0x0002
++/* hw has been reset as the result of a watchdog timer timeout */
++#define INFO_WATCH_DOG_RESET    0x0003
++/* failed to send out NULL frame from PS mode notification to AP */
++/* recommended action: try entering 802.11 PS mode again */
++#define INFO_PS_FAIL            0x0004
++/* encryption/decryption process on a packet failed */
++#define INFO_IV_ICV_FAILURE     0x0005
++
++/* Info mailbox format:
++2 bytes: type
++2 bytes: status
++more bytes may follow
++    rumors say about status:
++      0x0000 info available (set by hw)
++      0x0001 information received (must be set by host)
++      0x1000 info available, mailbox overflowed (messages lost) (set by hw)
++    but in practice we've seen:
++      0x9000 when we did not set status to 0x0001 on prev message
++      0x1001 when we did set it
++      0x0000 was never seen
++    conclusion: this is really a bitfield:
++    0x1000 is 'info available' bit
++    'mailbox overflowed' bit is 0x8000, not 0x1000
++    value of 0x0000 probably means that there are no messages at all
++    P.S. I dunno how in hell hw is supposed to notice that messages are lost -
++    it does NOT clear bit 0x0001, and this bit will probably stay forever set
++    after we set it once. Let's hope this will be fixed in firmware someday
++*/
++
++static void
++handle_info_irq(acx_device_t *adev)
++{
++#if ACX_DEBUG
++      static const char * const info_type_msg[] = {
++              "(unknown)",
++              "scan complete",
++              "WEP key not found",
++              "internal watchdog reset was done",
++              "failed to send powersave (NULL frame) notification to AP",
++              "encrypt/decrypt on a packet has failed",
++              "TKIP tx keys disabled",
++              "TKIP rx keys disabled",
++              "TKIP rx: key ID not found",
++              "???",
++              "???",
++              "???",
++              "???",
++              "???",
++              "???",
++              "???",
++              "TKIP IV value exceeds thresh"
++      };
++#endif
++      u32 info_type, info_status;
++
++      info_type = readl(adev->info_area);
++      info_status = (info_type >> 16);
++      info_type = (u16)info_type;
++
++      /* inform fw that we have read this info message */
++      writel(info_type | 0x00010000, adev->info_area);
++      write_reg16(adev, IO_ACX_INT_TRIG, INT_TRIG_INFOACK);
++      write_flush(adev);
++
++      log(L_CTL, "info_type:%04X info_status:%04X\n",
++                      info_type, info_status);
++
++      log(L_IRQ, "got Info IRQ: status %04X type %04X: %s\n",
++              info_status, info_type,
++              info_type_msg[(info_type >= VEC_SIZE(info_type_msg)) ?
++                              0 : info_type]
++      );
++}
++
++
++static void
++log_unusual_irq(u16 irqtype) {
++      /*
++      if (!printk_ratelimit())
++              return;
++      */
++
++      printk("acx: got");
++      if (irqtype & HOST_INT_RX_DATA) {
++              printk(" Rx_Data");
++      }
++              /* HOST_INT_TX_COMPLETE   */
++      if (irqtype & HOST_INT_TX_XFER) {
++              printk(" Tx_Xfer");
++      }
++              /* HOST_INT_RX_COMPLETE   */
++      if (irqtype & HOST_INT_DTIM) {
++              printk(" DTIM");
++      }
++      if (irqtype & HOST_INT_BEACON) {
++              printk(" Beacon");
++      }
++      if (irqtype & HOST_INT_TIMER) {
++              log(L_IRQ, " Timer");
++      }
++      if (irqtype & HOST_INT_KEY_NOT_FOUND) {
++              printk(" Key_Not_Found");
++      }
++      if (irqtype & HOST_INT_IV_ICV_FAILURE) {
++              printk(" IV_ICV_Failure (crypto)");
++      }
++              /* HOST_INT_CMD_COMPLETE  */
++              /* HOST_INT_INFO          */
++      if (irqtype & HOST_INT_OVERFLOW) {
++              printk(" Overflow");
++      }
++      if (irqtype & HOST_INT_PROCESS_ERROR) {
++              printk(" Process_Error");
++      }
++              /* HOST_INT_SCAN_COMPLETE */
++      if (irqtype & HOST_INT_FCS_THRESHOLD) {
++              printk(" FCS_Threshold");
++      }
++      if (irqtype & HOST_INT_UNKNOWN) {
++              printk(" Unknown");
++      }
++      printk(" IRQ(s)\n");
++}
++
++
++static void
++update_link_quality_led(acx_device_t *adev)
++{
++      int qual;
++
++      qual = acx_signal_determine_quality(adev->wstats.qual.level, adev->wstats.qual.noise);
++      if (qual > adev->brange_max_quality)
++              qual = adev->brange_max_quality;
++
++      if (time_after(jiffies, adev->brange_time_last_state_change +
++                              (HZ/2 - HZ/2 * (unsigned long)qual / adev->brange_max_quality ) )) {
++              acxpci_l_power_led(adev, (adev->brange_last_state == 0));
++              adev->brange_last_state ^= 1; /* toggle */
++              adev->brange_time_last_state_change = jiffies;
++      }
++}
++
++
++#define MAX_IRQLOOPS_PER_JIFFY  (20000/HZ) /* a la orinoco.c */
++
++static irqreturn_t
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
++acxpci_i_interrupt(int irq, void *dev_id)
++#else
++acxpci_i_interrupt(int irq, void *dev_id, struct pt_regs *regs)
++#endif
++{
++      acx_device_t *adev;
++      unsigned long flags;
++      unsigned int irqcount = MAX_IRQLOOPS_PER_JIFFY;
++      register u16 irqtype;
++      u16 unmasked;
++
++      adev = ndev2adev((struct net_device*)dev_id);
++
++      /* LOCKING: can just spin_lock() since IRQs are disabled anyway.
++       * I am paranoid */
++      acx_lock(adev, flags);
++
++      unmasked = read_reg16(adev, IO_ACX_IRQ_STATUS_CLEAR);
++      if (unlikely(0xffff == unmasked)) {
++              /* 0xffff value hints at missing hardware,
++               * so don't do anything.
++               * Not very clean, but other drivers do the same... */
++              log(L_IRQ, "IRQ type:FFFF - device removed? IRQ_NONE\n");
++              goto none;
++      }
++
++      /* We will check only "interesting" IRQ types */
++      irqtype = unmasked & ~adev->irq_mask;
++      if (!irqtype) {
++              /* We are on a shared IRQ line and it wasn't our IRQ */
++              log(L_IRQ, "IRQ type:%04X, mask:%04X - all are masked, IRQ_NONE\n",
++                      unmasked, adev->irq_mask);
++              goto none;
++      }
++
++      /* Done here because IRQ_NONEs taking three lines of log
++      ** drive me crazy */
++      FN_ENTER;
++
++#define IRQ_ITERATE 1
++#if IRQ_ITERATE
++if (jiffies != adev->irq_last_jiffies) {
++      adev->irq_loops_this_jiffy = 0;
++      adev->irq_last_jiffies = jiffies;
++}
++
++/* safety condition; we'll normally abort loop below
++ * in case no IRQ type occurred */
++while (likely(--irqcount)) {
++#endif
++      /* ACK all IRQs ASAP */
++      write_reg16(adev, IO_ACX_IRQ_ACK, 0xffff);
++
++      log(L_IRQ, "IRQ type:%04X, mask:%04X, type & ~mask:%04X\n",
++                              unmasked, adev->irq_mask, irqtype);
++
++      /* Handle most important IRQ types first */
++      if (irqtype & HOST_INT_RX_COMPLETE) {
++              log(L_IRQ, "got Rx_Complete IRQ\n");
++              acxpci_l_process_rxdesc(adev);
++      }
++      if (irqtype & HOST_INT_TX_COMPLETE) {
++              log(L_IRQ, "got Tx_Complete IRQ\n");
++              /* don't clean up on each Tx complete, wait a bit
++               * unless we're going towards full, in which case
++               * we do it immediately, too (otherwise we might lockup
++               * with a full Tx buffer if we go into
++               * acxpci_l_clean_txdesc() at a time when we won't wakeup
++               * the net queue in there for some reason...) */
++              if (adev->tx_free <= TX_START_CLEAN) {
++#if TX_CLEANUP_IN_SOFTIRQ
++                      acx_schedule_task(adev, ACX_AFTER_IRQ_TX_CLEANUP);
++#else
++                      acxpci_l_clean_txdesc(adev);
++#endif
++              }
++      }
++
++      /* Less frequent ones */
++      if (irqtype & (0
++              | HOST_INT_CMD_COMPLETE
++              | HOST_INT_INFO
++              | HOST_INT_SCAN_COMPLETE
++      )) {
++              if (irqtype & HOST_INT_CMD_COMPLETE) {
++                      log(L_IRQ, "got Command_Complete IRQ\n");
++                      /* save the state for the running issue_cmd() */
++                      SET_BIT(adev->irq_status, HOST_INT_CMD_COMPLETE);
++              }
++              if (irqtype & HOST_INT_INFO) {
++                      handle_info_irq(adev);
++              }
++              if (irqtype & HOST_INT_SCAN_COMPLETE) {
++                      log(L_IRQ, "got Scan_Complete IRQ\n");
++                      /* need to do that in process context */
++                      acx_schedule_task(adev, ACX_AFTER_IRQ_COMPLETE_SCAN);
++                      /* remember that fw is not scanning anymore */
++                      SET_BIT(adev->irq_status, HOST_INT_SCAN_COMPLETE);
++              }
++      }
++
++      /* These we just log, but either they happen rarely
++       * or we keep them masked out */
++      if (irqtype & (0
++              | HOST_INT_RX_DATA
++              /* | HOST_INT_TX_COMPLETE   */
++              | HOST_INT_TX_XFER
++              /* | HOST_INT_RX_COMPLETE   */
++              | HOST_INT_DTIM
++              | HOST_INT_BEACON
++              | HOST_INT_TIMER
++              | HOST_INT_KEY_NOT_FOUND
++              | HOST_INT_IV_ICV_FAILURE
++              /* | HOST_INT_CMD_COMPLETE  */
++              /* | HOST_INT_INFO          */
++              | HOST_INT_OVERFLOW
++              | HOST_INT_PROCESS_ERROR
++              /* | HOST_INT_SCAN_COMPLETE */
++              | HOST_INT_FCS_THRESHOLD
++              | HOST_INT_UNKNOWN
++      )) {
++              log_unusual_irq(irqtype);
++      }
++
++#if IRQ_ITERATE
++      unmasked = read_reg16(adev, IO_ACX_IRQ_STATUS_CLEAR);
++      irqtype = unmasked & ~adev->irq_mask;
++      /* Bail out if no new IRQ bits or if all are masked out */
++      if (!irqtype)
++              break;
++
++      if (unlikely(++adev->irq_loops_this_jiffy > MAX_IRQLOOPS_PER_JIFFY)) {
++              printk(KERN_ERR "acx: too many interrupts per jiffy!\n");
++              /* Looks like card floods us with IRQs! Try to stop that */
++              write_reg16(adev, IO_ACX_IRQ_MASK, 0xffff);
++              /* This will short-circuit all future attempts to handle IRQ.
++               * We cant do much more... */
++              adev->irq_mask = 0;
++              break;
++      }
++}
++#endif
++      /* Routine to perform blink with range */
++      if (unlikely(adev->led_power == 2))
++              update_link_quality_led(adev);
++
++/* handled: */
++      /* write_flush(adev); - not needed, last op was read anyway */
++      acx_unlock(adev, flags);
++      FN_EXIT0;
++      return IRQ_HANDLED;
++
++none:
++      acx_unlock(adev, flags);
++      return IRQ_NONE;
++}
++
++
++/***********************************************************************
++** acxpci_l_power_led
++*/
++void
++acxpci_l_power_led(acx_device_t *adev, int enable)
++{
++      u16 gpio_pled = IS_ACX111(adev) ? 0x0040 : 0x0800;
++
++      /* A hack. Not moving message rate limiting to adev->xxx
++       * (it's only a debug message after all) */
++      static int rate_limit = 0;
++
++      if (rate_limit++ < 3)
++              log(L_IOCTL, "Please report in case toggling the power "
++                              "LED doesn't work for your card!\n");
++      if (enable)
++              write_reg16(adev, IO_ACX_GPIO_OUT,
++                      read_reg16(adev, IO_ACX_GPIO_OUT) & ~gpio_pled);
++      else
++              write_reg16(adev, IO_ACX_GPIO_OUT,
++                      read_reg16(adev, IO_ACX_GPIO_OUT) | gpio_pled);
++}
++
++
++/***********************************************************************
++** Ioctls
++*/
++
++/***********************************************************************
++*/
++int
++acx111pci_ioctl_info(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      struct iw_param *vwrq,
++      char *extra)
++{
++#if ACX_DEBUG > 1
++      acx_device_t *adev = ndev2adev(ndev);
++      rxdesc_t *rxdesc;
++      txdesc_t *txdesc;
++      rxhostdesc_t *rxhostdesc;
++      txhostdesc_t *txhostdesc;
++      struct acx111_ie_memoryconfig memconf;
++      struct acx111_ie_queueconfig queueconf;
++      unsigned long flags;
++      int i;
++      char memmap[0x34];
++      char rxconfig[0x8];
++      char fcserror[0x8];
++      char ratefallback[0x5];
++
++      if ( !(acx_debug & (L_IOCTL|L_DEBUG)) )
++              return OK;
++      /* using printk() since we checked debug flag already */
++
++      acx_sem_lock(adev);
++
++      if (!IS_ACX111(adev)) {
++              printk("acx111-specific function called "
++                      "with non-acx111 chip, aborting\n");
++              goto end_ok;
++      }
++
++      /* get Acx111 Memory Configuration */
++      memset(&memconf, 0, sizeof(memconf));
++      /* BTW, fails with 12 (Write only) error code.
++      ** Retained for easy testing of issue_cmd error handling :) */
++      acx_s_interrogate(adev, &memconf, ACX1xx_IE_QUEUE_CONFIG);
++
++      /* get Acx111 Queue Configuration */
++      memset(&queueconf, 0, sizeof(queueconf));
++      acx_s_interrogate(adev, &queueconf, ACX1xx_IE_MEMORY_CONFIG_OPTIONS);
++
++      /* get Acx111 Memory Map */
++      memset(memmap, 0, sizeof(memmap));
++      acx_s_interrogate(adev, &memmap, ACX1xx_IE_MEMORY_MAP);
++
++      /* get Acx111 Rx Config */
++      memset(rxconfig, 0, sizeof(rxconfig));
++      acx_s_interrogate(adev, &rxconfig, ACX1xx_IE_RXCONFIG);
++
++      /* get Acx111 fcs error count */
++      memset(fcserror, 0, sizeof(fcserror));
++      acx_s_interrogate(adev, &fcserror, ACX1xx_IE_FCS_ERROR_COUNT);
++
++      /* get Acx111 rate fallback */
++      memset(ratefallback, 0, sizeof(ratefallback));
++      acx_s_interrogate(adev, &ratefallback, ACX1xx_IE_RATE_FALLBACK);
++
++      /* force occurrence of a beacon interrupt */
++      /* TODO: comment why is this necessary */
++      write_reg16(adev, IO_ACX_HINT_TRIG, HOST_INT_BEACON);
++
++      /* dump Acx111 Mem Configuration */
++      printk("dump mem config:\n"
++              "data read: %d, struct size: %d\n"
++              "Number of stations: %1X\n"
++              "Memory block size: %1X\n"
++              "tx/rx memory block allocation: %1X\n"
++              "count rx: %X / tx: %X queues\n"
++              "options %1X\n"
++              "fragmentation %1X\n"
++              "Rx Queue 1 Count Descriptors: %X\n"
++              "Rx Queue 1 Host Memory Start: %X\n"
++              "Tx Queue 1 Count Descriptors: %X\n"
++              "Tx Queue 1 Attributes: %X\n",
++              memconf.len, (int) sizeof(memconf),
++              memconf.no_of_stations,
++              memconf.memory_block_size,
++              memconf.tx_rx_memory_block_allocation,
++              memconf.count_rx_queues, memconf.count_tx_queues,
++              memconf.options,
++              memconf.fragmentation,
++              memconf.rx_queue1_count_descs,
++      acx2cpu(memconf.rx_queue1_host_rx_start),
++              memconf.tx_queue1_count_descs,
++              memconf.tx_queue1_attributes);
++
++      /* dump Acx111 Queue Configuration */
++      printk("dump queue head:\n"
++              "data read: %d, struct size: %d\n"
++              "tx_memory_block_address (from card): %X\n"
++              "rx_memory_block_address (from card): %X\n"
++              "rx1_queue address (from card): %X\n"
++              "tx1_queue address (from card): %X\n"
++              "tx1_queue attributes (from card): %X\n",
++              queueconf.len, (int) sizeof(queueconf),
++              queueconf.tx_memory_block_address,
++              queueconf.rx_memory_block_address,
++              queueconf.rx1_queue_address,
++              queueconf.tx1_queue_address,
++              queueconf.tx1_attributes);
++
++      /* dump Acx111 Mem Map */
++      printk("dump mem map:\n"
++              "data read: %d, struct size: %d\n"
++              "Code start: %X\n"
++              "Code end: %X\n"
++              "WEP default key start: %X\n"
++              "WEP default key end: %X\n"
++              "STA table start: %X\n"
++              "STA table end: %X\n"
++              "Packet template start: %X\n"
++              "Packet template end: %X\n"
++              "Queue memory start: %X\n"
++              "Queue memory end: %X\n"
++              "Packet memory pool start: %X\n"
++              "Packet memory pool end: %X\n"
++              "iobase: %p\n"
++              "iobase2: %p\n",
++              *((u16 *)&memmap[0x02]), (int) sizeof(memmap),
++              *((u32 *)&memmap[0x04]),
++              *((u32 *)&memmap[0x08]),
++              *((u32 *)&memmap[0x0C]),
++              *((u32 *)&memmap[0x10]),
++              *((u32 *)&memmap[0x14]),
++              *((u32 *)&memmap[0x18]),
++              *((u32 *)&memmap[0x1C]),
++              *((u32 *)&memmap[0x20]),
++              *((u32 *)&memmap[0x24]),
++              *((u32 *)&memmap[0x28]),
++              *((u32 *)&memmap[0x2C]),
++              *((u32 *)&memmap[0x30]),
++              adev->iobase,
++              adev->iobase2);
++
++      /* dump Acx111 Rx Config */
++      printk("dump rx config:\n"
++              "data read: %d, struct size: %d\n"
++              "rx config: %X\n"
++              "rx filter config: %X\n",
++              *((u16 *)&rxconfig[0x02]), (int) sizeof(rxconfig),
++              *((u16 *)&rxconfig[0x04]),
++              *((u16 *)&rxconfig[0x06]));
++
++      /* dump Acx111 fcs error */
++      printk("dump fcserror:\n"
++              "data read: %d, struct size: %d\n"
++              "fcserrors: %X\n",
++              *((u16 *)&fcserror[0x02]), (int) sizeof(fcserror),
++              *((u32 *)&fcserror[0x04]));
++
++      /* dump Acx111 rate fallback */
++      printk("dump rate fallback:\n"
++              "data read: %d, struct size: %d\n"
++              "ratefallback: %X\n",
++              *((u16 *)&ratefallback[0x02]), (int) sizeof(ratefallback),
++              *((u8 *)&ratefallback[0x04]));
++
++      /* protect against IRQ */
++      acx_lock(adev, flags);
++
++      /* dump acx111 internal rx descriptor ring buffer */
++      rxdesc = adev->rxdesc_start;
++
++      /* loop over complete receive pool */
++      if (rxdesc) for (i = 0; i < RX_CNT; i++) {
++              printk("\ndump internal rxdesc %d:\n"
++                      "mem pos %p\n"
++                      "next 0x%X\n"
++                      "acx mem pointer (dynamic) 0x%X\n"
++                      "CTL (dynamic) 0x%X\n"
++                      "Rate (dynamic) 0x%X\n"
++                      "RxStatus (dynamic) 0x%X\n"
++                      "Mod/Pre (dynamic) 0x%X\n",
++                      i,
++                      rxdesc,
++                      acx2cpu(rxdesc->pNextDesc),
++                      acx2cpu(rxdesc->ACXMemPtr),
++                      rxdesc->Ctl_8,
++                      rxdesc->rate,
++                      rxdesc->error,
++                      rxdesc->SNR);
++              rxdesc++;
++      }
++
++      /* dump host rx descriptor ring buffer */
++
++      rxhostdesc = adev->rxhostdesc_start;
++
++      /* loop over complete receive pool */
++      if (rxhostdesc) for (i = 0; i < RX_CNT; i++) {
++              printk("\ndump host rxdesc %d:\n"
++                      "mem pos %p\n"
++                      "buffer mem pos 0x%X\n"
++                      "buffer mem offset 0x%X\n"
++                      "CTL 0x%X\n"
++                      "Length 0x%X\n"
++                      "next 0x%X\n"
++                      "Status 0x%X\n",
++                      i,
++                      rxhostdesc,
++                      acx2cpu(rxhostdesc->data_phy),
++                      rxhostdesc->data_offset,
++                      le16_to_cpu(rxhostdesc->Ctl_16),
++                      le16_to_cpu(rxhostdesc->length),
++                      acx2cpu(rxhostdesc->desc_phy_next),
++                      rxhostdesc->Status);
++              rxhostdesc++;
++      }
++
++      /* dump acx111 internal tx descriptor ring buffer */
++      txdesc = adev->txdesc_start;
++
++      /* loop over complete transmit pool */
++      if (txdesc) for (i = 0; i < TX_CNT; i++) {
++              printk("\ndump internal txdesc %d:\n"
++                      "size 0x%X\n"
++                      "mem pos %p\n"
++                      "next 0x%X\n"
++                      "acx mem pointer (dynamic) 0x%X\n"
++                      "host mem pointer (dynamic) 0x%X\n"
++                      "length (dynamic) 0x%X\n"
++                      "CTL (dynamic) 0x%X\n"
++                      "CTL2 (dynamic) 0x%X\n"
++                      "Status (dynamic) 0x%X\n"
++                      "Rate (dynamic) 0x%X\n",
++                      i,
++                      (int) sizeof(struct txdesc),
++                      txdesc,
++                      acx2cpu(txdesc->pNextDesc),
++                      acx2cpu(txdesc->AcxMemPtr),
++                      acx2cpu(txdesc->HostMemPtr),
++                      le16_to_cpu(txdesc->total_length),
++                      txdesc->Ctl_8,
++                      txdesc->Ctl2_8, txdesc->error,
++                      txdesc->u.r1.rate);
++              txdesc = advance_txdesc(adev, txdesc, 1);
++      }
++
++      /* dump host tx descriptor ring buffer */
++
++      txhostdesc = adev->txhostdesc_start;
++
++      /* loop over complete host send pool */
++      if (txhostdesc) for (i = 0; i < TX_CNT * 2; i++) {
++              printk("\ndump host txdesc %d:\n"
++                      "mem pos %p\n"
++                      "buffer mem pos 0x%X\n"
++                      "buffer mem offset 0x%X\n"
++                      "CTL 0x%X\n"
++                      "Length 0x%X\n"
++                      "next 0x%X\n"
++                      "Status 0x%X\n",
++                      i,
++                      txhostdesc,
++                      acx2cpu(txhostdesc->data_phy),
++                      txhostdesc->data_offset,
++                      le16_to_cpu(txhostdesc->Ctl_16),
++                      le16_to_cpu(txhostdesc->length),
++                      acx2cpu(txhostdesc->desc_phy_next),
++                      le32_to_cpu(txhostdesc->Status));
++              txhostdesc++;
++      }
++
++      /* write_reg16(adev, 0xb4, 0x4); */
++
++      acx_unlock(adev, flags);
++end_ok:
++
++      acx_sem_unlock(adev);
++#endif /* ACX_DEBUG */
++      return OK;
++}
++
++
++/***********************************************************************
++*/
++int
++acx100pci_ioctl_set_phy_amp_bias(
++      struct net_device *ndev,
++      struct iw_request_info *info,
++      struct iw_param *vwrq,
++      char *extra)
++{
++      acx_device_t *adev = ndev2adev(ndev);
++      unsigned long flags;
++      u16 gpio_old;
++
++      if (!IS_ACX100(adev)) {
++              /* WARNING!!!
++               * Removing this check *might* damage
++               * hardware, since we're tweaking GPIOs here after all!!!
++               * You've been warned...
++               * WARNING!!! */
++              printk("acx: sorry, setting bias level for non-acx100 "
++                      "is not supported yet\n");
++              return OK;
++      }
++
++      if (*extra > 7) {
++              printk("acx: invalid bias parameter, range is 0-7\n");
++              return -EINVAL;
++      }
++
++      acx_sem_lock(adev);
++
++      /* Need to lock accesses to [IO_ACX_GPIO_OUT]:
++       * IRQ handler uses it to update LED */
++      acx_lock(adev, flags);
++      gpio_old = read_reg16(adev, IO_ACX_GPIO_OUT);
++      write_reg16(adev, IO_ACX_GPIO_OUT, (gpio_old & 0xf8ff) | ((u16)*extra << 8));
++      acx_unlock(adev, flags);
++
++      log(L_DEBUG, "gpio_old: 0x%04X\n", gpio_old);
++      printk("%s: PHY power amplifier bias: old:%d, new:%d\n",
++              ndev->name,
++              (gpio_old & 0x0700) >> 8, (unsigned char)*extra);
++
++      acx_sem_unlock(adev);
++
++      return OK;
++}
++
++
++/***************************************************************
++** acxpci_l_alloc_tx
++** Actually returns a txdesc_t* ptr
++**
++** FIXME: in case of fragments, should allocate multiple descrs
++** after figuring out how many we need and whether we still have
++** sufficiently many.
++*/
++tx_t*
++acxpci_l_alloc_tx(acx_device_t *adev)
++{
++      struct txdesc *txdesc;
++      unsigned head;
++      u8 ctl8;
++
++      FN_ENTER;
++
++      if (unlikely(!adev->tx_free)) {
++              printk("acx: BUG: no free txdesc left\n");
++              txdesc = NULL;
++              goto end;
++      }
++
++      head = adev->tx_head;
++      txdesc = get_txdesc(adev, head);
++      ctl8 = txdesc->Ctl_8;
++
++      /* 2005-10-11: there were several bug reports on this happening
++      ** but now cause seems to be understood & fixed */
++      if (unlikely(DESC_CTL_HOSTOWN != (ctl8 & DESC_CTL_ACXDONE_HOSTOWN))) {
++              /* whoops, descr at current index is not free, so probably
++               * ring buffer already full */
++              printk("acx: BUG: tx_head:%d Ctl8:0x%02X - failed to find "
++                      "free txdesc\n", head, ctl8);
++              txdesc = NULL;
++              goto end;
++      }
++
++      /* Needed in case txdesc won't be eventually submitted for tx */
++      txdesc->Ctl_8 = DESC_CTL_ACXDONE_HOSTOWN;
++
++      adev->tx_free--;
++      log(L_BUFT, "tx: got desc %u, %u remain\n",
++                      head, adev->tx_free);
++      /* Keep a few free descs between head and tail of tx ring.
++      ** It is not absolutely needed, just feels safer */
++      if (adev->tx_free < TX_STOP_QUEUE) {
++              log(L_BUF, "stop queue (%u tx desc left)\n",
++                              adev->tx_free);
++              acx_stop_queue(adev->ndev, NULL);
++      }
++
++      /* returning current descriptor, so advance to next free one */
++      adev->tx_head = (head + 1) % TX_CNT;
++end:
++      FN_EXIT0;
++
++      return (tx_t*)txdesc;
++}
++
++
++/***********************************************************************
++*/
++void*
++acxpci_l_get_txbuf(acx_device_t *adev, tx_t* tx_opaque)
++{
++      return get_txhostdesc(adev, (txdesc_t*)tx_opaque)->data;
++}
++
++
++/***********************************************************************
++** acxpci_l_tx_data
++**
++** Can be called from IRQ (rx -> (AP bridging or mgmt response) -> tx).
++** Can be called from acx_i_start_xmit (data frames from net core).
++**
++** FIXME: in case of fragments, should loop over the number of
++** pre-allocated tx descrs, properly setting up transfer data and
++** CTL_xxx flags according to fragment number.
++*/
++void
++acxpci_l_tx_data(acx_device_t *adev, tx_t* tx_opaque, int len)
++{
++      txdesc_t *txdesc = (txdesc_t*)tx_opaque;
++      txhostdesc_t *hostdesc1, *hostdesc2;
++      client_t *clt;
++      u16 rate_cur;
++      u8 Ctl_8, Ctl2_8;
++
++      FN_ENTER;
++
++      /* fw doesn't tx such packets anyhow */
++      if (unlikely(len < WLAN_HDR_A3_LEN))
++              goto end;
++
++      hostdesc1 = get_txhostdesc(adev, txdesc);
++      /* modify flag status in separate variable to be able to write it back
++       * in one big swoop later (also in order to have less device memory
++       * accesses) */
++      Ctl_8 = txdesc->Ctl_8;
++      Ctl2_8 = 0; /* really need to init it to 0, not txdesc->Ctl2_8, it seems */
++
++      hostdesc2 = hostdesc1 + 1;
++
++      /* DON'T simply set Ctl field to 0 here globally,
++       * it needs to maintain a consistent flag status (those are state flags!!),
++       * otherwise it may lead to severe disruption. Only set or reset particular
++       * flags at the exact moment this is needed... */
++
++      /* let chip do RTS/CTS handshaking before sending
++       * in case packet size exceeds threshold */
++      if (len > adev->rts_threshold)
++              SET_BIT(Ctl2_8, DESC_CTL2_RTS);
++      else
++              CLEAR_BIT(Ctl2_8, DESC_CTL2_RTS);
++
++      switch (adev->mode) {
++      case ACX_MODE_0_ADHOC:
++      case ACX_MODE_3_AP:
++              clt = acx_l_sta_list_get(adev, ((wlan_hdr_t*)hostdesc1->data)->a1);
++              break;
++      case ACX_MODE_2_STA:
++              clt = adev->ap_client;
++              break;
++#if 0
++/* testing was done on acx111: */
++      case ACX_MODE_MONITOR:
++              SET_BIT(Ctl2_8, 0
++/* sends CTS to self before packet */
++                      + DESC_CTL2_SEQ         /* don't increase sequence field */
++/* not working (looks like good fcs is still added) */
++                      + DESC_CTL2_FCS         /* don't add the FCS */
++/* not tested */
++                      + DESC_CTL2_MORE_FRAG
++/* not tested */
++                      + DESC_CTL2_RETRY       /* don't increase retry field */
++/* not tested */
++                      + DESC_CTL2_POWER       /* don't increase power mgmt. field */
++/* no effect */
++                      + DESC_CTL2_WEP         /* encrypt this frame */
++/* not tested */
++                      + DESC_CTL2_DUR         /* don't increase duration field */
++                      );
++              /* fallthrough */
++#endif
++      default: /* ACX_MODE_OFF, ACX_MODE_MONITOR */
++              clt = NULL;
++              break;
++      }
++
++      rate_cur = clt ? clt->rate_cur : adev->rate_bcast;
++      if (unlikely(!rate_cur)) {
++              printk("acx: driver bug! bad ratemask\n");
++              goto end;
++      }
++
++      /* used in tx cleanup routine for auto rate and accounting: */
++      put_txcr(adev, txdesc, clt, rate_cur);
++
++      txdesc->total_length = cpu_to_le16(len);
++      hostdesc2->length = cpu_to_le16(len - WLAN_HDR_A3_LEN);
++      if (IS_ACX111(adev)) {
++              /* note that if !txdesc->do_auto, txrate->cur
++              ** has only one nonzero bit */
++              txdesc->u.r2.rate111 = cpu_to_le16(
++                      rate_cur
++                      /* WARNING: I was never able to make it work with prism54 AP.
++                      ** It was falling down to 1Mbit where shortpre is not applicable,
++                      ** and not working at all at "5,11 basic rates only" setting.
++                      ** I even didn't see tx packets in radio packet capture.
++                      ** Disabled for now --vda */
++                      /*| ((clt->shortpre && clt->cur!=RATE111_1) ? RATE111_SHORTPRE : 0) */
++                      );
++#ifdef TODO_FIGURE_OUT_WHEN_TO_SET_THIS
++                      /* should add this to rate111 above as necessary */
++                      | (clt->pbcc511 ? RATE111_PBCC511 : 0)
++#endif
++              hostdesc1->length = cpu_to_le16(len);
++      } else { /* ACX100 */
++              u8 rate_100 = clt ? clt->rate_100 : adev->rate_bcast100;
++              txdesc->u.r1.rate = rate_100;
++#ifdef TODO_FIGURE_OUT_WHEN_TO_SET_THIS
++              if (clt->pbcc511) {
++                      if (n == RATE100_5 || n == RATE100_11)
++                              n |= RATE100_PBCC511;
++              }
++
++              if (clt->shortpre && (clt->cur != RATE111_1))
++                      SET_BIT(Ctl_8, DESC_CTL_SHORT_PREAMBLE); /* set Short Preamble */
++#endif
++              /* set autodma and reclaim and 1st mpdu */
++              SET_BIT(Ctl_8, DESC_CTL_AUTODMA | DESC_CTL_RECLAIM | DESC_CTL_FIRSTFRAG);
++#if ACX_FRAGMENTATION
++              /* SET_BIT(Ctl2_8, DESC_CTL2_MORE_FRAG); cannot set it unconditionally, needs to be set for all non-last fragments */
++#endif
++              hostdesc1->length = cpu_to_le16(WLAN_HDR_A3_LEN);
++      }
++      /* don't need to clean ack/rts statistics here, already
++       * done on descr cleanup */
++
++      /* clears HOSTOWN and ACXDONE bits, thus telling that the descriptors
++       * are now owned by the acx100; do this as LAST operation */
++      CLEAR_BIT(Ctl_8, DESC_CTL_ACXDONE_HOSTOWN);
++      /* flush writes before we release hostdesc to the adapter here */
++      wmb();
++      CLEAR_BIT(hostdesc1->Ctl_16, cpu_to_le16(DESC_CTL_HOSTOWN));
++      CLEAR_BIT(hostdesc2->Ctl_16, cpu_to_le16(DESC_CTL_HOSTOWN));
++
++      /* write back modified flags */
++      txdesc->Ctl2_8 = Ctl2_8;
++      txdesc->Ctl_8 = Ctl_8;
++      /* unused: txdesc->tx_time = cpu_to_le32(jiffies); */
++
++      /* flush writes before we tell the adapter that it's its turn now */
++      mmiowb();
++      write_reg16(adev, IO_ACX_INT_TRIG, INT_TRIG_TXPRC);
++      write_flush(adev);
++
++      /* log the packet content AFTER sending it,
++       * in order to not delay sending any further than absolutely needed
++       * Do separate logs for acx100/111 to have human-readable rates */
++      if (unlikely(acx_debug & (L_XFER|L_DATA))) {
++              u16 fc = ((wlan_hdr_t*)hostdesc1->data)->fc;
++              if (IS_ACX111(adev))
++                      printk("tx: pkt (%s): len %d "
++                              "rate %04X%s status %u\n",
++                              acx_get_packet_type_string(le16_to_cpu(fc)), len,
++                              le16_to_cpu(txdesc->u.r2.rate111),
++                              (le16_to_cpu(txdesc->u.r2.rate111) & RATE111_SHORTPRE) ? "(SPr)" : "",
++                              adev->status);
++              else
++                      printk("tx: pkt (%s): len %d rate %03u%s status %u\n",
++                              acx_get_packet_type_string(fc), len,
++                              txdesc->u.r1.rate,
++                              (Ctl_8 & DESC_CTL_SHORT_PREAMBLE) ? "(SPr)" : "",
++                              adev->status);
++
++              if (acx_debug & L_DATA) {
++                      printk("tx: 802.11 [%d]: ", len);
++                      acx_dump_bytes(hostdesc1->data, len);
++              }
++      }
++end:
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++** acxpci_l_clean_txdesc
++**
++** This function resets the txdescs' status when the ACX100
++** signals the TX done IRQ (txdescs have been processed), starting with
++** the pool index of the descriptor which we would use next,
++** in order to make sure that we can be as fast as possible
++** in filling new txdescs.
++** Everytime we get called we know where the next packet to be cleaned is.
++*/
++
++#if !ACX_DEBUG
++static inline void log_txbuffer(const acx_device_t *adev) {}
++#else
++static void
++log_txbuffer(acx_device_t *adev)
++{
++      txdesc_t *txdesc;
++      int i;
++
++      /* no FN_ENTER here, we don't want that */
++      /* no locks here, since it's entirely non-critical code */
++      txdesc = adev->txdesc_start;
++      if (unlikely(!txdesc)) return;
++      printk("tx: desc->Ctl8's:");
++      for (i = 0; i < TX_CNT; i++) {
++              printk(" %02X", txdesc->Ctl_8);
++              txdesc = advance_txdesc(adev, txdesc, 1);
++      }
++      printk("\n");
++}
++#endif
++
++
++static void
++handle_tx_error(acx_device_t *adev, u8 error, unsigned int finger)
++{
++      const char *err = "unknown error";
++
++      /* hmm, should we handle this as a mask
++       * of *several* bits?
++       * For now I think only caring about
++       * individual bits is ok... */
++      switch (error) {
++      case 0x01:
++              err = "no Tx due to error in other fragment";
++              adev->wstats.discard.fragment++;
++              break;
++      case 0x02:
++              err = "Tx aborted";
++              adev->stats.tx_aborted_errors++;
++              break;
++      case 0x04:
++              err = "Tx desc wrong parameters";
++              adev->wstats.discard.misc++;
++              break;
++      case 0x08:
++              err = "WEP key not found";
++              adev->wstats.discard.misc++;
++              break;
++      case 0x10:
++              err = "MSDU lifetime timeout? - try changing "
++                              "'iwconfig retry lifetime XXX'";
++              adev->wstats.discard.misc++;
++              break;
++      case 0x20:
++              err = "excessive Tx retries due to either distance "
++                      "too high or unable to Tx or Tx frame error - "
++                      "try changing 'iwconfig txpower XXX' or "
++                      "'sens'itivity or 'retry'";
++              adev->wstats.discard.retries++;
++              /* Tx error 0x20 also seems to occur on
++               * overheating, so I'm not sure whether we
++               * actually want to do aggressive radio recalibration,
++               * since people maybe won't notice then that their hardware
++               * is slowly getting cooked...
++               * Or is it still a safe long distance from utter
++               * radio non-functionality despite many radio recalibs
++               * to final destructive overheating of the hardware?
++               * In this case we really should do recalib here...
++               * I guess the only way to find out is to do a
++               * potentially fatal self-experiment :-\
++               * Or maybe only recalib in case we're using Tx
++               * rate auto (on errors switching to lower speed
++               * --> less heat?) or 802.11 power save mode?
++               *
++               * ok, just do it. */
++              if (++adev->retry_errors_msg_ratelimit % 4 == 0) {
++                      if (adev->retry_errors_msg_ratelimit <= 20) {
++                              printk("%s: several excessive Tx "
++                                      "retry errors occurred, attempting "
++                                      "to recalibrate radio. Radio "
++                                      "drift might be caused by increasing "
++                                      "card temperature, please check the card "
++                                      "before it's too late!\n",
++                                      adev->ndev->name);
++                              if (adev->retry_errors_msg_ratelimit == 20)
++                                      printk("disabling above message\n");
++                      }
++
++                      acx_schedule_task(adev, ACX_AFTER_IRQ_CMD_RADIO_RECALIB);
++              }
++              break;
++      case 0x40:
++              err = "Tx buffer overflow";
++              adev->stats.tx_fifo_errors++;
++              break;
++      case 0x80:
++              /* possibly ACPI C-state powersaving related!!!
++               * (DMA timeout due to excessively high wakeup
++               * latency after C-state activation!?)
++               * Disable C-State powersaving and try again,
++               * then PLEASE REPORT, I'm VERY interested in
++               * whether my theory is correct that this is
++               * actually the problem here.
++               * In that case, use new Linux idle wakeup latency
++               * requirements kernel API to prevent this issue. */
++              err = "DMA error";
++              adev->wstats.discard.misc++;
++              break;
++      }
++      adev->stats.tx_errors++;
++      if (adev->stats.tx_errors <= 20)
++              printk("%s: tx error 0x%02X, buf %02u! (%s)\n",
++                              adev->ndev->name, error, finger, err);
++      else
++              printk("%s: tx error 0x%02X, buf %02u!\n",
++                              adev->ndev->name, error, finger);
++}
++
++
++unsigned int
++acxpci_l_clean_txdesc(acx_device_t *adev)
++{
++      txdesc_t *txdesc;
++      unsigned finger;
++      int num_cleaned;
++      u16 r111;
++      u8 error, ack_failures, rts_failures, rts_ok, r100;
++
++      FN_ENTER;
++
++      if (unlikely(acx_debug & L_DEBUG))
++              log_txbuffer(adev);
++
++      log(L_BUFT, "tx: cleaning up bufs from %u\n", adev->tx_tail);
++
++      /* We know first descr which is not free yet. We advance it as far
++      ** as we see correct bits set in following descs (if next desc
++      ** is NOT free, we shouldn't advance at all). We know that in
++      ** front of tx_tail may be "holes" with isolated free descs.
++      ** We will catch up when all intermediate descs will be freed also */
++
++      finger = adev->tx_tail;
++      num_cleaned = 0;
++      while (likely(finger != adev->tx_head)) {
++              txdesc = get_txdesc(adev, finger);
++
++              /* If we allocated txdesc on tx path but then decided
++              ** to NOT use it, then it will be left as a free "bubble"
++              ** in the "allocated for tx" part of the ring.
++              ** We may meet it on the next ring pass here. */
++
++              /* stop if not marked as "tx finished" and "host owned" */
++              if ((txdesc->Ctl_8 & DESC_CTL_ACXDONE_HOSTOWN)
++                                      != DESC_CTL_ACXDONE_HOSTOWN) {
++                      if (unlikely(!num_cleaned)) { /* maybe remove completely */
++                              log(L_BUFT, "clean_txdesc: tail isn't free. "
++                                      "tail:%d head:%d\n",
++                                      adev->tx_tail, adev->tx_head);
++                      }
++                      break;
++              }
++
++              /* remember desc values... */
++              error = txdesc->error;
++              ack_failures = txdesc->ack_failures;
++              rts_failures = txdesc->rts_failures;
++              rts_ok = txdesc->rts_ok;
++              r100 = txdesc->u.r1.rate;
++              r111 = le16_to_cpu(txdesc->u.r2.rate111);
++
++              /* need to check for certain error conditions before we
++               * clean the descriptor: we still need valid descr data here */
++              if (unlikely(0x30 & error)) {
++                      /* only send IWEVTXDROP in case of retry or lifetime exceeded;
++                       * all other errors mean we screwed up locally */
++                      union iwreq_data wrqu;
++                      wlan_hdr_t *hdr;
++                      txhostdesc_t *hostdesc;
++
++                      hostdesc = get_txhostdesc(adev, txdesc);
++                      hdr = (wlan_hdr_t *)hostdesc->data;
++                      MAC_COPY(wrqu.addr.sa_data, hdr->a1);
++                      wireless_send_event(adev->ndev, IWEVTXDROP, &wrqu, NULL);
++              }
++
++              /* ...and free the desc */
++              txdesc->error = 0;
++              txdesc->ack_failures = 0;
++              txdesc->rts_failures = 0;
++              txdesc->rts_ok = 0;
++              /* signal host owning it LAST, since ACX already knows that this
++              ** descriptor is finished since it set Ctl_8 accordingly. */
++              txdesc->Ctl_8 = DESC_CTL_HOSTOWN;
++
++              adev->tx_free++;
++              num_cleaned++;
++
++              if ((adev->tx_free >= TX_START_QUEUE)
++               && (adev->status == ACX_STATUS_4_ASSOCIATED)
++               && (acx_queue_stopped(adev->ndev))
++              ) {
++                      log(L_BUF, "tx: wake queue (avail. Tx desc %u)\n",
++                                      adev->tx_free);
++                      acx_wake_queue(adev->ndev, NULL);
++              }
++
++              /* do error checking, rate handling and logging
++               * AFTER having done the work, it's faster */
++
++              /* do rate handling */
++              if (adev->rate_auto) {
++                      struct client *clt = get_txc(adev, txdesc);
++                      if (clt) {
++                              u16 cur = get_txr(adev, txdesc);
++                              if (clt->rate_cur == cur) {
++                                      acx_l_handle_txrate_auto(adev, clt,
++                                              cur, /* intended rate */
++                                              r100, r111, /* actually used rate */
++                                              (error & 0x30), /* was there an error? */
++                                              TX_CNT + TX_CLEAN_BACKLOG - adev->tx_free);
++                              }
++                      }
++              }
++
++              if (unlikely(error))
++                      handle_tx_error(adev, error, finger);
++
++              if (IS_ACX111(adev))
++                      log(L_BUFT, "tx: cleaned %u: !ACK=%u !RTS=%u RTS=%u r111=%04X\n",
++                              finger, ack_failures, rts_failures, rts_ok, r111);
++              else
++                      log(L_BUFT, "tx: cleaned %u: !ACK=%u !RTS=%u RTS=%u rate=%u\n",
++                              finger, ack_failures, rts_failures, rts_ok, r100);
++
++              /* update pointer for descr to be cleaned next */
++              finger = (finger + 1) % TX_CNT;
++      }
++
++      /* remember last position */
++      adev->tx_tail = finger;
++/* end: */
++      FN_EXIT1(num_cleaned);
++      return num_cleaned;
++}
++
++/* clean *all* Tx descriptors, and regardless of their previous state.
++ * Used for brute-force reset handling. */
++void
++acxpci_l_clean_txdesc_emergency(acx_device_t *adev)
++{
++      txdesc_t *txdesc;
++      int i;
++
++      FN_ENTER;
++
++      for (i = 0; i < TX_CNT; i++) {
++              txdesc = get_txdesc(adev, i);
++
++              /* free it */
++              txdesc->ack_failures = 0;
++              txdesc->rts_failures = 0;
++              txdesc->rts_ok = 0;
++              txdesc->error = 0;
++              txdesc->Ctl_8 = DESC_CTL_HOSTOWN;
++      }
++
++      adev->tx_free = TX_CNT;
++
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++** acxpci_s_create_tx_host_desc_queue
++*/
++
++static void*
++allocate(acx_device_t *adev, size_t size, dma_addr_t *phy, const char *msg)
++{
++      void *ptr;
++
++      ptr = dma_alloc_coherent(adev->pdev ? &adev->pdev->dev : NULL,
++                      size, phy, GFP_KERNEL);
++
++      if (ptr) {
++              log(L_DEBUG, "%s sz=%d adr=0x%p phy=0x%08llx\n",
++                              msg, (int)size, ptr, (unsigned long long)*phy);
++              memset(ptr, 0, size);
++              return ptr;
++      }
++      printk(KERN_ERR "acx: %s allocation FAILED (%d bytes)\n",
++                                      msg, (int)size);
++      return NULL;
++}
++
++
++static int
++acxpci_s_create_tx_host_desc_queue(acx_device_t *adev)
++{
++      txhostdesc_t *hostdesc;
++      u8 *txbuf;
++      dma_addr_t hostdesc_phy;
++      dma_addr_t txbuf_phy;
++      int i;
++
++      FN_ENTER;
++
++      /* allocate TX buffer */
++      adev->txbuf_area_size = TX_CNT * WLAN_A4FR_MAXLEN_WEP_FCS;
++      adev->txbuf_start = allocate(adev, adev->txbuf_area_size,
++                      &adev->txbuf_startphy, "txbuf_start");
++      if (!adev->txbuf_start)
++              goto fail;
++
++      /* allocate the TX host descriptor queue pool */
++      adev->txhostdesc_area_size = TX_CNT * 2*sizeof(*hostdesc);
++      adev->txhostdesc_start = allocate(adev, adev->txhostdesc_area_size,
++                      &adev->txhostdesc_startphy, "txhostdesc_start");
++      if (!adev->txhostdesc_start)
++              goto fail;
++      /* check for proper alignment of TX host descriptor pool */
++      if ((long) adev->txhostdesc_start & 3) {
++              printk("acx: driver bug: dma alloc returns unaligned address\n");
++              goto fail;
++      }
++
++      hostdesc = adev->txhostdesc_start;
++      hostdesc_phy = adev->txhostdesc_startphy;
++      txbuf = adev->txbuf_start;
++      txbuf_phy = adev->txbuf_startphy;
++
++#if 0
++/* Each tx buffer is accessed by hardware via
++** txdesc -> txhostdesc(s) -> txbuffer(s).
++** We use only one txhostdesc per txdesc, but it looks like
++** acx111 is buggy: it accesses second txhostdesc
++** (via hostdesc.desc_phy_next field) even if
++** txdesc->length == hostdesc->length and thus
++** entire packet was placed into first txhostdesc.
++** Due to this bug acx111 hangs unless second txhostdesc
++** has le16_to_cpu(hostdesc.length) = 3 (or larger)
++** Storing NULL into hostdesc.desc_phy_next
++** doesn't seem to help.
++**
++** Update: although it worked on Xterasys XN-2522g
++** with len=3 trick, WG311v2 is even more bogus, doesn't work.
++** Keeping this code (#ifdef'ed out) for documentational purposes.
++*/
++      for (i = 0; i < TX_CNT*2; i++) {
++              hostdesc_phy += sizeof(*hostdesc);
++              if (!(i & 1)) {
++                      hostdesc->data_phy = cpu2acx(txbuf_phy);
++                      /* hostdesc->data_offset = ... */
++                      /* hostdesc->reserved = ... */
++                      hostdesc->Ctl_16 = cpu_to_le16(DESC_CTL_HOSTOWN);
++                      /* hostdesc->length = ... */
++                      hostdesc->desc_phy_next = cpu2acx(hostdesc_phy);
++                      hostdesc->pNext = ptr2acx(NULL);
++                      /* hostdesc->Status = ... */
++                      /* below: non-hardware fields */
++                      hostdesc->data = txbuf;
++
++                      txbuf += WLAN_A4FR_MAXLEN_WEP_FCS;
++                      txbuf_phy += WLAN_A4FR_MAXLEN_WEP_FCS;
++              } else {
++                      /* hostdesc->data_phy = ... */
++                      /* hostdesc->data_offset = ... */
++                      /* hostdesc->reserved = ... */
++                      /* hostdesc->Ctl_16 = ... */
++                      hostdesc->length = cpu_to_le16(3); /* bug workaround */
++                      /* hostdesc->desc_phy_next = ... */
++                      /* hostdesc->pNext = ... */
++                      /* hostdesc->Status = ... */
++                      /* below: non-hardware fields */
++                      /* hostdesc->data = ... */
++              }
++              hostdesc++;
++      }
++#endif
++/* We initialize two hostdescs so that they point to adjacent
++** memory areas. Thus txbuf is really just a contiguous memory area */
++      for (i = 0; i < TX_CNT*2; i++) {
++              hostdesc_phy += sizeof(*hostdesc);
++
++              hostdesc->data_phy = cpu2acx(txbuf_phy);
++              /* done by memset(0): hostdesc->data_offset = 0; */
++              /* hostdesc->reserved = ... */
++              hostdesc->Ctl_16 = cpu_to_le16(DESC_CTL_HOSTOWN);
++              /* hostdesc->length = ... */
++              hostdesc->desc_phy_next = cpu2acx(hostdesc_phy);
++              /* done by memset(0): hostdesc->pNext = ptr2acx(NULL); */
++              /* hostdesc->Status = ... */
++              /* ->data is a non-hardware field: */
++              hostdesc->data = txbuf;
++
++              if (!(i & 1)) {
++                      txbuf += WLAN_HDR_A3_LEN;
++                      txbuf_phy += WLAN_HDR_A3_LEN;
++              } else {
++                      txbuf += WLAN_A4FR_MAXLEN_WEP_FCS - WLAN_HDR_A3_LEN;
++                      txbuf_phy += WLAN_A4FR_MAXLEN_WEP_FCS - WLAN_HDR_A3_LEN;
++              }
++              hostdesc++;
++      }
++      hostdesc--;
++      hostdesc->desc_phy_next = cpu2acx(adev->txhostdesc_startphy);
++
++      FN_EXIT1(OK);
++      return OK;
++fail:
++      printk("acx: create_tx_host_desc_queue FAILED\n");
++      /* dealloc will be done by free function on error case */
++      FN_EXIT1(NOT_OK);
++      return NOT_OK;
++}
++
++
++/***************************************************************
++** acxpci_s_create_rx_host_desc_queue
++*/
++/* the whole size of a data buffer (header plus data body)
++ * plus 32 bytes safety offset at the end */
++#define RX_BUFFER_SIZE (sizeof(rxbuffer_t) + 32)
++
++static int
++acxpci_s_create_rx_host_desc_queue(acx_device_t *adev)
++{
++      rxhostdesc_t *hostdesc;
++      rxbuffer_t *rxbuf;
++      dma_addr_t hostdesc_phy;
++      dma_addr_t rxbuf_phy;
++      int i;
++
++      FN_ENTER;
++
++      /* allocate the RX host descriptor queue pool */
++      adev->rxhostdesc_area_size = RX_CNT * sizeof(*hostdesc);
++      adev->rxhostdesc_start = allocate(adev, adev->rxhostdesc_area_size,
++                      &adev->rxhostdesc_startphy, "rxhostdesc_start");
++      if (!adev->rxhostdesc_start)
++              goto fail;
++      /* check for proper alignment of RX host descriptor pool */
++      if ((long) adev->rxhostdesc_start & 3) {
++              printk("acx: driver bug: dma alloc returns unaligned address\n");
++              goto fail;
++      }
++
++      /* allocate Rx buffer pool which will be used by the acx
++       * to store the whole content of the received frames in it */
++      adev->rxbuf_area_size = RX_CNT * RX_BUFFER_SIZE;
++      adev->rxbuf_start = allocate(adev, adev->rxbuf_area_size,
++                      &adev->rxbuf_startphy, "rxbuf_start");
++      if (!adev->rxbuf_start)
++              goto fail;
++
++      rxbuf = adev->rxbuf_start;
++      rxbuf_phy = adev->rxbuf_startphy;
++      hostdesc = adev->rxhostdesc_start;
++      hostdesc_phy = adev->rxhostdesc_startphy;
++
++      /* don't make any popular C programming pointer arithmetic mistakes
++       * here, otherwise I'll kill you...
++       * (and don't dare asking me why I'm warning you about that...) */
++      for (i = 0; i < RX_CNT; i++) {
++              hostdesc->data = rxbuf;
++              hostdesc->data_phy = cpu2acx(rxbuf_phy);
++              hostdesc->length = cpu_to_le16(RX_BUFFER_SIZE);
++              CLEAR_BIT(hostdesc->Ctl_16, cpu_to_le16(DESC_CTL_HOSTOWN));
++              rxbuf++;
++              rxbuf_phy += sizeof(*rxbuf);
++              hostdesc_phy += sizeof(*hostdesc);
++              hostdesc->desc_phy_next = cpu2acx(hostdesc_phy);
++              hostdesc++;
++      }
++      hostdesc--;
++      hostdesc->desc_phy_next = cpu2acx(adev->rxhostdesc_startphy);
++      FN_EXIT1(OK);
++      return OK;
++fail:
++      printk("acx: create_rx_host_desc_queue FAILED\n");
++      /* dealloc will be done by free function on error case */
++      FN_EXIT1(NOT_OK);
++      return NOT_OK;
++}
++
++
++/***************************************************************
++** acxpci_s_create_hostdesc_queues
++*/
++int
++acxpci_s_create_hostdesc_queues(acx_device_t *adev)
++{
++      int result;
++      result = acxpci_s_create_tx_host_desc_queue(adev);
++      if (OK != result) return result;
++      result = acxpci_s_create_rx_host_desc_queue(adev);
++      return result;
++}
++
++
++/***************************************************************
++** acxpci_create_tx_desc_queue
++*/
++static void
++acxpci_create_tx_desc_queue(acx_device_t *adev, u32 tx_queue_start)
++{
++      txdesc_t *txdesc;
++      txhostdesc_t *hostdesc;
++      dma_addr_t hostmemptr;
++      u32 mem_offs;
++      int i;
++
++      FN_ENTER;
++
++      if (IS_ACX100(adev))
++              adev->txdesc_size = sizeof(*txdesc);
++      else
++              /* the acx111 txdesc is 4 bytes larger */
++              adev->txdesc_size = sizeof(*txdesc) + 4;
++
++      adev->txdesc_start = (txdesc_t *) (adev->iobase2 + tx_queue_start);
++
++      log(L_DEBUG, "adev->iobase2=%p\n"
++                      "tx_queue_start=%08X\n"
++                      "adev->txdesc_start=%p\n",
++                      adev->iobase2,
++                      tx_queue_start,
++                      adev->txdesc_start);
++
++      adev->tx_free = TX_CNT;
++      /* done by memset: adev->tx_head = 0; */
++      /* done by memset: adev->tx_tail = 0; */
++      txdesc = adev->txdesc_start;
++      mem_offs = tx_queue_start;
++      hostmemptr = adev->txhostdesc_startphy;
++      hostdesc = adev->txhostdesc_start;
++
++      if (IS_ACX111(adev)) {
++              /* ACX111 has a preinitialized Tx buffer! */
++              /* loop over whole send pool */
++              /* FIXME: do we have to do the hostmemptr stuff here?? */
++              for (i = 0; i < TX_CNT; i++) {
++                      txdesc->HostMemPtr = ptr2acx(hostmemptr);
++                      txdesc->Ctl_8 = DESC_CTL_HOSTOWN;
++                      /* reserve two (hdr desc and payload desc) */
++                      hostdesc += 2;
++                      hostmemptr += 2 * sizeof(*hostdesc);
++                      txdesc = advance_txdesc(adev, txdesc, 1);
++              }
++      } else {
++              /* ACX100 Tx buffer needs to be initialized by us */
++              /* clear whole send pool. sizeof is safe here (we are acx100) */
++              memset(adev->txdesc_start, 0, TX_CNT * sizeof(*txdesc));
++
++              /* loop over whole send pool */
++              for (i = 0; i < TX_CNT; i++) {
++                      log(L_DEBUG, "configure card tx descriptor: 0x%p, "
++                              "size: 0x%X\n", txdesc, adev->txdesc_size);
++
++                      /* pointer to hostdesc memory */
++                      txdesc->HostMemPtr = ptr2acx(hostmemptr);
++                      /* initialise ctl */
++                      txdesc->Ctl_8 = ( DESC_CTL_HOSTOWN | DESC_CTL_RECLAIM
++                                      | DESC_CTL_AUTODMA | DESC_CTL_FIRSTFRAG);
++                      /* done by memset(0): txdesc->Ctl2_8 = 0; */
++                      /* point to next txdesc */
++                      txdesc->pNextDesc = cpu2acx(mem_offs + adev->txdesc_size);
++                      /* reserve two (hdr desc and payload desc) */
++                      hostdesc += 2;
++                      hostmemptr += 2 * sizeof(*hostdesc);
++                      /* go to the next one */
++                      mem_offs += adev->txdesc_size;
++                      /* ++ is safe here (we are acx100) */
++                      txdesc++;
++              }
++              /* go back to the last one */
++              txdesc--;
++              /* and point to the first making it a ring buffer */
++              txdesc->pNextDesc = cpu2acx(tx_queue_start);
++      }
++      FN_EXIT0;
++}
++
++
++/***************************************************************
++** acxpci_create_rx_desc_queue
++*/
++static void
++acxpci_create_rx_desc_queue(acx_device_t *adev, u32 rx_queue_start)
++{
++      rxdesc_t *rxdesc;
++      u32 mem_offs;
++      int i;
++
++      FN_ENTER;
++
++      /* done by memset: adev->rx_tail = 0; */
++
++      /* ACX111 doesn't need any further config: preconfigures itself.
++       * Simply print ring buffer for debugging */
++      if (IS_ACX111(adev)) {
++              /* rxdesc_start already set here */
++
++              adev->rxdesc_start = (rxdesc_t *) ((u8 *)adev->iobase2 + rx_queue_start);
++
++              rxdesc = adev->rxdesc_start;
++              for (i = 0; i < RX_CNT; i++) {
++                      log(L_DEBUG, "rx descriptor %d @ 0x%p\n", i, rxdesc);
++                      rxdesc = adev->rxdesc_start = (rxdesc_t *)
++                              (adev->iobase2 + acx2cpu(rxdesc->pNextDesc));
++              }
++      } else {
++              /* we didn't pre-calculate rxdesc_start in case of ACX100 */
++              /* rxdesc_start should be right AFTER Tx pool */
++              adev->rxdesc_start = (rxdesc_t *)
++                      ((u8 *) adev->txdesc_start + (TX_CNT * sizeof(txdesc_t)));
++              /* NB: sizeof(txdesc_t) above is valid because we know
++              ** we are in if (acx100) block. Beware of cut-n-pasting elsewhere!
++              ** acx111's txdesc is larger! */
++
++              memset(adev->rxdesc_start, 0, RX_CNT * sizeof(*rxdesc));
++
++              /* loop over whole receive pool */
++              rxdesc = adev->rxdesc_start;
++              mem_offs = rx_queue_start;
++              for (i = 0; i < RX_CNT; i++) {
++                      log(L_DEBUG, "rx descriptor @ 0x%p\n", rxdesc);
++                      rxdesc->Ctl_8 = DESC_CTL_RECLAIM | DESC_CTL_AUTODMA;
++                      /* point to next rxdesc */
++                      rxdesc->pNextDesc = cpu2acx(mem_offs + sizeof(*rxdesc));
++                      /* go to the next one */
++                      mem_offs += sizeof(*rxdesc);
++                      rxdesc++;
++              }
++              /* go to the last one */
++              rxdesc--;
++
++              /* and point to the first making it a ring buffer */
++              rxdesc->pNextDesc = cpu2acx(rx_queue_start);
++      }
++      FN_EXIT0;
++}
++
++
++/***************************************************************
++** acxpci_create_desc_queues
++*/
++void
++acxpci_create_desc_queues(acx_device_t *adev, u32 tx_queue_start, u32 rx_queue_start)
++{
++      acxpci_create_tx_desc_queue(adev, tx_queue_start);
++      acxpci_create_rx_desc_queue(adev, rx_queue_start);
++}
++
++
++/***************************************************************
++** acxpci_s_proc_diag_output
++*/
++char*
++acxpci_s_proc_diag_output(char *p, acx_device_t *adev)
++{
++      const char *rtl, *thd, *ttl;
++      rxhostdesc_t *rxhostdesc;
++      txdesc_t *txdesc;
++      int i;
++
++      FN_ENTER;
++
++      p += sprintf(p, "** Rx buf **\n");
++      rxhostdesc = adev->rxhostdesc_start;
++      if (rxhostdesc) for (i = 0; i < RX_CNT; i++) {
++              rtl = (i == adev->rx_tail) ? " [tail]" : "";
++              if ((rxhostdesc->Ctl_16 & cpu_to_le16(DESC_CTL_HOSTOWN))
++               && (rxhostdesc->Status & cpu_to_le32(DESC_STATUS_FULL)) )
++                      p += sprintf(p, "%02u FULL%s\n", i, rtl);
++              else
++                      p += sprintf(p, "%02u empty%s\n", i, rtl);
++              rxhostdesc++;
++      }
++      p += sprintf(p, "** Tx buf (free %d, Linux netqueue %s) **\n", adev->tx_free,
++                              acx_queue_stopped(adev->ndev) ? "STOPPED" : "running");
++      txdesc = adev->txdesc_start;
++      if (txdesc) for (i = 0; i < TX_CNT; i++) {
++              thd = (i == adev->tx_head) ? " [head]" : "";
++              ttl = (i == adev->tx_tail) ? " [tail]" : "";
++              if (txdesc->Ctl_8 & DESC_CTL_ACXDONE)
++                      p += sprintf(p, "%02u free (%02X)%s%s\n", i, txdesc->Ctl_8, thd, ttl);
++              else
++                      p += sprintf(p, "%02u tx   (%02X)%s%s\n", i, txdesc->Ctl_8, thd, ttl);
++              txdesc = advance_txdesc(adev, txdesc, 1);
++      }
++      p += sprintf(p,
++              "\n"
++              "** PCI data **\n"
++              "txbuf_start %p, txbuf_area_size %u, txbuf_startphy %08llx\n"
++              "txdesc_size %u, txdesc_start %p\n"
++              "txhostdesc_start %p, txhostdesc_area_size %u, txhostdesc_startphy %08llx\n"
++              "rxdesc_start %p\n"
++              "rxhostdesc_start %p, rxhostdesc_area_size %u, rxhostdesc_startphy %08llx\n"
++              "rxbuf_start %p, rxbuf_area_size %u, rxbuf_startphy %08llx\n",
++              adev->txbuf_start, adev->txbuf_area_size,
++                              (unsigned long long)adev->txbuf_startphy,
++              adev->txdesc_size, adev->txdesc_start,
++              adev->txhostdesc_start, adev->txhostdesc_area_size,
++                              (unsigned long long)adev->txhostdesc_startphy,
++              adev->rxdesc_start,
++              adev->rxhostdesc_start, adev->rxhostdesc_area_size,
++                              (unsigned long long)adev->rxhostdesc_startphy,
++              adev->rxbuf_start, adev->rxbuf_area_size,
++                              (unsigned long long)adev->rxbuf_startphy);
++
++      FN_EXIT0;
++      return p;
++}
++
++
++/***********************************************************************
++*/
++int
++acxpci_proc_eeprom_output(char *buf, acx_device_t *adev)
++{
++      char *p = buf;
++      int i;
++
++      FN_ENTER;
++
++      for (i = 0; i < 0x400; i++) {
++              acxpci_read_eeprom_byte(adev, i, p++);
++      }
++
++      FN_EXIT1(p - buf);
++      return p - buf;
++}
++
++
++/***********************************************************************
++*/
++void
++acxpci_set_interrupt_mask(acx_device_t *adev)
++{
++      if (IS_ACX111(adev)) {
++              adev->irq_mask = (u16) ~(0
++                              /* | HOST_INT_RX_DATA        */
++                              | HOST_INT_TX_COMPLETE
++                              /* | HOST_INT_TX_XFER        */
++                              | HOST_INT_RX_COMPLETE
++                              /* | HOST_INT_DTIM           */
++                              /* | HOST_INT_BEACON         */
++                              /* | HOST_INT_TIMER          */
++                              /* | HOST_INT_KEY_NOT_FOUND  */
++                              | HOST_INT_IV_ICV_FAILURE
++                              | HOST_INT_CMD_COMPLETE
++                              | HOST_INT_INFO
++                              /* | HOST_INT_OVERFLOW       */
++                              /* | HOST_INT_PROCESS_ERROR  */
++                              | HOST_INT_SCAN_COMPLETE
++                              | HOST_INT_FCS_THRESHOLD
++                              /* | HOST_INT_UNKNOWN        */
++                              );
++              /* Or else acx100 won't signal cmd completion, right? */
++              adev->irq_mask_off = (u16)~( HOST_INT_CMD_COMPLETE ); /* 0xfdff */
++      } else {
++              adev->irq_mask = (u16) ~(0
++                              /* | HOST_INT_RX_DATA        */
++                              | HOST_INT_TX_COMPLETE
++                              /* | HOST_INT_TX_XFER        */
++                              | HOST_INT_RX_COMPLETE
++                              /* | HOST_INT_DTIM           */
++                              /* | HOST_INT_BEACON         */
++                              /* | HOST_INT_TIMER          */
++                              /* | HOST_INT_KEY_NOT_FOUND  */
++                              /* | HOST_INT_IV_ICV_FAILURE */
++                              | HOST_INT_CMD_COMPLETE
++                              | HOST_INT_INFO
++                              /* | HOST_INT_OVERFLOW       */
++                              /* | HOST_INT_PROCESS_ERROR  */
++                              | HOST_INT_SCAN_COMPLETE
++                              /* | HOST_INT_FCS_THRESHOLD  */
++                              /* | HOST_INT_UNKNOWN        */
++                              );
++              adev->irq_mask_off = (u16)~( HOST_INT_UNKNOWN ); /* 0x7fff */
++      }
++}
++
++
++/***********************************************************************
++*/
++int
++acx100pci_s_set_tx_level(acx_device_t *adev, u8 level_dbm)
++{
++      /* since it can be assumed that at least the Maxim radio has a
++       * maximum power output of 20dBm and since it also can be
++       * assumed that these values drive the DAC responsible for
++       * setting the linear Tx level, I'd guess that these values
++       * should be the corresponding linear values for a dBm value,
++       * in other words: calculate the values from that formula:
++       * Y [dBm] = 10 * log (X [mW])
++       * then scale the 0..63 value range onto the 1..100mW range (0..20 dBm)
++       * and you're done...
++       * Hopefully that's ok, but you never know if we're actually
++       * right... (especially since Windows XP doesn't seem to show
++       * actual Tx dBm values :-P) */
++
++      /* NOTE: on Maxim, value 30 IS 30mW, and value 10 IS 10mW - so the
++       * values are EXACTLY mW!!! Not sure about RFMD and others,
++       * though... */
++      static const u8 dbm2val_maxim[21] = {
++              63, 63, 63, 62,
++              61, 61, 60, 60,
++              59, 58, 57, 55,
++              53, 50, 47, 43,
++              38, 31, 23, 13,
++              0
++      };
++      static const u8 dbm2val_rfmd[21] = {
++               0,  0,  0,  1,
++               2,  2,  3,  3,
++               4,  5,  6,  8,
++              10, 13, 16, 20,
++              25, 32, 41, 50,
++              63
++      };
++      const u8 *table;
++
++      switch (adev->radio_type) {
++      case RADIO_MAXIM_0D:
++              table = &dbm2val_maxim[0];
++              break;
++      case RADIO_RFMD_11:
++      case RADIO_RALINK_15:
++              table = &dbm2val_rfmd[0];
++              break;
++      default:
++              printk("%s: unknown/unsupported radio type, "
++                      "cannot modify tx power level yet!\n",
++                              adev->ndev->name);
++              return NOT_OK;
++      }
++      printk("%s: changing radio power level to %u dBm (%u)\n",
++                      adev->ndev->name, level_dbm, table[level_dbm]);
++      acxpci_s_write_phy_reg(adev, 0x11, table[level_dbm]);
++      return OK;
++}
++
++
++/***********************************************************************
++** Data for init_module/cleanup_module
++*/
++static const struct pci_device_id
++acxpci_id_tbl[] __devinitdata = {
++      {
++              .vendor = PCI_VENDOR_ID_TI,
++              .device = PCI_DEVICE_ID_TI_TNETW1100A,
++              .subvendor = PCI_ANY_ID,
++              .subdevice = PCI_ANY_ID,
++              .driver_data = CHIPTYPE_ACX100,
++      },
++      {
++              .vendor = PCI_VENDOR_ID_TI,
++              .device = PCI_DEVICE_ID_TI_TNETW1100B,
++              .subvendor = PCI_ANY_ID,
++              .subdevice = PCI_ANY_ID,
++              .driver_data = CHIPTYPE_ACX100,
++      },
++      {
++              .vendor = PCI_VENDOR_ID_TI,
++              .device = PCI_DEVICE_ID_TI_TNETW1130,
++              .subvendor = PCI_ANY_ID,
++              .subdevice = PCI_ANY_ID,
++              .driver_data = CHIPTYPE_ACX111,
++      },
++      {
++              .vendor = 0,
++              .device = 0,
++              .subvendor = 0,
++              .subdevice = 0,
++              .driver_data = 0,
++      }
++};
++
++MODULE_DEVICE_TABLE(pci, acxpci_id_tbl);
++
++/* FIXME: checks should be removed once driver is included in the kernel */
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11)
++/* pci_name() got introduced at start of 2.6.x,
++ * got mandatory (slot_name member removed) in 2.6.11-bk1 */
++#define pci_name(x) x->slot_name
++#endif
++
++static struct pci_driver
++acxpci_drv_id = {
++      .name        = "acx_pci",
++      .id_table    = acxpci_id_tbl,
++      .probe       = acxpci_e_probe,
++      .remove      = __devexit_p(acxpci_e_remove),
++#ifdef CONFIG_PM
++      .suspend     = acxpci_e_suspend,
++      .resume      = acxpci_e_resume
++#endif /* CONFIG_PM */
++};
++
++
++/***********************************************************************
++** acxpci_e_init_module
++**
++** Module initialization routine, called once at module load time
++*/
++int __init
++acxpci_e_init_module(void)
++{
++      int res;
++
++      FN_ENTER;
++
++#if (ACX_IO_WIDTH==32)
++      printk("acx: compiled to use 32bit I/O access. "
++              "I/O timing issues might occur, such as "
++              "non-working firmware upload. Report them\n");
++#else
++      printk("acx: compiled to use 16bit I/O access only "
++              "(compatibility mode)\n");
++#endif
++
++#ifdef __LITTLE_ENDIAN
++#define ENDIANNESS_STRING "running on a little-endian CPU\n"
++#else
++#define ENDIANNESS_STRING "running on a BIG-ENDIAN CPU\n"
++#endif
++      log(L_INIT,
++              ENDIANNESS_STRING
++              "PCI module " ACX_RELEASE " initialized, "
++              "waiting for cards to probe...\n"
++      );
++
++      res = pci_register_driver(&acxpci_drv_id);
++      FN_EXIT1(res);
++      return res;
++}
++
++
++/***********************************************************************
++** acxpci_e_cleanup_module
++**
++** Called at module unload time. This is our last chance to
++** clean up after ourselves.
++*/
++void __exit
++acxpci_e_cleanup_module(void)
++{
++      FN_ENTER;
++
++      pci_unregister_driver(&acxpci_drv_id);
++
++      FN_EXIT0;
++}
+Index: linux-2.6.22/drivers/net/wireless/acx/rx3000_acx.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/drivers/net/wireless/acx/rx3000_acx.c 2007-08-23 18:34:19.000000000 +0200
+@@ -0,0 +1,110 @@
++/*
++ * WLAN (TI TNETW1100B) support in the HP iPAQ RX3000
++ *
++ * Copyright (c) 2006 SDG Systems, LLC
++ * Copyright (c) 2006 Roman Moravcik
++ *
++ * 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.
++ *
++ * Based on hx4700_acx.c
++ */
++
++
++#include <linux/kernel.h>
++#include <linux/platform_device.h>
++#include <linux/delay.h>
++#include <linux/dpm.h>
++#include <linux/leds.h>
++
++#include <asm/hardware.h>
++
++#include <asm/arch/regs-gpio.h>
++#include <linux/mfd/asic3_base.h>
++#include <asm/arch/rx3000.h>
++#include <asm/arch/rx3000-asic3.h>
++#include <asm/io.h>
++
++#include "acx_hw.h"
++
++extern struct platform_device s3c_device_asic3;
++
++static int rx3000_wlan_start(void)
++{
++      DPM_DEBUG("rx3000_acx: Turning on\n");
++      asic3_set_gpio_out_b(&s3c_device_asic3.dev, ASIC3_GPB3, ASIC3_GPB3);
++      mdelay(20);
++      asic3_set_gpio_out_c(&s3c_device_asic3.dev, ASIC3_GPC13, ASIC3_GPC13);
++      mdelay(20);
++      asic3_set_gpio_out_c(&s3c_device_asic3.dev, ASIC3_GPC11, ASIC3_GPC11);
++      mdelay(100);
++      asic3_set_gpio_out_b(&s3c_device_asic3.dev, ASIC3_GPB3, ASIC3_GPB3);
++      mdelay(20);
++      s3c2410_gpio_cfgpin(S3C2410_GPA15, S3C2410_GPA15_nGCS4);        
++      mdelay(100);
++      s3c2410_gpio_setpin(S3C2410_GPA11, 0);
++      mdelay(50);
++      s3c2410_gpio_setpin(S3C2410_GPA11, 1);
++      led_trigger_event_shared(rx3000_radio_trig, LED_FULL);
++      return 0;
++}
++
++static int rx3000_wlan_stop(void)
++{
++      DPM_DEBUG("rx3000_acx: Turning off\n");
++      s3c2410_gpio_setpin(S3C2410_GPA15, 1);
++      s3c2410_gpio_cfgpin(S3C2410_GPA15, S3C2410_GPA15_OUT);
++      asic3_set_gpio_out_b(&s3c_device_asic3.dev, ASIC3_GPB3, 0);
++      asic3_set_gpio_out_c(&s3c_device_asic3.dev, ASIC3_GPC13, 0);
++      asic3_set_gpio_out_c(&s3c_device_asic3.dev, ASIC3_GPC11, 0);
++      led_trigger_event_shared(rx3000_radio_trig, LED_OFF);
++      return 0;
++}
++
++static struct resource acx_resources[] = {
++      [0] = {
++              .start  = RX3000_PA_WLAN,
++              .end    = RX3000_PA_WLAN + 0x20,
++              .flags  = IORESOURCE_MEM,
++      },
++      [1] = {
++              .start  = IRQ_EINT16,
++              .end    = IRQ_EINT16,
++              .flags  = IORESOURCE_IRQ,
++      },
++};
++
++static struct acx_hardware_data acx_data = {
++      .start_hw       = rx3000_wlan_start,
++      .stop_hw        = rx3000_wlan_stop,
++};
++
++static struct platform_device acx_device = {
++      .name   = "acx-mem",
++      .dev    = {
++              .platform_data = &acx_data,
++      },
++      .num_resources  = ARRAY_SIZE(acx_resources),
++      .resource       = acx_resources,
++};
++
++static int __init rx3000_wlan_init(void)
++{
++      printk("rx3000_wlan_init: acx-mem platform_device_register\n");
++      return platform_device_register(&acx_device);
++}
++
++
++static void __exit rx3000_wlan_exit(void)
++{
++      platform_device_unregister(&acx_device);
++}
++
++module_init(rx3000_wlan_init);
++module_exit(rx3000_wlan_exit);
++
++MODULE_AUTHOR("Todd Blumer <todd@sdgsystems.com>, Roman Moravcik <roman.moravcik@gmail.com>");
++MODULE_DESCRIPTION("WLAN driver for HP iPAQ RX3000");
++MODULE_LICENSE("GPL");
++
+Index: linux-2.6.22/drivers/net/wireless/acx/setrate.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/drivers/net/wireless/acx/setrate.c    2007-08-23 18:34:19.000000000 +0200
+@@ -0,0 +1,213 @@
++/* TODO: stop #including, move into wireless.c
++ * until then, keep in sync copies in prism54/ and acx/ dirs
++ * code+data size: less than 1k */
++
++enum {
++      DOT11_RATE_1,
++      DOT11_RATE_2,
++      DOT11_RATE_5,
++      DOT11_RATE_11,
++      DOT11_RATE_22,
++      DOT11_RATE_33,
++      DOT11_RATE_6,
++      DOT11_RATE_9,
++      DOT11_RATE_12,
++      DOT11_RATE_18,
++      DOT11_RATE_24,
++      DOT11_RATE_36,
++      DOT11_RATE_48,
++      DOT11_RATE_54
++};
++enum {
++      DOT11_MOD_DBPSK,
++      DOT11_MOD_DQPSK,
++      DOT11_MOD_CCK,
++      DOT11_MOD_OFDM,
++      DOT11_MOD_CCKOFDM,
++      DOT11_MOD_PBCC
++};
++static const u8 ratelist[] = { 1,2,5,11,22,33,6,9,12,18,24,36,48,54 };
++static const u8 dot11ratebyte[] = { 1*2,2*2,11,11*2,22*2,33*2,6*2,9*2,12*2,18*2,24*2,36*2,48*2,54*2 };
++static const u8 default_modulation[] = {
++      DOT11_MOD_DBPSK,
++      DOT11_MOD_DQPSK,
++      DOT11_MOD_CCK,
++      DOT11_MOD_CCK,
++      DOT11_MOD_PBCC,
++      DOT11_MOD_PBCC,
++      DOT11_MOD_OFDM,
++      DOT11_MOD_OFDM,
++      DOT11_MOD_OFDM,
++      DOT11_MOD_OFDM,
++      DOT11_MOD_OFDM,
++      DOT11_MOD_OFDM,
++      DOT11_MOD_OFDM,
++      DOT11_MOD_OFDM
++};
++
++static /* TODO: remove 'static' when moved to wireless.c */
++int
++rate_mbit2enum(int n) {
++      int i=0;
++      while(i<sizeof(ratelist)) {
++              if(n==ratelist[i]) return i;
++              i++;
++      }
++      return -EINVAL;
++}
++
++static int
++get_modulation(int r_enum, char suffix) {
++      if(suffix==',' || suffix==' ' || suffix=='\0') {
++              /* could shorten default_mod by 8 bytes:
++              if(r_enum>=DOT11_RATE_6) return DOT11_MOD_OFDM; */
++              return default_modulation[r_enum];
++      }
++      if(suffix=='c') {
++              if(r_enum<DOT11_RATE_5 || r_enum>DOT11_RATE_11) return -EINVAL;
++              return DOT11_MOD_CCK;
++      }
++      if(suffix=='p') {
++              if(r_enum<DOT11_RATE_5 || r_enum>DOT11_RATE_33) return -EINVAL;
++              return DOT11_MOD_PBCC;
++      }
++      if(suffix=='o') {
++              if(r_enum<DOT11_RATE_6) return -EINVAL;
++              return DOT11_MOD_OFDM;
++      }
++      if(suffix=='d') {
++              if(r_enum<DOT11_RATE_6) return -EINVAL;
++              return DOT11_MOD_CCKOFDM;
++      }
++      return -EINVAL;
++}
++
++#ifdef UNUSED
++static int
++fill_ratevector(const char **pstr, u8 *vector, int size,
++              int (*supported)(int mbit, int mod, void *opaque), void *opaque, int or_mask)
++{
++      unsigned long rate_mbit;
++      int rate_enum,mod;
++      const char *str = *pstr;
++      char c;
++
++      do {
++              rate_mbit = simple_strtoul(str, (char**)&str, 10);
++              if(rate_mbit>INT_MAX) return -EINVAL;
++
++              rate_enum = rate_mbit2enum(rate_mbit);
++              if(rate_enum<0) return rate_enum;
++
++              c = *str;
++              mod = get_modulation(rate_enum, c);
++              if(mod<0) return mod;
++
++              if(c>='a' && c<='z') c = *++str;
++              if(c!=',' && c!=' ' && c!='\0') return -EINVAL;
++
++              if(supported) {
++                      int r = supported(rate_mbit, mod, opaque);
++                      if(r) return r;
++              }
++
++              *vector++ = dot11ratebyte[rate_enum] | or_mask;
++
++              size--;
++              str++;
++      } while(size>0 && c==',');
++
++      if(size<1) return -E2BIG;
++      *vector=0; /* TODO: sort, remove dups? */
++
++      *pstr = str-1;
++      return 0;
++}
++
++static /* TODO: remove 'static' when moved to wireless.c */
++int
++fill_ratevectors(const char *str, u8 *brate, u8 *orate, int size,
++              int (*supported)(int mbit, int mod, void *opaque), void *opaque)
++{
++      int r;
++
++      r = fill_ratevector(&str, brate, size, supported, opaque, 0x80);
++      if(r) return r;
++
++      orate[0] = 0;
++      if(*str==' ') {
++              str++;
++              r = fill_ratevector(&str, orate, size, supported, opaque, 0);
++              if(r) return r;
++              /* TODO: sanitize, e.g. remove/error on rates already in basic rate set? */
++      }
++      if(*str)
++              return -EINVAL;
++
++      return 0;
++}
++#endif
++
++/* TODO: use u64 masks? */
++
++static int
++fill_ratemask(const char **pstr, u32* mask,
++              int (*supported)(int mbit, int mod,void *opaque),
++              u32 (*gen_mask)(int mbit, int mod,void *opaque),
++              void *opaque)
++{
++      unsigned long rate_mbit;
++      int rate_enum,mod;
++      u32 m = 0;
++      const char *str = *pstr;
++      char c;
++
++      do {
++              rate_mbit = simple_strtoul(str, (char**)&str, 10);
++              if(rate_mbit>INT_MAX) return -EINVAL;
++
++              rate_enum = rate_mbit2enum(rate_mbit);
++              if(rate_enum<0) return rate_enum;
++
++              c = *str;
++              mod = get_modulation(rate_enum, c);
++              if(mod<0) return mod;
++
++              if(c>='a' && c<='z') c = *++str;
++              if(c!=',' && c!=' ' && c!='\0') return -EINVAL;
++
++              if(supported) {
++                      int r = supported(rate_mbit, mod, opaque);
++                      if(r) return r;
++              }
++
++              m |= gen_mask(rate_mbit, mod, opaque);
++              str++;
++      } while(c==',');
++
++      *pstr = str-1;
++      *mask |= m;
++      return 0;
++}
++
++static /* TODO: remove 'static' when moved to wireless.c */
++int
++fill_ratemasks(const char *str, u32 *bmask, u32 *omask,
++              int (*supported)(int mbit, int mod,void *opaque),
++              u32 (*gen_mask)(int mbit, int mod,void *opaque),
++              void *opaque)
++{
++      int r;
++
++      r = fill_ratemask(&str, bmask, supported, gen_mask, opaque);
++      if(r) return r;
++
++      if(*str==' ') {
++              str++;
++              r = fill_ratemask(&str, omask, supported, gen_mask, opaque);
++              if(r) return r;
++      }
++      if(*str)
++              return -EINVAL;
++      return 0;
++}
+Index: linux-2.6.22/drivers/net/wireless/acx/usb.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/drivers/net/wireless/acx/usb.c        2007-08-23 18:34:19.000000000 +0200
+@@ -0,0 +1,1922 @@
++/***********************************************************************
++** Copyright (C) 2003  ACX100 Open Source Project
++**
++** The contents of this file are subject to the Mozilla Public
++** License Version 1.1 (the "License"); you may not use this file
++** except in compliance with the License. You may obtain a copy of
++** the License at http://www.mozilla.org/MPL/
++**
++** Software distributed under the License is distributed on an "AS
++** IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
++** implied. See the License for the specific language governing
++** rights and limitations under the License.
++**
++** Alternatively, the contents of this file may be used under the
++** terms of the GNU Public License version 2 (the "GPL"), in which
++** case the provisions of the GPL are applicable instead of the
++** above.  If you wish to allow the use of your version of this file
++** only under the terms of the GPL and not to allow others to use
++** your version of this file under the MPL, indicate your decision
++** by deleting the provisions above and replace them with the notice
++** and other provisions required by the GPL.  If you do not delete
++** the provisions above, a recipient may use your version of this
++** file under either the MPL or the GPL.
++** ---------------------------------------------------------------------
++** Inquiries regarding the ACX100 Open Source Project can be
++** made directly to:
++**
++** acx100-users@lists.sf.net
++** http://acx100.sf.net
++** ---------------------------------------------------------------------
++*/
++
++/***********************************************************************
++** USB support for TI ACX100 based devices. Many parts are taken from
++** the PCI driver.
++**
++** Authors:
++**  Martin Wawro <martin.wawro AT uni-dortmund.de>
++**  Andreas Mohr <andi AT lisas.de>
++**
++** LOCKING
++** callback functions called by USB core are running in interrupt context
++** and thus have names with _i_.
++*/
++#define ACX_USB 1
++
++#include <linux/version.h>
++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18)
++#include <linux/config.h>
++#endif
++#include <linux/types.h>
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/kernel.h>
++#include <linux/usb.h>
++#include <linux/netdevice.h>
++#include <linux/rtnetlink.h>
++#include <linux/etherdevice.h>
++#include <linux/wireless.h>
++#include <net/iw_handler.h>
++#include <linux/vmalloc.h>
++
++#include "acx.h"
++
++
++/***********************************************************************
++*/
++/* number of endpoints of an interface */
++#define NUM_EP(intf) (intf)->altsetting[0].desc.bNumEndpoints
++#define EP(intf, nr) (intf)->altsetting[0].endpoint[(nr)].desc
++#define GET_DEV(udev) usb_get_dev((udev))
++#define PUT_DEV(udev) usb_put_dev((udev))
++#define SET_NETDEV_OWNER(ndev, owner) /* not needed anymore ??? */
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14)
++/* removed in 2.6.14. We will use fake value for now */
++#define URB_ASYNC_UNLINK 0
++#endif
++
++
++/***********************************************************************
++*/
++/* ACX100 (TNETW1100) USB device: D-Link DWL-120+ */
++#define ACX100_VENDOR_ID 0x2001
++#define ACX100_PRODUCT_ID_UNBOOTED 0x3B01
++#define ACX100_PRODUCT_ID_BOOTED 0x3B00
++
++/* TNETW1450 USB devices */
++#define VENDOR_ID_DLINK               0x07b8 /* D-Link Corp. */
++#define PRODUCT_ID_WUG2400    0xb21a /* AboCom WUG2400 or SafeCom SWLUT-54125 */
++#define VENDOR_ID_AVM_GMBH    0x057c
++#define PRODUCT_ID_AVM_WLAN_USB       0x5601
++#define PRODUCT_ID_AVM_WLAN_USB_si    0x6201 /* "self install" named Version: driver kills kernel on inbound scans from fritz box ???  */
++#define VENDOR_ID_ZCOM                0x0cde
++#define PRODUCT_ID_ZCOM_XG750 0x0017 /* not tested yet */
++#define VENDOR_ID_TI          0x0451
++#define PRODUCT_ID_TI_UNKNOWN 0x60c5 /* not tested yet */
++
++#define ACX_USB_CTRL_TIMEOUT  5500   /* steps in ms */
++
++/* Buffer size for fw upload, same for both ACX100 USB and TNETW1450 */
++#define USB_RWMEM_MAXLEN      2048
++
++/* The number of bulk URBs to use */
++#define ACX_TX_URB_CNT                8
++#define ACX_RX_URB_CNT                2
++
++/* Should be sent to the bulkout endpoint */
++#define ACX_USB_REQ_UPLOAD_FW 0x10
++#define ACX_USB_REQ_ACK_CS    0x11
++#define ACX_USB_REQ_CMD               0x12
++
++/***********************************************************************
++** Prototypes
++*/
++static int acxusb_e_probe(struct usb_interface *, const struct usb_device_id *);
++static void acxusb_e_disconnect(struct usb_interface *);
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
++static void acxusb_i_complete_tx(struct urb *);
++static void acxusb_i_complete_rx(struct urb *);
++#else
++static void acxusb_i_complete_tx(struct urb *, struct pt_regs *);
++static void acxusb_i_complete_rx(struct urb *, struct pt_regs *);
++#endif
++static int acxusb_e_open(struct net_device *);
++static int acxusb_e_close(struct net_device *);
++static void acxusb_i_set_rx_mode(struct net_device *);
++static int acxusb_boot(struct usb_device *, int is_tnetw1450, int *radio_type);
++
++static void acxusb_l_poll_rx(acx_device_t *adev, usb_rx_t* rx);
++
++static void acxusb_i_tx_timeout(struct net_device *);
++
++/* static void dump_device(struct usb_device *); */
++/* static void dump_device_descriptor(struct usb_device_descriptor *); */
++/* static void dump_config_descriptor(struct usb_config_descriptor *); */
++
++/***********************************************************************
++** Module Data
++*/
++#define TXBUFSIZE sizeof(usb_txbuffer_t)
++/*
++ * Now, this is just plain lying, but the device insists in giving us
++ * huge packets. We supply extra space after rxbuffer. Need to understand
++ * it better...
++ */
++#define RXBUFSIZE (sizeof(rxbuffer_t) + \
++                 (sizeof(usb_rx_t) - sizeof(struct usb_rx_plain)))
++
++static const struct usb_device_id
++acxusb_ids[] = {
++      { USB_DEVICE(ACX100_VENDOR_ID, ACX100_PRODUCT_ID_BOOTED) },
++      { USB_DEVICE(ACX100_VENDOR_ID, ACX100_PRODUCT_ID_UNBOOTED) },
++      { USB_DEVICE(VENDOR_ID_DLINK, PRODUCT_ID_WUG2400) },
++      { USB_DEVICE(VENDOR_ID_AVM_GMBH, PRODUCT_ID_AVM_WLAN_USB) },
++      { USB_DEVICE(VENDOR_ID_AVM_GMBH, PRODUCT_ID_AVM_WLAN_USB_si) },
++      { USB_DEVICE(VENDOR_ID_ZCOM, PRODUCT_ID_ZCOM_XG750) },
++      { USB_DEVICE(VENDOR_ID_TI, PRODUCT_ID_TI_UNKNOWN) },
++      {}
++};
++
++MODULE_DEVICE_TABLE(usb, acxusb_ids);
++
++/* USB driver data structure as required by the kernel's USB core */
++static struct usb_driver
++acxusb_driver = {
++      .name = "acx_usb",
++      .probe = acxusb_e_probe,
++      .disconnect = acxusb_e_disconnect,
++      .id_table = acxusb_ids
++};
++
++
++/***********************************************************************
++** USB helper
++**
++** ldd3 ch13 says:
++** When the function is usb_kill_urb, the urb lifecycle is stopped. This
++** function is usually used when the device is disconnected from the system,
++** in the disconnect callback. For some drivers, the usb_unlink_urb function
++** should be used to tell the USB core to stop an urb. This function does not
++** wait for the urb to be fully stopped before returning to the caller.
++** This is useful for stoppingthe urb while in an interrupt handler or when
++** a spinlock is held, as waiting for a urb to fully stop requires the ability
++** for the USB core to put the calling process to sleep. This function requires
++** that the URB_ASYNC_UNLINK flag value be set in the urb that is being asked
++** to be stopped in order to work properly.
++**
++** (URB_ASYNC_UNLINK is obsolete, usb_unlink_urb will always be
++** asynchronous while usb_kill_urb is synchronous and should be called
++** directly (drivers/usb/core/urb.c))
++**
++** In light of this, timeout is just for paranoid reasons...
++*
++* Actually, it's useful for debugging. If we reach timeout, we're doing
++* something wrong with the urbs.
++*/
++static void
++acxusb_unlink_urb(struct urb* urb)
++{
++      if (!urb)
++              return;
++
++      if (urb->status == -EINPROGRESS) {
++              int timeout = 10;
++
++              usb_unlink_urb(urb);
++              while (--timeout && urb->status == -EINPROGRESS) {
++                      mdelay(1);
++              }
++              if (!timeout) {
++                      printk("acx_usb: urb unlink timeout!\n");
++              }
++      }
++}
++
++
++/***********************************************************************
++** EEPROM and PHY read/write helpers
++*/
++/***********************************************************************
++** acxusb_s_read_phy_reg
++*/
++int
++acxusb_s_read_phy_reg(acx_device_t *adev, u32 reg, u8 *charbuf)
++{
++      /* mem_read_write_t mem; */
++
++      FN_ENTER;
++
++      printk("%s doesn't seem to work yet, disabled.\n", __func__);
++
++      /*
++      mem.addr = cpu_to_le16(reg);
++      mem.type = cpu_to_le16(0x82);
++      mem.len = cpu_to_le32(4);
++      acx_s_issue_cmd(adev, ACX1xx_CMD_MEM_READ, &mem, sizeof(mem));
++      *charbuf = mem.data;
++      log(L_DEBUG, "read radio PHY[0x%04X]=0x%02X\n", reg, *charbuf);
++      */
++
++      FN_EXIT1(OK);
++      return OK;
++}
++
++
++/***********************************************************************
++*/
++int
++acxusb_s_write_phy_reg(acx_device_t *adev, u32 reg, u8 value)
++{
++      mem_read_write_t mem;
++
++      FN_ENTER;
++
++      mem.addr = cpu_to_le16(reg);
++      mem.type = cpu_to_le16(0x82);
++      mem.len = cpu_to_le32(4);
++      mem.data = value;
++      acx_s_issue_cmd(adev, ACX1xx_CMD_MEM_WRITE, &mem, sizeof(mem));
++      log(L_DEBUG, "write radio PHY[0x%04X]=0x%02X\n", reg, value);
++
++      FN_EXIT1(OK);
++      return OK;
++}
++
++
++/***********************************************************************
++** acxusb_s_issue_cmd_timeo
++** Excecutes a command in the command mailbox
++**
++** buffer = a pointer to the data.
++** The data must not include 4 byte command header
++*/
++
++/* TODO: ideally we shall always know how much we need
++** and this shall be 0 */
++#define BOGUS_SAFETY_PADDING 0x40
++
++#undef FUNC
++#define FUNC "issue_cmd"
++
++#if !ACX_DEBUG
++int
++acxusb_s_issue_cmd_timeo(
++      acx_device_t *adev,
++      unsigned cmd,
++      void *buffer,
++      unsigned buflen,
++      unsigned timeout)
++{
++#else
++int
++acxusb_s_issue_cmd_timeo_debug(
++      acx_device_t *adev,
++      unsigned cmd,
++      void *buffer,
++      unsigned buflen,
++      unsigned timeout,
++      const char* cmdstr)
++{
++#endif
++      /* USB ignores timeout param */
++
++      struct usb_device *usbdev;
++      struct {
++              u16     cmd;
++              u16     status;
++              u8      data[1];
++      } ACX_PACKED *loc;
++      const char *devname;
++      int acklen, blocklen, inpipe, outpipe;
++      int cmd_status;
++      int result;
++
++      FN_ENTER;
++
++      devname = adev->ndev->name;
++      /* no "wlan%%d: ..." please */
++      if (!devname || !devname[0] || devname[4]=='%')
++              devname = "acx";
++
++      log(L_CTL, FUNC"(cmd:%s,buflen:%u,type:0x%04X)\n",
++              cmdstr, buflen,
++              buffer ? le16_to_cpu(((acx_ie_generic_t *)buffer)->type) : -1);
++
++      loc = kmalloc(buflen + 4 + BOGUS_SAFETY_PADDING, GFP_KERNEL);
++      if (!loc) {
++              printk("%s: "FUNC"(): no memory for data buffer\n", devname);
++              goto bad;
++      }
++
++      /* get context from acx_device */
++      usbdev = adev->usbdev;
++
++      /* check which kind of command was issued */
++      loc->cmd = cpu_to_le16(cmd);
++      loc->status = 0;
++
++/* NB: buflen == frmlen + 4
++**
++** Interrogate: write 8 bytes: (cmd,status,rid,frmlen), then
++**            read (cmd,status,rid,frmlen,data[frmlen]) back
++**
++** Configure: write (cmd,status,rid,frmlen,data[frmlen])
++**
++** Possibly bogus special handling of ACX1xx_IE_SCAN_STATUS removed
++*/
++
++      /* now write the parameters of the command if needed */
++      acklen = buflen + 4 + BOGUS_SAFETY_PADDING;
++      blocklen = buflen;
++      if (buffer && buflen) {
++              /* if it's an INTERROGATE command, just pass the length
++               * of parameters to read, as data */
++              if (cmd == ACX1xx_CMD_INTERROGATE) {
++                      blocklen = 4;
++                      acklen = buflen + 4;
++              }
++              memcpy(loc->data, buffer, blocklen);
++      }
++      blocklen += 4; /* account for cmd,status */
++
++      /* obtain the I/O pipes */
++      outpipe = usb_sndctrlpipe(usbdev, 0);
++      inpipe = usb_rcvctrlpipe(usbdev, 0);
++      log(L_CTL, "ctrl inpipe=0x%X outpipe=0x%X\n", inpipe, outpipe);
++      log(L_CTL, "sending USB control msg (out) (blocklen=%d)\n", blocklen);
++      if (acx_debug & L_DATA)
++              acx_dump_bytes(loc, blocklen);
++
++      result = usb_control_msg(usbdev, outpipe,
++              ACX_USB_REQ_CMD, /* request */
++              USB_TYPE_VENDOR|USB_DIR_OUT, /* requesttype */
++              0, /* value */
++              0, /* index */
++              loc, /* dataptr */
++              blocklen, /* size */
++              ACX_USB_CTRL_TIMEOUT /* timeout in ms */
++      );
++
++      if (result == -ENODEV) {
++              log(L_CTL, "no device present (unplug?)\n");
++              goto good;
++      }
++
++      log(L_CTL, "wrote %d bytes\n", result);
++      if (result < 0) {
++              goto bad;
++      }
++
++      /* check for device acknowledge */
++      log(L_CTL, "sending USB control msg (in) (acklen=%d)\n", acklen);
++      loc->status = 0; /* delete old status flag -> set to IDLE */
++      /* shall we zero out the rest? */
++      result = usb_control_msg(usbdev, inpipe,
++              ACX_USB_REQ_CMD, /* request */
++              USB_TYPE_VENDOR|USB_DIR_IN, /* requesttype */
++              0, /* value */
++              0, /* index */
++              loc, /* dataptr */
++              acklen, /* size */
++              ACX_USB_CTRL_TIMEOUT /* timeout in ms */
++      );
++      if (result < 0) {
++              printk("%s: "FUNC"(): USB read error %d\n", devname, result);
++              goto bad;
++      }
++      if (acx_debug & L_CTL) {
++              printk("read %d bytes: ", result);
++              acx_dump_bytes(loc, result);
++      }
++
++/*
++   check for result==buflen+4? Was seen:
++
++interrogate(type:ACX100_IE_DOT11_ED_THRESHOLD,len:4)
++issue_cmd(cmd:ACX1xx_CMD_INTERROGATE,buflen:8,type:4111)
++ctrl inpipe=0x80000280 outpipe=0x80000200
++sending USB control msg (out) (blocklen=8)
++01 00 00 00 0F 10 04 00
++wrote 8 bytes
++sending USB control msg (in) (acklen=12) sizeof(loc->data
++read 4 bytes <==== MUST BE 12!!
++*/
++
++      cmd_status = le16_to_cpu(loc->status);
++      if (cmd_status != 1) {
++              printk("%s: "FUNC"(): cmd_status is not SUCCESS: %d (%s)\n",
++                      devname, cmd_status, acx_cmd_status_str(cmd_status));
++              /* TODO: goto bad; ? */
++      }
++      if ((cmd == ACX1xx_CMD_INTERROGATE) && buffer && buflen) {
++              memcpy(buffer, loc->data, buflen);
++              log(L_CTL, "response frame: cmd=0x%04X status=%d\n",
++                      le16_to_cpu(loc->cmd),
++                      cmd_status);
++      }
++good:
++      kfree(loc);
++      FN_EXIT1(OK);
++      return OK;
++bad:
++      /* Give enough info so that callers can avoid
++      ** printing their own diagnostic messages */
++#if ACX_DEBUG
++      printk("%s: "FUNC"(cmd:%s) FAILED\n", devname, cmdstr);
++#else
++      printk("%s: "FUNC"(cmd:0x%04X) FAILED\n", devname, cmd);
++#endif
++      dump_stack();
++      kfree(loc);
++      FN_EXIT1(NOT_OK);
++      return NOT_OK;
++}
++
++
++/***********************************************************************
++** acxusb_boot()
++** Inputs:
++**    usbdev -> Pointer to kernel's usb_device structure
++**
++** Returns:
++**  (int) Errorcode or 0 on success
++**
++** This function triggers the loading of the firmware image from harddisk
++** and then uploads the firmware to the USB device. After uploading the
++** firmware and transmitting the checksum, the device resets and appears
++** as a new device on the USB bus (the device we can finally deal with)
++*/
++static inline int
++acxusb_fw_needs_padding(firmware_image_t *fw_image, unsigned int usb_maxlen)
++{
++      unsigned int num_xfers = ((fw_image->size - 1) / usb_maxlen) + 1;
++
++      return ((num_xfers % 2) == 0);
++}
++
++static int
++acxusb_boot(struct usb_device *usbdev, int is_tnetw1450, int *radio_type)
++{
++      char filename[sizeof("tiacx1NNusbcRR")];
++
++      firmware_image_t *fw_image = NULL;
++      char *usbbuf;
++      unsigned int offset;
++      unsigned int blk_len, inpipe, outpipe;
++      u32 num_processed;
++      u32 img_checksum, sum;
++      u32 file_size;
++      int result = -EIO;
++      int i;
++
++      FN_ENTER;
++
++      /* dump_device(usbdev); */
++
++      usbbuf = kmalloc(USB_RWMEM_MAXLEN, GFP_KERNEL);
++      if (!usbbuf) {
++              printk(KERN_ERR "acx: no memory for USB transfer buffer (%d bytes)\n", USB_RWMEM_MAXLEN);
++              result = -ENOMEM;
++              goto end;
++      }
++      if (is_tnetw1450) {
++              /* Obtain the I/O pipes */
++              outpipe = usb_sndbulkpipe(usbdev, 1);
++              inpipe = usb_rcvbulkpipe(usbdev, 2);
++
++              printk(KERN_DEBUG "wait for device ready\n");
++              for (i = 0; i <= 2; i++) {
++                      result = usb_bulk_msg(usbdev, inpipe,
++                              usbbuf,
++                              USB_RWMEM_MAXLEN,
++                              &num_processed,
++                              2000
++                              );
++
++                      if ((*(u32 *)&usbbuf[4] == 0x40000001)
++                      && (*(u16 *)&usbbuf[2] == 0x1)
++                      && ((*(u16 *)usbbuf & 0x3fff) == 0)
++                      && ((*(u16 *)usbbuf & 0xc000) == 0xc000))
++                              break;
++                      msleep(10);
++              }
++              if (i == 2)
++                      goto fw_end;
++
++              *radio_type = usbbuf[8];
++      } else {
++              /* Obtain the I/O pipes */
++              outpipe = usb_sndctrlpipe(usbdev, 0);
++              inpipe = usb_rcvctrlpipe(usbdev, 0);
++
++              /* FIXME: shouldn't be hardcoded */
++              *radio_type = RADIO_MAXIM_0D;
++      }
++
++      snprintf(filename, sizeof(filename), "tiacx1%02dusbc%02X",
++                              is_tnetw1450 * 11, *radio_type);
++
++      fw_image = acx_s_read_fw(&usbdev->dev, filename, &file_size);
++      if (!fw_image) {
++              result = -EIO;
++              goto end;
++      }
++      log(L_INIT, "firmware size: %d bytes\n", file_size);
++
++      img_checksum = le32_to_cpu(fw_image->chksum);
++
++      if (is_tnetw1450) {
++              u8 cmdbuf[20];
++              const u8 *p;
++              u8 need_padding;
++              u32 tmplen, val;
++
++              memset(cmdbuf, 0, 16);
++
++              need_padding = acxusb_fw_needs_padding(fw_image, USB_RWMEM_MAXLEN);
++              tmplen = need_padding ? file_size-4 : file_size-8;
++              *(u16 *)&cmdbuf[0] = 0xc000;
++              *(u16 *)&cmdbuf[2] = 0x000b;
++              *(u32 *)&cmdbuf[4] = tmplen;
++              *(u32 *)&cmdbuf[8] = file_size-8;
++              *(u32 *)&cmdbuf[12] = img_checksum;
++
++              result = usb_bulk_msg(usbdev, outpipe, cmdbuf, 16, &num_processed, HZ);
++              if (result < 0)
++                      goto fw_end;
++
++              p = (const u8 *)&fw_image->size;
++
++              /* first calculate checksum for image size part */
++              sum = p[0]+p[1]+p[2]+p[3];
++              p += 4;
++
++              /* now continue checksum for firmware data part */
++              tmplen = le32_to_cpu(fw_image->size);
++              for (i = 0; i < tmplen /* image size */; i++) {
++                      sum += *p++;
++              }
++
++              if (sum != le32_to_cpu(fw_image->chksum)) {
++                      printk("acx: FATAL: firmware upload: "
++                              "checksums don't match! "
++                              "(0x%08x vs. 0x%08x)\n",
++                                      sum, fw_image->chksum);
++                      goto fw_end;
++              }
++
++              offset = 8;
++              while (offset < file_size) {
++                      blk_len = file_size - offset;
++                      if (blk_len > USB_RWMEM_MAXLEN) {
++                              blk_len = USB_RWMEM_MAXLEN;
++                      }
++
++                      log(L_INIT, "uploading firmware (%d bytes, offset=%d)\n",
++                                                      blk_len, offset);
++                      memcpy(usbbuf, ((u8 *)fw_image) + offset, blk_len);
++
++                      p = usbbuf;
++                      for (i = 0; i < blk_len; i += 4) {
++                              *(u32 *)p = be32_to_cpu(*(u32 *)p);
++                              p += 4;
++                      }
++
++                      result = usb_bulk_msg(usbdev, outpipe, usbbuf, blk_len, &num_processed, HZ);
++                      if ((result < 0) || (num_processed != blk_len))
++                              goto fw_end;
++                      offset += blk_len;
++              }
++              if (need_padding) {
++                      printk(KERN_DEBUG "send padding\n");
++                      memset(usbbuf, 0, 4);
++                      result = usb_bulk_msg(usbdev, outpipe, usbbuf, 4, &num_processed, HZ);
++                      if ((result < 0) || (num_processed != 4))
++                              goto fw_end;
++              }
++              printk(KERN_DEBUG "read firmware upload result\n");
++              memset(cmdbuf, 0, 20); /* additional memset */
++              result = usb_bulk_msg(usbdev, inpipe, cmdbuf, 20, &num_processed, 2000);
++              if (result < 0)
++                      goto fw_end;
++              if (*(u32 *)&cmdbuf[4] == 0x40000003)
++                      goto fw_end;
++              if (*(u32 *)&cmdbuf[4])
++                      goto fw_end;
++              if (*(u16 *)&cmdbuf[16] != 1)
++                      goto fw_end;
++
++              val = *(u32 *)&cmdbuf[0];
++              if ((val & 0x3fff)
++              ||  ((val & 0xc000) != 0xc000))
++                      goto fw_end;
++
++              val = *(u32 *)&cmdbuf[8];
++              if (val & 2) {
++                      result = usb_bulk_msg(usbdev, inpipe, cmdbuf, 20, &num_processed, 2000);
++                      if (result < 0)
++                              goto fw_end;
++                      val = *(u32 *)&cmdbuf[8];
++              }
++              /* yup, no "else" here! */
++              if (val & 1) {
++                      memset(usbbuf, 0, 4);
++                      result = usb_bulk_msg(usbdev, outpipe, usbbuf, 4, &num_processed, HZ);
++                      if ((result < 0) || (!num_processed))
++                              goto fw_end;
++              }
++
++              printk("TNETW1450 firmware upload successful!\n");
++              result = 0;
++              goto end;
++fw_end:
++              result = -EIO;
++              goto end;
++      } else {
++              /* ACX100 USB */
++
++              /* now upload the firmware, slice the data into blocks */
++              offset = 8;
++              while (offset < file_size) {
++                      blk_len = file_size - offset;
++                      if (blk_len > USB_RWMEM_MAXLEN) {
++                              blk_len = USB_RWMEM_MAXLEN;
++                      }
++                      log(L_INIT, "uploading firmware (%d bytes, offset=%d)\n",
++                                                      blk_len, offset);
++                      memcpy(usbbuf, ((u8 *)fw_image) + offset, blk_len);
++                      result = usb_control_msg(usbdev, outpipe,
++                              ACX_USB_REQ_UPLOAD_FW,
++                              USB_TYPE_VENDOR|USB_DIR_OUT,
++                              (file_size - 8) & 0xffff, /* value */
++                              (file_size - 8) >> 16, /* index */
++                              usbbuf, /* dataptr */
++                              blk_len, /* size */
++                              3000 /* timeout in ms */
++                      );
++                      offset += blk_len;
++                      if (result < 0) {
++                              printk(KERN_ERR "acx: error %d during upload "
++                                      "of firmware, aborting\n", result);
++                              goto end;
++                      }
++              }
++
++              /* finally, send the checksum and reboot the device */
++              /* does this trigger the reboot? */
++              result = usb_control_msg(usbdev, outpipe,
++                      ACX_USB_REQ_UPLOAD_FW,
++                      USB_TYPE_VENDOR|USB_DIR_OUT,
++                      img_checksum & 0xffff, /* value */
++                      img_checksum >> 16, /* index */
++                      NULL, /* dataptr */
++                      0, /* size */
++                      3000 /* timeout in ms */
++              );
++              if (result < 0) {
++                      printk(KERN_ERR "acx: error %d during tx of checksum, "
++                                      "aborting\n", result);
++                      goto end;
++              }
++              result = usb_control_msg(usbdev, inpipe,
++                      ACX_USB_REQ_ACK_CS,
++                      USB_TYPE_VENDOR|USB_DIR_IN,
++                      img_checksum & 0xffff, /* value */
++                      img_checksum >> 16, /* index */
++                      usbbuf, /* dataptr */
++                      8, /* size */
++                      3000 /* timeout in ms */
++              );
++              if (result < 0) {
++                      printk(KERN_ERR "acx: error %d during ACK of checksum, "
++                                      "aborting\n", result);
++                      goto end;
++              }
++              if (*usbbuf != 0x10) {
++                      printk(KERN_ERR "acx: invalid checksum?\n");
++                      result = -EINVAL;
++                      goto end;
++              }
++              result = 0;
++      }
++
++end:
++      vfree(fw_image);
++      kfree(usbbuf);
++
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/* FIXME: maybe merge it with usual eeprom reading, into common code? */
++static void
++acxusb_s_read_eeprom_version(acx_device_t *adev)
++{
++      u8 eeprom_ver[0x8];
++
++      memset(eeprom_ver, 0, sizeof(eeprom_ver));
++      acx_s_interrogate(adev, &eeprom_ver, ACX1FF_IE_EEPROM_VER);
++
++      /* FIXME: which one of those values to take? */
++      adev->eeprom_version = eeprom_ver[5];
++}
++
++
++/*
++ * temporary helper function to at least fill important cfgopt members with
++ * useful replacement values until we figure out how one manages to fetch
++ * the configoption struct in the USB device case...
++ */
++static int
++acxusb_s_fill_configoption(acx_device_t *adev)
++{
++      adev->cfgopt_probe_delay = 200;
++      adev->cfgopt_dot11CCAModes = 4;
++      adev->cfgopt_dot11Diversity = 1;
++      adev->cfgopt_dot11ShortPreambleOption = 1;
++      adev->cfgopt_dot11PBCCOption = 1;
++      adev->cfgopt_dot11ChannelAgility = 0;
++      adev->cfgopt_dot11PhyType = 5;
++      adev->cfgopt_dot11TempType = 1;
++      return OK;
++}
++
++
++/***********************************************************************
++** acxusb_e_probe()
++**
++** This function is invoked by the kernel's USB core whenever a new device is
++** attached to the system or the module is loaded. It is presented a usb_device
++** structure from which information regarding the device is obtained and evaluated.
++** In case this driver is able to handle one of the offered devices, it returns
++** a non-null pointer to a driver context and thereby claims the device.
++*/
++
++static void
++dummy_netdev_init(struct net_device *ndev) {}
++
++static int
++acxusb_e_probe(struct usb_interface *intf, const struct usb_device_id *devID)
++{
++      struct usb_device *usbdev = interface_to_usbdev(intf);
++      acx_device_t *adev = NULL;
++      struct net_device *ndev = NULL;
++      struct usb_config_descriptor *config;
++      struct usb_endpoint_descriptor *epdesc;
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11)
++      struct usb_host_endpoint *ep;
++#endif
++      struct usb_interface_descriptor *ifdesc;
++      const char* msg;
++      int numconfigs, numfaces, numep;
++      int result = OK;
++      int i;
++      int radio_type;
++      /* this one needs to be more precise in case there appears a TNETW1450 from the same vendor */
++      int is_tnetw1450 = (usbdev->descriptor.idVendor != ACX100_VENDOR_ID);
++
++      FN_ENTER;
++
++      if (is_tnetw1450) {
++              /* Boot the device (i.e. upload the firmware) */
++              acxusb_boot(usbdev, is_tnetw1450, &radio_type);
++
++              /* TNETW1450-based cards will continue right away with
++               * the same USB ID after booting */
++      } else {
++              /* First check if this is the "unbooted" hardware */
++              if (usbdev->descriptor.idProduct == ACX100_PRODUCT_ID_UNBOOTED) {
++
++                      /* Boot the device (i.e. upload the firmware) */
++                      acxusb_boot(usbdev, is_tnetw1450, &radio_type);
++
++                      /* DWL-120+ will first boot the firmware,
++                       * then later have a *separate* probe() run
++                       * since its USB ID will have changed after
++                       * firmware boot!
++                       * Since the first probe() run has no
++                       * other purpose than booting the firmware,
++                       * simply return immediately.
++                      */
++                      log(L_INIT, "finished booting, returning from probe()\n");
++                      result = OK; /* success */
++                      goto end;
++              }
++              else
++              /* device not unbooted, but invalid USB ID!? */
++              if (usbdev->descriptor.idProduct != ACX100_PRODUCT_ID_BOOTED)
++                      goto end_nodev;
++      }
++
++/* Ok, so it's our device and it has already booted */
++
++      /* Allocate memory for a network device */
++
++      ndev = alloc_netdev(sizeof(*adev), "wlan%d", dummy_netdev_init);
++      /* (NB: memsets to 0 entire area) */
++      if (!ndev) {
++              msg = "acx: no memory for netdev\n";
++              goto end_nomem;
++      }
++
++      /* Register the callbacks for the network device functions */
++
++      ether_setup(ndev);
++      ndev->open = &acxusb_e_open;
++      ndev->stop = &acxusb_e_close;
++      ndev->hard_start_xmit = (void *)&acx_i_start_xmit;
++      ndev->get_stats = (void *)&acx_e_get_stats;
++#if IW_HANDLER_VERSION <= 5
++      ndev->get_wireless_stats = (void *)&acx_e_get_wireless_stats;
++#endif
++      ndev->wireless_handlers = (struct iw_handler_def *)&acx_ioctl_handler_def;
++      ndev->set_multicast_list = (void *)&acxusb_i_set_rx_mode;
++#ifdef HAVE_TX_TIMEOUT
++      ndev->tx_timeout = &acxusb_i_tx_timeout;
++      ndev->watchdog_timeo = 4 * HZ;
++#endif
++      ndev->change_mtu = &acx_e_change_mtu;
++      SET_MODULE_OWNER(ndev);
++
++      /* Setup private driver context */
++
++      adev = ndev2adev(ndev);
++      adev->ndev = ndev;
++
++      adev->dev_type = DEVTYPE_USB;
++      adev->radio_type = radio_type;
++      if (is_tnetw1450) {
++              /* well, actually it's a TNETW1450, but since it
++               * seems to be sufficiently similar to TNETW1130,
++               * I don't want to change large amounts of code now */
++              adev->chip_type = CHIPTYPE_ACX111;
++      } else {
++              adev->chip_type = CHIPTYPE_ACX100;
++      }
++
++      adev->usbdev = usbdev;
++      spin_lock_init(&adev->lock);    /* initial state: unlocked */
++      sema_init(&adev->sem, 1);       /* initial state: 1 (upped) */
++
++      /* Check that this is really the hardware we know about.
++      ** If not sure, at least notify the user that he
++      ** may be in trouble...
++      */
++      numconfigs = (int)usbdev->descriptor.bNumConfigurations;
++      if (numconfigs != 1)
++              printk("acx: number of configurations is %d, "
++                      "this driver only knows how to handle 1, "
++                      "be prepared for surprises\n", numconfigs);
++
++      config = &usbdev->config->desc;
++      numfaces = config->bNumInterfaces;
++      if (numfaces != 1)
++              printk("acx: number of interfaces is %d, "
++                      "this driver only knows how to handle 1, "
++                      "be prepared for surprises\n", numfaces);
++
++      ifdesc = &intf->altsetting->desc;
++      numep = ifdesc->bNumEndpoints;
++      log(L_DEBUG, "# of endpoints: %d\n", numep);
++
++      if (is_tnetw1450) {
++              adev->bulkoutep = 1;
++              adev->bulkinep = 2;
++      } else {
++              /* obtain information about the endpoint
++              ** addresses, begin with some default values
++              */
++              adev->bulkoutep = 1;
++              adev->bulkinep = 1;
++              for (i = 0; i < numep; i++) {
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11)
++                      ep = usbdev->ep_in[i];
++                      if (!ep)
++                              continue;
++                      epdesc = &ep->desc;
++#else
++                      epdesc = usb_epnum_to_ep_desc(usbdev, i);
++                      if (!epdesc)
++                              continue;
++#endif
++                      if (epdesc->bmAttributes & USB_ENDPOINT_XFER_BULK) {
++                              if (epdesc->bEndpointAddress & 0x80)
++                                      adev->bulkinep = epdesc->bEndpointAddress & 0xF;
++                              else
++                                      adev->bulkoutep = epdesc->bEndpointAddress & 0xF;
++                      }
++              }
++      }
++      log(L_DEBUG, "bulkout ep: 0x%X\n", adev->bulkoutep);
++      log(L_DEBUG, "bulkin ep: 0x%X\n", adev->bulkinep);
++
++      /* already done by memset: adev->rxtruncsize = 0; */
++      log(L_DEBUG, "TXBUFSIZE=%d RXBUFSIZE=%d\n",
++                              (int) TXBUFSIZE, (int) RXBUFSIZE);
++
++      /* Allocate the RX/TX containers. */
++      adev->usb_tx = kmalloc(sizeof(usb_tx_t) * ACX_TX_URB_CNT, GFP_KERNEL);
++      if (!adev->usb_tx) {
++              msg = "acx: no memory for tx container";
++              goto end_nomem;
++      }
++      adev->usb_rx = kmalloc(sizeof(usb_rx_t) * ACX_RX_URB_CNT, GFP_KERNEL);
++      if (!adev->usb_rx) {
++              msg = "acx: no memory for rx container";
++              goto end_nomem;
++      }
++
++      /* Setup URBs for bulk-in/out messages */
++      for (i = 0; i < ACX_RX_URB_CNT; i++) {
++              adev->usb_rx[i].urb = usb_alloc_urb(0, GFP_KERNEL);
++              if (!adev->usb_rx[i].urb) {
++                      msg = "acx: no memory for input URB\n";
++                      goto end_nomem;
++              }
++              adev->usb_rx[i].urb->status = 0;
++              adev->usb_rx[i].adev = adev;
++              adev->usb_rx[i].busy = 0;
++      }
++
++      for (i = 0; i< ACX_TX_URB_CNT; i++) {
++              adev->usb_tx[i].urb = usb_alloc_urb(0, GFP_KERNEL);
++              if (!adev->usb_tx[i].urb) {
++                      msg = "acx: no memory for output URB\n";
++                      goto end_nomem;
++              }
++              adev->usb_tx[i].urb->status = 0;
++              adev->usb_tx[i].adev = adev;
++              adev->usb_tx[i].busy = 0;
++      }
++      adev->tx_free = ACX_TX_URB_CNT;
++
++      usb_set_intfdata(intf, adev);
++      SET_NETDEV_DEV(ndev, &intf->dev);
++
++      /* TODO: move all of fw cmds to open()? But then we won't know our MAC addr
++         until ifup (it's available via reading ACX1xx_IE_DOT11_STATION_ID)... */
++
++      /* put acx out of sleep mode and initialize it */
++      acx_s_issue_cmd(adev, ACX1xx_CMD_WAKE, NULL, 0);
++
++      result = acx_s_init_mac(adev);
++      if (result)
++              goto end;
++
++      /* TODO: see similar code in pci.c */
++      acxusb_s_read_eeprom_version(adev);
++      acxusb_s_fill_configoption(adev);
++      acx_s_set_defaults(adev);
++      acx_s_get_firmware_version(adev);
++      acx_display_hardware_details(adev);
++
++      /* Register the network device */
++      log(L_INIT, "registering network device\n");
++      result = register_netdev(ndev);
++      if (result) {
++              msg = "acx: failed to register USB network device "
++                      "(error %d)\n";
++              goto end_nomem;
++      }
++
++      acx_proc_register_entries(ndev);
++
++      acx_stop_queue(ndev, "on probe");
++      acx_carrier_off(ndev, "on probe");
++
++      printk("acx: USB module " ACX_RELEASE " loaded successfully\n");
++
++#if CMD_DISCOVERY
++      great_inquisitor(adev);
++#endif
++
++      /* Everything went OK, we are happy now */
++      result = OK;
++      goto end;
++
++end_nomem:
++      printk(msg, result);
++
++      if (ndev) {
++              if (adev->usb_rx) {
++                      for (i = 0; i < ACX_RX_URB_CNT; i++)
++                              usb_free_urb(adev->usb_rx[i].urb);
++                      kfree(adev->usb_rx);
++              }
++              if (adev->usb_tx) {
++                      for (i = 0; i < ACX_TX_URB_CNT; i++)
++                              usb_free_urb(adev->usb_tx[i].urb);
++                      kfree(adev->usb_tx);
++              }
++              free_netdev(ndev);
++      }
++
++      result = -ENOMEM;
++      goto end;
++
++end_nodev:
++      /* no device we could handle, return error. */
++      result = -EIO;
++
++end:
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/***********************************************************************
++** acxusb_e_disconnect()
++**
++** This function is invoked whenever the user pulls the plug from the USB
++** device or the module is removed from the kernel. In these cases, the
++** network devices have to be taken down and all allocated memory has
++** to be freed.
++*/
++static void
++acxusb_e_disconnect(struct usb_interface *intf)
++{
++      acx_device_t *adev = usb_get_intfdata(intf);
++      unsigned long flags;
++      int i;
++
++      FN_ENTER;
++
++      /* No WLAN device... no sense */
++      if (!adev)
++              goto end;
++
++      /* Unregister network device
++       *
++       * If the interface is up, unregister_netdev() will take
++       * care of calling our close() function, which takes
++       * care of unlinking the urbs, sending the device to
++       * sleep, etc...
++       * This can't be called with sem or lock held because
++       * _close() will try to grab it as well if it's called,
++       * deadlocking the machine.
++       */
++      unregister_netdev(adev->ndev);
++
++      acx_sem_lock(adev);
++      acx_lock(adev, flags);
++      /* This device exists no more */
++      usb_set_intfdata(intf, NULL);
++      acx_proc_unregister_entries(adev->ndev);
++
++      /*
++       * Here we only free them. _close() took care of
++       * unlinking them.
++       */
++      for (i = 0; i < ACX_RX_URB_CNT; ++i) {
++              usb_free_urb(adev->usb_rx[i].urb);
++      }
++      for (i = 0; i< ACX_TX_URB_CNT; ++i) {
++              usb_free_urb(adev->usb_tx[i].urb);
++      }
++
++      /* Freeing containers */
++      kfree(adev->usb_rx);
++      kfree(adev->usb_tx);
++
++      acx_unlock(adev, flags);
++      acx_sem_unlock(adev);
++
++      free_netdev(adev->ndev);
++end:
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++** acxusb_e_open()
++** This function is called when the user sets up the network interface.
++** It initializes a management timer, sets up the USB card and starts
++** the network tx queue and USB receive.
++*/
++static int
++acxusb_e_open(struct net_device *ndev)
++{
++      acx_device_t *adev = ndev2adev(ndev);
++      unsigned long flags;
++      int i;
++
++      FN_ENTER;
++
++      acx_sem_lock(adev);
++
++      /* put the ACX100 out of sleep mode */
++      acx_s_issue_cmd(adev, ACX1xx_CMD_WAKE, NULL, 0);
++
++      acx_init_task_scheduler(adev);
++
++      init_timer(&adev->mgmt_timer);
++      adev->mgmt_timer.function = acx_i_timer;
++      adev->mgmt_timer.data = (unsigned long)adev;
++
++      /* acx_s_start needs it */
++      SET_BIT(adev->dev_state_mask, ACX_STATE_IFACE_UP);
++      acx_s_start(adev);
++
++      /* don't acx_start_queue() here, we need to associate first */
++
++      acx_lock(adev, flags);
++      for (i = 0; i < ACX_RX_URB_CNT; i++) {
++              adev->usb_rx[i].urb->status = 0;
++      }
++
++      acxusb_l_poll_rx(adev, &adev->usb_rx[0]);
++
++      acx_unlock(adev, flags);
++
++      acx_sem_unlock(adev);
++
++      FN_EXIT0;
++      return 0;
++}
++
++
++/***********************************************************************
++** acxusb_e_close()
++**
++** This function stops the network functionality of the interface (invoked
++** when the user calls ifconfig <wlan> down). The tx queue is halted and
++** the device is marked as down. In case there were any pending USB bulk
++** transfers, these are unlinked (asynchronously). The module in-use count
++** is also decreased in this function.
++*/
++static int
++acxusb_e_close(struct net_device *ndev)
++{
++      acx_device_t *adev = ndev2adev(ndev);
++      unsigned long flags;
++      int i;
++
++      FN_ENTER;
++
++#ifdef WE_STILL_DONT_CARE_ABOUT_IT
++      /* Transmit a disassociate frame */
++      lock
++      acx_l_transmit_disassoc(adev, &client);
++      unlock
++#endif
++
++      acx_sem_lock(adev);
++
++      CLEAR_BIT(adev->dev_state_mask, ACX_STATE_IFACE_UP);
++
++/* Code below is remarkably similar to acxpci_s_down(). Maybe we can merge them? */
++
++      /* Make sure we don't get any more rx requests */
++      acx_s_issue_cmd(adev, ACX1xx_CMD_DISABLE_RX, NULL, 0);
++      acx_s_issue_cmd(adev, ACX1xx_CMD_DISABLE_TX, NULL, 0);
++
++      /*
++       * We must do FLUSH *without* holding sem to avoid a deadlock.
++       * See pci.c:acxpci_s_down() for deails.
++       */
++      acx_sem_unlock(adev);
++      FLUSH_SCHEDULED_WORK();
++      acx_sem_lock(adev);
++
++      /* Power down the device */
++      acx_s_issue_cmd(adev, ACX1xx_CMD_SLEEP, NULL, 0);
++
++      /* Stop the transmit queue, mark the device as DOWN */
++      acx_lock(adev, flags);
++      acx_stop_queue(ndev, "on ifdown");
++      acx_set_status(adev, ACX_STATUS_0_STOPPED);
++      /* stop pending rx/tx urb transfers */
++      for (i = 0; i < ACX_TX_URB_CNT; i++) {
++              acxusb_unlink_urb(adev->usb_tx[i].urb);
++              adev->usb_tx[i].busy = 0;
++      }
++      for (i = 0; i < ACX_RX_URB_CNT; i++) {
++              acxusb_unlink_urb(adev->usb_rx[i].urb);
++              adev->usb_rx[i].busy = 0;
++      }
++      adev->tx_free = ACX_TX_URB_CNT;
++      acx_unlock(adev, flags);
++
++      /* Must do this outside of lock */
++      del_timer_sync(&adev->mgmt_timer);
++
++      acx_sem_unlock(adev);
++
++      FN_EXIT0;
++      return 0;
++}
++
++
++/***********************************************************************
++** acxusb_l_poll_rx
++** This function (re)initiates a bulk-in USB transfer on a given urb
++*/
++static void
++acxusb_l_poll_rx(acx_device_t *adev, usb_rx_t* rx)
++{
++      struct usb_device *usbdev;
++      struct urb *rxurb;
++      int errcode, rxnum;
++      unsigned int inpipe;
++
++      FN_ENTER;
++
++      rxurb = rx->urb;
++      usbdev = adev->usbdev;
++
++      rxnum = rx - adev->usb_rx;
++
++      inpipe = usb_rcvbulkpipe(usbdev, adev->bulkinep);
++      if (unlikely(rxurb->status == -EINPROGRESS)) {
++              printk(KERN_ERR "acx: error, rx triggered while rx urb in progress\n");
++              /* FIXME: this is nasty, receive is being cancelled by this code
++               * on the other hand, this should not happen anyway...
++               */
++              usb_unlink_urb(rxurb);
++      } else
++      if (unlikely(rxurb->status == -ECONNRESET)) {
++              log(L_USBRXTX, "acx_usb: _poll_rx: connection reset\n");
++              goto end;
++      }
++      rxurb->actual_length = 0;
++      usb_fill_bulk_urb(rxurb, usbdev, inpipe,
++              &rx->bulkin, /* dataptr */
++              RXBUFSIZE, /* size */
++              acxusb_i_complete_rx, /* handler */
++              rx /* handler param */
++      );
++      rxurb->transfer_flags = URB_ASYNC_UNLINK;
++
++      /* ATOMIC: we may be called from complete_rx() usb callback */
++      errcode = usb_submit_urb(rxurb, GFP_ATOMIC);
++      /* FIXME: evaluate the error code! */
++      log(L_USBRXTX, "SUBMIT RX (%d) inpipe=0x%X size=%d errcode=%d\n",
++                      rxnum, inpipe, (int) RXBUFSIZE, errcode);
++end:
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++** acxusb_i_complete_rx()
++** Inputs:
++**     urb -> pointer to USB request block
++**    regs -> pointer to register-buffer for syscalls (see asm/ptrace.h)
++**
++** This function is invoked by USB subsystem whenever a bulk receive
++** request returns.
++** The received data is then committed to the network stack and the next
++** USB receive is triggered.
++*/
++static void
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
++acxusb_i_complete_rx(struct urb *urb)
++#else
++acxusb_i_complete_rx(struct urb *urb, struct pt_regs *regs)
++#endif
++{
++      acx_device_t *adev;
++      rxbuffer_t *ptr;
++      rxbuffer_t *inbuf;
++      usb_rx_t *rx;
++      unsigned long flags;
++      int size, remsize, packetsize, rxnum;
++
++      FN_ENTER;
++
++      BUG_ON(!urb->context);
++
++      rx = (usb_rx_t *)urb->context;
++      adev = rx->adev;
++
++      acx_lock(adev, flags);
++
++      /*
++       * Happens on disconnect or close. Don't play with the urb.
++       * Don't resubmit it. It will get unlinked by close()
++       */
++      if (unlikely(!(adev->dev_state_mask & ACX_STATE_IFACE_UP))) {
++              log(L_USBRXTX, "rx: device is down, not doing anything\n");
++              goto end_unlock;
++      }
++
++      inbuf = &rx->bulkin;
++      size = urb->actual_length;
++      remsize = size;
++      rxnum = rx - adev->usb_rx;
++
++      log(L_USBRXTX, "RETURN RX (%d) status=%d size=%d\n",
++                              rxnum, urb->status, size);
++
++      /* Send the URB that's waiting. */
++      log(L_USBRXTX, "rxnum=%d, sending=%d\n", rxnum, rxnum^1);
++      acxusb_l_poll_rx(adev, &adev->usb_rx[rxnum^1]);
++
++      if (unlikely(size > sizeof(rxbuffer_t)))
++              printk("acx_usb: rx too large: %d, please report\n", size);
++
++      /* check if the transfer was aborted */
++      switch (urb->status) {
++      case 0: /* No error */
++              break;
++      case -EOVERFLOW:
++              printk(KERN_ERR "acx: rx data overrun\n");
++              adev->rxtruncsize = 0; /* Not valid anymore. */
++              goto end_unlock;
++      case -ECONNRESET:
++              adev->rxtruncsize = 0;
++              goto end_unlock;
++      case -ESHUTDOWN: /* rmmod */
++              adev->rxtruncsize = 0;
++              goto end_unlock;
++      default:
++              adev->rxtruncsize = 0;
++              adev->stats.rx_errors++;
++              printk("acx: rx error (urb status=%d)\n", urb->status);
++              goto end_unlock;
++      }
++
++      if (unlikely(!size))
++              printk("acx: warning, encountered zerolength rx packet\n");
++
++      if (urb->transfer_buffer != inbuf)
++              goto end_unlock;
++
++      /* check if previous frame was truncated
++      ** FIXME: this code can only handle truncation
++      ** of consecutive packets!
++      */
++      ptr = inbuf;
++      if (adev->rxtruncsize) {
++              int tail_size;
++
++              ptr = &adev->rxtruncbuf;
++              packetsize = RXBUF_BYTES_USED(ptr);
++              if (acx_debug & L_USBRXTX) {
++                      printk("handling truncated frame (truncsize=%d size=%d "
++                                      "packetsize(from trunc)=%d)\n",
++                                      adev->rxtruncsize, size, packetsize);
++                      acx_dump_bytes(ptr, RXBUF_HDRSIZE);
++                      acx_dump_bytes(inbuf, RXBUF_HDRSIZE);
++              }
++
++              /* bytes needed for rxtruncbuf completion: */
++              tail_size = packetsize - adev->rxtruncsize;
++
++              if (size < tail_size) {
++                      /* there is not enough data to complete this packet,
++                      ** simply append the stuff to the truncation buffer
++                      */
++                      memcpy(((char *)ptr) + adev->rxtruncsize, inbuf, size);
++                      adev->rxtruncsize += size;
++                      remsize = 0;
++              } else {
++                      /* ok, this data completes the previously
++                      ** truncated packet. copy it into a descriptor
++                      ** and give it to the rest of the stack */
++
++                      /* append tail to previously truncated part
++                      ** NB: adev->rxtruncbuf (pointed to by ptr) can't
++                      ** overflow because this is already checked before
++                      ** truncation buffer was filled. See below,
++                      ** "if (packetsize > sizeof(rxbuffer_t))..." code */
++                      memcpy(((char *)ptr) + adev->rxtruncsize, inbuf, tail_size);
++
++                      if (acx_debug & L_USBRXTX) {
++                              printk("full trailing packet + 12 bytes:\n");
++                              acx_dump_bytes(inbuf, tail_size + RXBUF_HDRSIZE);
++                      }
++                      acx_l_process_rxbuf(adev, ptr);
++                      adev->rxtruncsize = 0;
++                      ptr = (rxbuffer_t *) (((char *)inbuf) + tail_size);
++                      remsize -= tail_size;
++              }
++              log(L_USBRXTX, "post-merge size=%d remsize=%d\n",
++                                              size, remsize);
++      }
++
++      /* size = USB data block size
++      ** remsize = unprocessed USB bytes left
++      ** ptr = current pos in USB data block
++      */
++      while (remsize) {
++              if (remsize < RXBUF_HDRSIZE) {
++                      printk("acx: truncated rx header (%d bytes)!\n",
++                              remsize);
++                      if (ACX_DEBUG)
++                              acx_dump_bytes(ptr, remsize);
++                      break;
++              }
++
++              packetsize = RXBUF_BYTES_USED(ptr);
++              log(L_USBRXTX, "packet with packetsize=%d\n", packetsize);
++
++              if (RXBUF_IS_TXSTAT(ptr)) {
++                      /* do rate handling */
++                      usb_txstatus_t *stat = (void*)ptr;
++                      u16 client_no = (u16)stat->hostdata;
++
++                      log(L_USBRXTX, "tx: stat: mac_cnt_rcvd:%04X "
++                      "queue_index:%02X mac_status:%02X hostdata:%08X "
++                      "rate:%u ack_failures:%02X rts_failures:%02X "
++                      "rts_ok:%02X\n",
++                      stat->mac_cnt_rcvd,
++                      stat->queue_index, stat->mac_status, stat->hostdata,
++                      stat->rate, stat->ack_failures, stat->rts_failures,
++                      stat->rts_ok);
++
++                      if (adev->rate_auto && client_no < VEC_SIZE(adev->sta_list)) {
++                              client_t *clt = &adev->sta_list[client_no];
++                              u16 cur = stat->hostdata >> 16;
++
++                              if (clt && clt->rate_cur == cur) {
++                                      acx_l_handle_txrate_auto(adev, clt,
++                                              cur, /* intended rate */
++                                              stat->rate, 0, /* actually used rate */
++                                              stat->mac_status, /* error? */
++                                              ACX_TX_URB_CNT - adev->tx_free);
++                              }
++                      }
++                      goto next;
++              }
++
++              if (packetsize > sizeof(rxbuffer_t)) {
++                      printk("acx: packet exceeds max wlan "
++                              "frame size (%d > %d). size=%d\n",
++                              packetsize, (int) sizeof(rxbuffer_t), size);
++                      if (ACX_DEBUG)
++                              acx_dump_bytes(ptr, 16);
++                      /* FIXME: put some real error-handling in here! */
++                      break;
++              }
++
++              if (packetsize > remsize) {
++                      /* frame truncation handling */
++                      if (acx_debug & L_USBRXTX) {
++                              printk("need to truncate packet, "
++                                      "packetsize=%d remsize=%d "
++                                      "size=%d bytes:",
++                                      packetsize, remsize, size);
++                              acx_dump_bytes(ptr, RXBUF_HDRSIZE);
++                      }
++                      memcpy(&adev->rxtruncbuf, ptr, remsize);
++                      adev->rxtruncsize = remsize;
++                      break;
++              }
++
++              /* packetsize <= remsize */
++              /* now handle the received data */
++              acx_l_process_rxbuf(adev, ptr);
++next:
++              ptr = (rxbuffer_t *)(((char *)ptr) + packetsize);
++              remsize -= packetsize;
++              if ((acx_debug & L_USBRXTX) && remsize) {
++                      printk("more than one packet in buffer, "
++                                              "second packet hdr:");
++                      acx_dump_bytes(ptr, RXBUF_HDRSIZE);
++              }
++      }
++
++end_unlock:
++      acx_unlock(adev, flags);
++/* end: */
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++** acxusb_i_complete_tx()
++** Inputs:
++**     urb -> pointer to USB request block
++**    regs -> pointer to register-buffer for syscalls (see asm/ptrace.h)
++**
++** This function is invoked upon termination of a USB transfer.
++*/
++static void
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
++acxusb_i_complete_tx(struct urb *urb)
++#else
++acxusb_i_complete_tx(struct urb *urb, struct pt_regs *regs)
++#endif
++{
++      acx_device_t *adev;
++      usb_tx_t *tx;
++      unsigned long flags;
++      int txnum;
++
++      FN_ENTER;
++
++      BUG_ON(!urb->context);
++
++      tx = (usb_tx_t *)urb->context;
++      adev = tx->adev;
++
++      txnum = tx - adev->usb_tx;
++
++      acx_lock(adev, flags);
++
++      /*
++       * If the iface isn't up, we don't have any right
++       * to play with them. The urb may get unlinked.
++       */
++      if (unlikely(!(adev->dev_state_mask & ACX_STATE_IFACE_UP))) {
++              log(L_USBRXTX, "tx: device is down, not doing anything\n");
++              goto end_unlock;
++      }
++
++      log(L_USBRXTX, "RETURN TX (%d): status=%d size=%d\n",
++                              txnum, urb->status, urb->actual_length);
++
++      /* handle USB transfer errors */
++      switch (urb->status) {
++      case 0: /* No error */
++              break;
++      case -ESHUTDOWN:
++              goto end_unlock;
++              break;
++      case -ECONNRESET:
++              goto end_unlock;
++              break;
++              /* FIXME: real error-handling code here please */
++      default:
++              printk(KERN_ERR "acx: tx error, urb status=%d\n", urb->status);
++              /* FIXME: real error-handling code here please */
++      }
++
++      /* free the URB and check for more data */
++      tx->busy = 0;
++      adev->tx_free++;
++      if ((adev->tx_free >= TX_START_QUEUE)
++       && (adev->status == ACX_STATUS_4_ASSOCIATED)
++       && (acx_queue_stopped(adev->ndev))
++      ) {
++              log(L_BUF, "tx: wake queue (%u free txbufs)\n",
++                              adev->tx_free);
++              acx_wake_queue(adev->ndev, NULL);
++      }
++
++end_unlock:
++      acx_unlock(adev, flags);
++/* end: */
++      FN_EXIT0;
++}
++
++
++/***************************************************************
++** acxusb_l_alloc_tx
++** Actually returns a usb_tx_t* ptr
++*/
++tx_t*
++acxusb_l_alloc_tx(acx_device_t *adev)
++{
++      usb_tx_t *tx;
++      unsigned head;
++
++      FN_ENTER;
++
++      head = adev->tx_head;
++      do {
++              head = (head + 1) % ACX_TX_URB_CNT;
++              if (!adev->usb_tx[head].busy) {
++                      log(L_USBRXTX, "allocated tx %d\n", head);
++                      tx = &adev->usb_tx[head];
++                      tx->busy = 1;
++                      adev->tx_free--;
++                      /* Keep a few free descs between head and tail of tx ring.
++                      ** It is not absolutely needed, just feels safer */
++                      if (adev->tx_free < TX_STOP_QUEUE) {
++                              log(L_BUF, "tx: stop queue "
++                                      "(%u free txbufs)\n", adev->tx_free);
++                              acx_stop_queue(adev->ndev, NULL);
++                      }
++                      goto end;
++              }
++      } while (likely(head!=adev->tx_head));
++      tx = NULL;
++      printk_ratelimited("acx: tx buffers full\n");
++end:
++      adev->tx_head = head;
++      FN_EXIT0;
++      return (tx_t*)tx;
++}
++
++
++/***************************************************************
++** Used if alloc_tx()'ed buffer needs to be cancelled without doing tx
++*/
++void
++acxusb_l_dealloc_tx(tx_t *tx_opaque)
++{
++      usb_tx_t* tx = (usb_tx_t*)tx_opaque;
++      tx->busy = 0;
++}
++
++
++/***************************************************************
++*/
++void*
++acxusb_l_get_txbuf(acx_device_t *adev, tx_t* tx_opaque)
++{
++      usb_tx_t* tx = (usb_tx_t*)tx_opaque;
++      return &tx->bulkout.data;
++}
++
++
++/***************************************************************
++** acxusb_l_tx_data
++**
++** Can be called from IRQ (rx -> (AP bridging or mgmt response) -> tx).
++** Can be called from acx_i_start_xmit (data frames from net core).
++*/
++void
++acxusb_l_tx_data(acx_device_t *adev, tx_t* tx_opaque, int wlanpkt_len)
++{
++      struct usb_device *usbdev;
++      struct urb* txurb;
++      usb_tx_t* tx;
++      usb_txbuffer_t* txbuf;
++      client_t *clt;
++      wlan_hdr_t* whdr;
++      unsigned int outpipe;
++      int ucode, txnum;
++
++      FN_ENTER;
++
++      tx = ((usb_tx_t *)tx_opaque);
++      txurb = tx->urb;
++      txbuf = &tx->bulkout;
++      whdr = (wlan_hdr_t *)txbuf->data;
++      txnum = tx - adev->usb_tx;
++
++      log(L_DEBUG, "using buf#%d free=%d len=%d\n",
++                      txnum, adev->tx_free, wlanpkt_len);
++
++      switch (adev->mode) {
++      case ACX_MODE_0_ADHOC:
++      case ACX_MODE_3_AP:
++              clt = acx_l_sta_list_get(adev, whdr->a1);
++              break;
++      case ACX_MODE_2_STA:
++              clt = adev->ap_client;
++              break;
++      default: /* ACX_MODE_OFF, ACX_MODE_MONITOR */
++              clt = NULL;
++              break;
++      }
++
++      if (unlikely(clt && !clt->rate_cur)) {
++              printk("acx: driver bug! bad ratemask\n");
++              goto end;
++      }
++
++      /* fill the USB transfer header */
++      txbuf->desc = cpu_to_le16(USB_TXBUF_TXDESC);
++      txbuf->mpdu_len = cpu_to_le16(wlanpkt_len);
++      txbuf->queue_index = 1;
++      if (clt) {
++              txbuf->rate = clt->rate_100;
++              txbuf->hostdata = (clt - adev->sta_list) | (clt->rate_cur << 16);
++      } else {
++              txbuf->rate = adev->rate_bcast100;
++              txbuf->hostdata = ((u16)-1) | (adev->rate_bcast << 16);
++      }
++      txbuf->ctrl1 = DESC_CTL_FIRSTFRAG;
++      if (1 == adev->preamble_cur)
++              SET_BIT(txbuf->ctrl1, DESC_CTL_SHORT_PREAMBLE);
++      txbuf->ctrl2 = 0;
++      txbuf->data_len = cpu_to_le16(wlanpkt_len);
++
++      if (unlikely(acx_debug & L_DATA)) {
++              printk("dump of bulk out urb:\n");
++              acx_dump_bytes(txbuf, wlanpkt_len + USB_TXBUF_HDRSIZE);
++      }
++
++      if (unlikely(txurb->status == -EINPROGRESS)) {
++              printk("acx: trying to submit tx urb while already in progress\n");
++      }
++
++      /* now schedule the USB transfer */
++      usbdev = adev->usbdev;
++      outpipe = usb_sndbulkpipe(usbdev, adev->bulkoutep);
++
++      usb_fill_bulk_urb(txurb, usbdev, outpipe,
++              txbuf, /* dataptr */
++              wlanpkt_len + USB_TXBUF_HDRSIZE, /* size */
++              acxusb_i_complete_tx, /* handler */
++              tx /* handler param */
++      );
++
++      txurb->transfer_flags = URB_ASYNC_UNLINK|URB_ZERO_PACKET;
++      ucode = usb_submit_urb(txurb, GFP_ATOMIC);
++      log(L_USBRXTX, "SUBMIT TX (%d): outpipe=0x%X buf=%p txsize=%d "
++              "rate=%u errcode=%d\n", txnum, outpipe, txbuf,
++              wlanpkt_len + USB_TXBUF_HDRSIZE, txbuf->rate, ucode);
++
++      if (unlikely(ucode)) {
++              printk(KERN_ERR "acx: submit_urb() error=%d txsize=%d\n",
++                      ucode, wlanpkt_len + USB_TXBUF_HDRSIZE);
++
++              /* on error, just mark the frame as done and update
++              ** the statistics
++              */
++              adev->stats.tx_errors++;
++              tx->busy = 0;
++              adev->tx_free++;
++              /* needed? if (adev->tx_free > TX_START_QUEUE) acx_wake_queue(...) */
++      }
++end:
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++*/
++static void
++acxusb_i_set_rx_mode(struct net_device *ndev)
++{
++}
++
++
++/***********************************************************************
++*/
++#ifdef HAVE_TX_TIMEOUT
++static void
++acxusb_i_tx_timeout(struct net_device *ndev)
++{
++      acx_device_t *adev = ndev2adev(ndev);
++      unsigned long flags;
++      int i;
++
++      FN_ENTER;
++
++      acx_lock(adev, flags);
++      /* unlink the URBs */
++      for (i = 0; i < ACX_TX_URB_CNT; i++) {
++              acxusb_unlink_urb(adev->usb_tx[i].urb);
++              adev->usb_tx[i].busy = 0;
++      }
++      adev->tx_free = ACX_TX_URB_CNT;
++      /* TODO: stats update */
++      acx_unlock(adev, flags);
++
++      FN_EXIT0;
++}
++#endif
++
++
++/***********************************************************************
++** init_module()
++**
++** This function is invoked upon loading of the kernel module.
++** It registers itself at the kernel's USB subsystem.
++**
++** Returns: Errorcode on failure, 0 on success
++*/
++int __init
++acxusb_e_init_module(void)
++{
++      log(L_INIT, "USB module " ACX_RELEASE " initialized, "
++              "probing for devices...\n");
++      return usb_register(&acxusb_driver);
++}
++
++
++
++/***********************************************************************
++** cleanup_module()
++**
++** This function is invoked as last step of the module unloading. It simply
++** deregisters this module at the kernel's USB subsystem.
++*/
++void __exit
++acxusb_e_cleanup_module()
++{
++      usb_deregister(&acxusb_driver);
++}
++
++
++/***********************************************************************
++** DEBUG STUFF
++*/
++#if ACX_DEBUG
++
++#ifdef UNUSED
++static void
++dump_device(struct usb_device *usbdev)
++{
++      int i;
++      struct usb_config_descriptor *cd;
++
++      printk("acx device dump:\n");
++      printk("  devnum: %d\n", usbdev->devnum);
++      printk("  speed: %d\n", usbdev->speed);
++      printk("  tt: 0x%X\n", (unsigned int)(usbdev->tt));
++      printk("  ttport: %d\n", (unsigned int)(usbdev->ttport));
++      printk("  toggle[0]: 0x%X  toggle[1]: 0x%X\n", (unsigned int)(usbdev->toggle[0]), (unsigned int)(usbdev->toggle[1]));
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11)
++      /* This saw a change after 2.6.10 */
++      printk("  ep_in wMaxPacketSize: ");
++      for (i = 0; i < 16; ++i)
++              if (usbdev->ep_in[i] != NULL)
++                      printk("%d:%d ", i, usbdev->ep_in[i]->desc.wMaxPacketSize);
++      printk("\n");
++      printk("  ep_out wMaxPacketSize: ");
++      for (i = 0; i < VEC_SIZE(usbdev->ep_out); ++i)
++              if (usbdev->ep_out[i] != NULL)
++                      printk("%d:%d ", i, usbdev->ep_out[i]->desc.wMaxPacketSize);
++      printk("\n");
++#else
++      printk("  epmaxpacketin: ");
++      for (i = 0; i < 16; i++)
++              printk("%d ", usbdev->epmaxpacketin[i]);
++      printk("\n");
++      printk("  epmaxpacketout: ");
++      for (i = 0; i < 16; i++)
++              printk("%d ", usbdev->epmaxpacketout[i]);
++      printk("\n");
++#endif
++      printk("  parent: 0x%X\n", (unsigned int)usbdev->parent);
++      printk("  bus: 0x%X\n", (unsigned int)usbdev->bus);
++#ifdef NO_DATATYPE
++      printk("  configs: ");
++      for (i = 0; i < usbdev->descriptor.bNumConfigurations; i++)
++              printk("0x%X ", usbdev->config[i]);
++      printk("\n");
++#endif
++      printk("  actconfig: %p\n", usbdev->actconfig);
++      dump_device_descriptor(&usbdev->descriptor);
++
++      cd = &usbdev->config->desc;
++      dump_config_descriptor(cd);
++}
++
++
++/***********************************************************************
++*/
++static void
++dump_config_descriptor(struct usb_config_descriptor *cd)
++{
++      printk("Configuration Descriptor:\n");
++      if (!cd) {
++              printk("NULL\n");
++              return;
++      }
++      printk("  bLength: %d (0x%X)\n", cd->bLength, cd->bLength);
++      printk("  bDescriptorType: %d (0x%X)\n", cd->bDescriptorType, cd->bDescriptorType);
++      printk("  bNumInterfaces: %d (0x%X)\n", cd->bNumInterfaces, cd->bNumInterfaces);
++      printk("  bConfigurationValue: %d (0x%X)\n", cd->bConfigurationValue, cd->bConfigurationValue);
++      printk("  iConfiguration: %d (0x%X)\n", cd->iConfiguration, cd->iConfiguration);
++      printk("  bmAttributes: %d (0x%X)\n", cd->bmAttributes, cd->bmAttributes);
++      /* printk("  MaxPower: %d (0x%X)\n", cd->bMaxPower, cd->bMaxPower); */
++}
++
++
++static void
++dump_device_descriptor(struct usb_device_descriptor *dd)
++{
++      printk("Device Descriptor:\n");
++      if (!dd) {
++              printk("NULL\n");
++              return;
++      }
++      printk("  bLength: %d (0x%X)\n", dd->bLength, dd->bLength);
++      printk("  bDescriptortype: %d (0x%X)\n", dd->bDescriptorType, dd->bDescriptorType);
++      printk("  bcdUSB: %d (0x%X)\n", dd->bcdUSB, dd->bcdUSB);
++      printk("  bDeviceClass: %d (0x%X)\n", dd->bDeviceClass, dd->bDeviceClass);
++      printk("  bDeviceSubClass: %d (0x%X)\n", dd->bDeviceSubClass, dd->bDeviceSubClass);
++      printk("  bDeviceProtocol: %d (0x%X)\n", dd->bDeviceProtocol, dd->bDeviceProtocol);
++      printk("  bMaxPacketSize0: %d (0x%X)\n", dd->bMaxPacketSize0, dd->bMaxPacketSize0);
++      printk("  idVendor: %d (0x%X)\n", dd->idVendor, dd->idVendor);
++      printk("  idProduct: %d (0x%X)\n", dd->idProduct, dd->idProduct);
++      printk("  bcdDevice: %d (0x%X)\n", dd->bcdDevice, dd->bcdDevice);
++      printk("  iManufacturer: %d (0x%X)\n", dd->iManufacturer, dd->iManufacturer);
++      printk("  iProduct: %d (0x%X)\n", dd->iProduct, dd->iProduct);
++      printk("  iSerialNumber: %d (0x%X)\n", dd->iSerialNumber, dd->iSerialNumber);
++      printk("  bNumConfigurations: %d (0x%X)\n", dd->bNumConfigurations, dd->bNumConfigurations);
++}
++#endif /* UNUSED */
++
++#endif /* ACX_DEBUG */
+Index: linux-2.6.22/drivers/net/wireless/acx/wlan.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/drivers/net/wireless/acx/wlan.c       2007-08-23 18:34:19.000000000 +0200
+@@ -0,0 +1,424 @@
++/***********************************************************************
++** Copyright (C) 2003  ACX100 Open Source Project
++**
++** The contents of this file are subject to the Mozilla Public
++** License Version 1.1 (the "License"); you may not use this file
++** except in compliance with the License. You may obtain a copy of
++** the License at http://www.mozilla.org/MPL/
++**
++** Software distributed under the License is distributed on an "AS
++** IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
++** implied. See the License for the specific language governing
++** rights and limitations under the License.
++**
++** Alternatively, the contents of this file may be used under the
++** terms of the GNU Public License version 2 (the "GPL"), in which
++** case the provisions of the GPL are applicable instead of the
++** above.  If you wish to allow the use of your version of this file
++** only under the terms of the GPL and not to allow others to use
++** your version of this file under the MPL, indicate your decision
++** by deleting the provisions above and replace them with the notice
++** and other provisions required by the GPL.  If you do not delete
++** the provisions above, a recipient may use your version of this
++** file under either the MPL or the GPL.
++** ---------------------------------------------------------------------
++** Inquiries regarding the ACX100 Open Source Project can be
++** made directly to:
++**
++** acx100-users@lists.sf.net
++** http://acx100.sf.net
++** ---------------------------------------------------------------------
++*/
++
++/***********************************************************************
++** This code is based on elements which are
++** Copyright (C) 1999 AbsoluteValue Systems, Inc.  All Rights Reserved.
++** info@linux-wlan.com
++** http://www.linux-wlan.com
++*/
++
++#include <linux/version.h>
++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18)
++#include <linux/config.h>
++#endif
++#include <linux/types.h>
++#include <linux/if_arp.h>
++#include <linux/wireless.h>
++#include <net/iw_handler.h>
++
++#include "acx.h"
++
++
++/***********************************************************************
++*/
++#define LOG_BAD_EID(hdr,len,ie_ptr) acx_log_bad_eid(hdr, len, ((wlan_ie_t*)ie_ptr))
++
++#define IE_EID(ie_ptr) (((wlan_ie_t*)(ie_ptr))->eid)
++#define IE_LEN(ie_ptr) (((wlan_ie_t*)(ie_ptr))->len)
++#define OFFSET(hdr,off) (WLAN_HDR_A3_DATAP(hdr) + (off))
++
++
++/***********************************************************************
++** wlan_mgmt_decode_XXX
++**
++** Given a complete frame in f->hdr, sets the pointers in f to
++** the areas that correspond to the parts of the frame.
++**
++** Assumptions:
++**    1) f->len and f->hdr are already set
++**    2) f->len is the length of the MAC header + data, the FCS
++**       is NOT included
++**    3) all members except len and hdr are zero
++** Arguments:
++**    f       frame structure
++**
++** Returns:
++**    nothing
++**
++** Side effects:
++**    frame structure members are pointing at their
++**    respective portions of the frame buffer.
++*/
++void
++wlan_mgmt_decode_beacon(wlan_fr_beacon_t * f)
++{
++      u8 *ie_ptr;
++      u8 *end = (u8*)f->hdr + f->len;
++
++      f->type = WLAN_FSTYPE_BEACON;
++
++      /*-- Fixed Fields ----*/
++      f->ts = (u64 *) OFFSET(f->hdr, WLAN_BEACON_OFF_TS);
++      f->bcn_int = (u16 *) OFFSET(f->hdr, WLAN_BEACON_OFF_BCN_INT);
++      f->cap_info = (u16 *) OFFSET(f->hdr, WLAN_BEACON_OFF_CAPINFO);
++
++      /*-- Information elements */
++      ie_ptr = OFFSET(f->hdr, WLAN_BEACON_OFF_SSID);
++      while (ie_ptr < end) {
++              switch (IE_EID(ie_ptr)) {
++              case WLAN_EID_SSID:
++                      f->ssid = (wlan_ie_ssid_t *) ie_ptr;
++                      break;
++              case WLAN_EID_SUPP_RATES:
++                      f->supp_rates = (wlan_ie_supp_rates_t *) ie_ptr;
++                      break;
++              case WLAN_EID_EXT_RATES:
++                      f->ext_rates = (wlan_ie_supp_rates_t *) ie_ptr;
++                      break;
++              case WLAN_EID_FH_PARMS:
++                      f->fh_parms = (wlan_ie_fh_parms_t *) ie_ptr;
++                      break;
++              case WLAN_EID_DS_PARMS:
++                      f->ds_parms = (wlan_ie_ds_parms_t *) ie_ptr;
++                      break;
++              case WLAN_EID_CF_PARMS:
++                      f->cf_parms = (wlan_ie_cf_parms_t *) ie_ptr;
++                      break;
++              case WLAN_EID_IBSS_PARMS:
++                      f->ibss_parms = (wlan_ie_ibss_parms_t *) ie_ptr;
++                      break;
++              case WLAN_EID_TIM:
++                      f->tim = (wlan_ie_tim_t *) ie_ptr;
++                      break;
++              case WLAN_EID_ERP_INFO:
++                      f->erp = (wlan_ie_erp_t *) ie_ptr;
++                      break;
++
++              case WLAN_EID_COUNTRY:
++              /* was seen: 07 06 47 42 20 01 0D 14 */
++              case WLAN_EID_PWR_CONSTRAINT:
++              /* was seen by Ashwin Mansinghka <ashwin_man@yahoo.com> from
++              Atheros-based PCI card in AP mode using madwifi drivers: */
++              /* 20 01 00 */
++              case WLAN_EID_NONERP:
++              /* was seen from WRT54GS with OpenWrt: 2F 01 07 */
++              case WLAN_EID_UNKNOWN128:
++              /* was seen by Jacek Jablonski <conexion2000@gmail.com> from Orinoco AP */
++              /* 80 06 00 60 1D 2C 3B 00 */
++              case WLAN_EID_UNKNOWN133:
++              /* was seen by David Bronaugh <dbronaugh@linuxboxen.org> from ???? */
++              /* 85 1E 00 00 84 12 07 00 FF 00 11 00 61 70 63 31 */
++              /* 63 73 72 30 34 32 00 00 00 00 00 00 00 00 00 25 */
++              case WLAN_EID_UNKNOWN223:
++              /* was seen by Carlos Martin <carlosmn@gmail.com> from ???? */
++              /* DF 20 01 1E 04 00 00 00 06 63 09 02 FF 0F 30 30 */
++              /* 30 42 36 42 33 34 30 39 46 31 00 00 00 00 00 00 00 00 */
++              case WLAN_EID_GENERIC:
++              /* WPA: hostap code:
++                      if (pos[1] >= 4 &&
++                              pos[2] == 0x00 && pos[3] == 0x50 &&
++                              pos[4] == 0xf2 && pos[5] == 1) {
++                              wpa = pos;
++                              wpa_len = pos[1] + 2;
++                      }
++              TI x4 mode: seen DD 04 08 00 28 00
++              (08 00 28 is TI's OUI)
++              last byte is probably 0/1 - disabled/enabled
++              */
++              case WLAN_EID_RSN:
++              /* hostap does something with it:
++                      rsn = pos;
++                      rsn_len = pos[1] + 2;
++              */
++                      break;
++
++              default:
++                      LOG_BAD_EID(f->hdr, f->len, ie_ptr);
++                      break;
++              }
++              ie_ptr = ie_ptr + 2 + IE_LEN(ie_ptr);
++      }
++}
++
++
++#ifdef UNUSED
++void wlan_mgmt_decode_ibssatim(wlan_fr_ibssatim_t * f)
++{
++      f->type = WLAN_FSTYPE_ATIM;
++      /*-- Fixed Fields ----*/
++      /*-- Information elements */
++}
++#endif /* UNUSED */
++
++void
++wlan_mgmt_decode_disassoc(wlan_fr_disassoc_t * f)
++{
++      f->type = WLAN_FSTYPE_DISASSOC;
++
++      /*-- Fixed Fields ----*/
++      f->reason = (u16 *) OFFSET(f->hdr, WLAN_DISASSOC_OFF_REASON);
++
++      /*-- Information elements */
++}
++
++
++void
++wlan_mgmt_decode_assocreq(wlan_fr_assocreq_t * f)
++{
++      u8 *ie_ptr;
++      u8 *end = (u8*)f->hdr + f->len;
++
++
++      f->type = WLAN_FSTYPE_ASSOCREQ;
++
++      /*-- Fixed Fields ----*/
++      f->cap_info = (u16 *) OFFSET(f->hdr, WLAN_ASSOCREQ_OFF_CAP_INFO);
++      f->listen_int = (u16 *) OFFSET(f->hdr, WLAN_ASSOCREQ_OFF_LISTEN_INT);
++
++      /*-- Information elements */
++      ie_ptr = OFFSET(f->hdr, WLAN_ASSOCREQ_OFF_SSID);
++      while (ie_ptr < end) {
++              switch (IE_EID(ie_ptr)) {
++              case WLAN_EID_SSID:
++                      f->ssid = (wlan_ie_ssid_t *) ie_ptr;
++                      break;
++              case WLAN_EID_SUPP_RATES:
++                      f->supp_rates = (wlan_ie_supp_rates_t *) ie_ptr;
++                      break;
++              case WLAN_EID_EXT_RATES:
++                      f->ext_rates = (wlan_ie_supp_rates_t *) ie_ptr;
++                      break;
++              default:
++                      LOG_BAD_EID(f->hdr, f->len, ie_ptr);
++                      break;
++              }
++              ie_ptr = ie_ptr + 2 + IE_LEN(ie_ptr);
++      }
++}
++
++
++void
++wlan_mgmt_decode_assocresp(wlan_fr_assocresp_t * f)
++{
++      f->type = WLAN_FSTYPE_ASSOCRESP;
++
++      /*-- Fixed Fields ----*/
++      f->cap_info = (u16 *) OFFSET(f->hdr, WLAN_ASSOCRESP_OFF_CAP_INFO);
++      f->status = (u16 *) OFFSET(f->hdr, WLAN_ASSOCRESP_OFF_STATUS);
++      f->aid = (u16 *) OFFSET(f->hdr, WLAN_ASSOCRESP_OFF_AID);
++
++      /*-- Information elements */
++      f->supp_rates = (wlan_ie_supp_rates_t *)
++                      OFFSET(f->hdr, WLAN_ASSOCRESP_OFF_SUPP_RATES);
++}
++
++
++#ifdef UNUSED
++void
++wlan_mgmt_decode_reassocreq(wlan_fr_reassocreq_t * f)
++{
++      u8 *ie_ptr;
++      u8 *end = (u8*)f->hdr + f->len;
++
++      f->type = WLAN_FSTYPE_REASSOCREQ;
++
++      /*-- Fixed Fields ----*/
++      f->cap_info = (u16 *) OFFSET(f->hdr, WLAN_REASSOCREQ_OFF_CAP_INFO);
++      f->listen_int = (u16 *) OFFSET(f->hdr, WLAN_REASSOCREQ_OFF_LISTEN_INT);
++      f->curr_ap = (u8 *) OFFSET(f->hdr, WLAN_REASSOCREQ_OFF_CURR_AP);
++
++      /*-- Information elements */
++      ie_ptr = OFFSET(f->hdr, WLAN_REASSOCREQ_OFF_SSID);
++      while (ie_ptr < end) {
++              switch (IE_EID(ie_ptr)) {
++              case WLAN_EID_SSID:
++                      f->ssid = (wlan_ie_ssid_t *) ie_ptr;
++                      break;
++              case WLAN_EID_SUPP_RATES:
++                      f->supp_rates = (wlan_ie_supp_rates_t *) ie_ptr;
++                      break;
++              case WLAN_EID_EXT_RATES:
++                      f->ext_rates = (wlan_ie_supp_rates_t *) ie_ptr;
++                      break;
++              default:
++                      LOG_BAD_EID(f->hdr, f->len, ie_ptr);
++                      break;
++              }
++              ie_ptr = ie_ptr + 2 + IE_LEN(ie_ptr);
++      }
++}
++
++
++void
++wlan_mgmt_decode_reassocresp(wlan_fr_reassocresp_t * f)
++{
++      f->type = WLAN_FSTYPE_REASSOCRESP;
++
++      /*-- Fixed Fields ----*/
++      f->cap_info = (u16 *) OFFSET(f->hdr, WLAN_REASSOCRESP_OFF_CAP_INFO);
++      f->status = (u16 *) OFFSET(f->hdr, WLAN_REASSOCRESP_OFF_STATUS);
++      f->aid = (u16 *) OFFSET(f->hdr, WLAN_REASSOCRESP_OFF_AID);
++
++      /*-- Information elements */
++      f->supp_rates = (wlan_ie_supp_rates_t *)
++                      OFFSET(f->hdr, WLAN_REASSOCRESP_OFF_SUPP_RATES);
++}
++
++
++void
++wlan_mgmt_decode_probereq(wlan_fr_probereq_t * f)
++{
++      u8 *ie_ptr;
++      u8 *end = (u8*)f->hdr + f->len;
++
++      f->type = WLAN_FSTYPE_PROBEREQ;
++
++      /*-- Fixed Fields ----*/
++
++      /*-- Information elements */
++      ie_ptr = OFFSET(f->hdr, WLAN_PROBEREQ_OFF_SSID);
++      while (ie_ptr < end) {
++              switch (IE_EID(ie_ptr)) {
++              case WLAN_EID_SSID:
++                      f->ssid = (wlan_ie_ssid_t *) ie_ptr;
++                      break;
++              case WLAN_EID_SUPP_RATES:
++                      f->supp_rates = (wlan_ie_supp_rates_t *) ie_ptr;
++                      break;
++              case WLAN_EID_EXT_RATES:
++                      f->ext_rates = (wlan_ie_supp_rates_t *) ie_ptr;
++                      break;
++              default:
++                      LOG_BAD_EID(f->hdr, f->len, ie_ptr);
++                      break;
++              }
++              ie_ptr = ie_ptr + 2 + IE_LEN(ie_ptr);
++      }
++}
++#endif /* UNUSED */
++
++
++/* TODO: decoding of beacon and proberesp can be merged (similar structure) */
++void
++wlan_mgmt_decode_proberesp(wlan_fr_proberesp_t * f)
++{
++      u8 *ie_ptr;
++      u8 *end = (u8*)f->hdr + f->len;
++
++      f->type = WLAN_FSTYPE_PROBERESP;
++
++      /*-- Fixed Fields ----*/
++      f->ts = (u64 *) OFFSET(f->hdr, WLAN_PROBERESP_OFF_TS);
++      f->bcn_int = (u16 *) OFFSET(f->hdr, WLAN_PROBERESP_OFF_BCN_INT);
++      f->cap_info = (u16 *) OFFSET(f->hdr, WLAN_PROBERESP_OFF_CAP_INFO);
++
++      /*-- Information elements */
++      ie_ptr = OFFSET(f->hdr, WLAN_PROBERESP_OFF_SSID);
++      while (ie_ptr < end) {
++              switch (IE_EID(ie_ptr)) {
++              case WLAN_EID_SSID:
++                      f->ssid = (wlan_ie_ssid_t *) ie_ptr;
++                      break;
++              case WLAN_EID_SUPP_RATES:
++                      f->supp_rates = (wlan_ie_supp_rates_t *) ie_ptr;
++                      break;
++              case WLAN_EID_EXT_RATES:
++                      f->ext_rates = (wlan_ie_supp_rates_t *) ie_ptr;
++                      break;
++              case WLAN_EID_FH_PARMS:
++                      f->fh_parms = (wlan_ie_fh_parms_t *) ie_ptr;
++                      break;
++              case WLAN_EID_DS_PARMS:
++                      f->ds_parms = (wlan_ie_ds_parms_t *) ie_ptr;
++                      break;
++              case WLAN_EID_CF_PARMS:
++                      f->cf_parms = (wlan_ie_cf_parms_t *) ie_ptr;
++                      break;
++              case WLAN_EID_IBSS_PARMS:
++                      f->ibss_parms = (wlan_ie_ibss_parms_t *) ie_ptr;
++                      break;
++#ifdef DONT_DO_IT_ADD_REAL_HANDLING_INSTEAD
++              case WLAN_EID_COUNTRY:
++                      break;
++              ...
++#endif
++#ifdef SENT_HERE_BY_OPENWRT
++              /* should those be trapped or handled?? */
++              case WLAN_EID_ERP_INFO:
++                      break;
++              case WLAN_EID_NONERP:
++                      break;
++              case WLAN_EID_GENERIC:
++                      break;
++#endif
++              default:
++                      LOG_BAD_EID(f->hdr, f->len, ie_ptr);
++                      break;
++              }
++
++              ie_ptr = ie_ptr + 2 + IE_LEN(ie_ptr);
++      }
++}
++
++
++void
++wlan_mgmt_decode_authen(wlan_fr_authen_t * f)
++{
++      u8 *ie_ptr;
++      u8 *end = (u8*)f->hdr + f->len;
++
++      f->type = WLAN_FSTYPE_AUTHEN;
++
++      /*-- Fixed Fields ----*/
++      f->auth_alg = (u16 *) OFFSET(f->hdr, WLAN_AUTHEN_OFF_AUTH_ALG);
++      f->auth_seq = (u16 *) OFFSET(f->hdr, WLAN_AUTHEN_OFF_AUTH_SEQ);
++      f->status = (u16 *) OFFSET(f->hdr, WLAN_AUTHEN_OFF_STATUS);
++
++      /*-- Information elements */
++      ie_ptr = OFFSET(f->hdr, WLAN_AUTHEN_OFF_CHALLENGE);
++      if ((ie_ptr < end) && (IE_EID(ie_ptr) == WLAN_EID_CHALLENGE)) {
++              f->challenge = (wlan_ie_challenge_t *) ie_ptr;
++      }
++}
++
++
++void
++wlan_mgmt_decode_deauthen(wlan_fr_deauthen_t * f)
++{
++      f->type = WLAN_FSTYPE_DEAUTHEN;
++
++      /*-- Fixed Fields ----*/
++      f->reason = (u16 *) OFFSET(f->hdr, WLAN_DEAUTHEN_OFF_REASON);
++
++      /*-- Information elements */
++}
+Index: linux-2.6.22/drivers/net/wireless/acx/wlan_compat.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/drivers/net/wireless/acx/wlan_compat.h        2007-08-23 18:34:19.000000000 +0200
+@@ -0,0 +1,260 @@
++/***********************************************************************
++** Copyright (C) 2003  ACX100 Open Source Project
++**
++** The contents of this file are subject to the Mozilla Public
++** License Version 1.1 (the "License"); you may not use this file
++** except in compliance with the License. You may obtain a copy of
++** the License at http://www.mozilla.org/MPL/
++**
++** Software distributed under the License is distributed on an "AS
++** IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
++** implied. See the License for the specific language governing
++** rights and limitations under the License.
++**
++** Alternatively, the contents of this file may be used under the
++** terms of the GNU Public License version 2 (the "GPL"), in which
++** case the provisions of the GPL are applicable instead of the
++** above.  If you wish to allow the use of your version of this file
++** only under the terms of the GPL and not to allow others to use
++** your version of this file under the MPL, indicate your decision
++** by deleting the provisions above and replace them with the notice
++** and other provisions required by the GPL.  If you do not delete
++** the provisions above, a recipient may use your version of this
++** file under either the MPL or the GPL.
++** ---------------------------------------------------------------------
++** Inquiries regarding the ACX100 Open Source Project can be
++** made directly to:
++**
++** acx100-users@lists.sf.net
++** http://acx100.sf.net
++** ---------------------------------------------------------------------
++*/
++
++/***********************************************************************
++** This code is based on elements which are
++** Copyright (C) 1999 AbsoluteValue Systems, Inc.  All Rights Reserved.
++** info@linux-wlan.com
++** http://www.linux-wlan.com
++*/
++
++/*=============================================================*/
++/*------ Establish Platform Identity --------------------------*/
++/*=============================================================*/
++/* Key macros: */
++/* WLAN_CPU_FAMILY */
++#define WLAN_Ix86                     1
++#define WLAN_PPC                      2
++#define WLAN_Ix96                     3
++#define WLAN_ARM                      4
++#define WLAN_ALPHA                    5
++#define WLAN_MIPS                     6
++#define WLAN_HPPA                     7
++#define WLAN_SPARC                    8
++#define WLAN_SH                               9
++#define WLAN_x86_64                   10
++/* WLAN_CPU_CORE */
++#define WLAN_I386CORE                 1
++#define WLAN_PPCCORE                  2
++#define WLAN_I296                     3
++#define WLAN_ARMCORE                  4
++#define WLAN_ALPHACORE                        5
++#define WLAN_MIPSCORE                 6
++#define WLAN_HPPACORE                 7
++/* WLAN_CPU_PART */
++#define WLAN_I386PART                 1
++#define WLAN_MPC860                   2
++#define WLAN_MPC823                   3
++#define WLAN_I296SA                   4
++#define WLAN_PPCPART                  5
++#define WLAN_ARMPART                  6
++#define WLAN_ALPHAPART                        7
++#define WLAN_MIPSPART                 8
++#define WLAN_HPPAPART                 9
++/* WLAN_SYSARCH */
++#define WLAN_PCAT                     1
++#define WLAN_MBX                      2
++#define WLAN_RPX                      3
++#define WLAN_LWARCH                   4
++#define WLAN_PMAC                     5
++#define WLAN_SKIFF                    6
++#define WLAN_BITSY                    7
++#define WLAN_ALPHAARCH                        7
++#define WLAN_MIPSARCH                 9
++#define WLAN_HPPAARCH                 10
++/* WLAN_HOSTIF (generally set on the command line, not detected) */
++#define WLAN_PCMCIA                   1
++#define WLAN_ISA                      2
++#define WLAN_PCI                      3
++#define WLAN_USB                      4
++#define WLAN_PLX                      5
++
++/* Note: the PLX HOSTIF above refers to some vendors implementations for */
++/*       PCI.  It's a PLX chip that is a PCI to PCMCIA adapter, but it   */
++/*       isn't a real PCMCIA host interface adapter providing all the    */
++/*       card&socket services.                                           */
++
++#ifdef __powerpc__
++#ifndef __ppc__
++#define __ppc__
++#endif
++#endif
++
++#if (defined(CONFIG_PPC) || defined(CONFIG_8xx))
++#ifndef __ppc__
++#define __ppc__
++#endif
++#endif
++
++#if defined(__x86_64__)
++ #define WLAN_CPU_FAMILY      WLAN_x86_64
++ #define WLAN_SYSARCH         WLAN_PCAT
++#elif defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__)
++ #define WLAN_CPU_FAMILY      WLAN_Ix86
++ #define WLAN_CPU_CORE                WLAN_I386CORE
++ #define WLAN_CPU_PART                WLAN_I386PART
++ #define WLAN_SYSARCH         WLAN_PCAT
++#elif defined(__ppc__)
++ #define WLAN_CPU_FAMILY      WLAN_PPC
++ #define WLAN_CPU_CORE                WLAN_PPCCORE
++ #if defined(CONFIG_MBX)
++  #define WLAN_CPU_PART               WLAN_MPC860
++  #define WLAN_SYSARCH                WLAN_MBX
++ #elif defined(CONFIG_RPXLITE)
++  #define WLAN_CPU_PART               WLAN_MPC823
++  #define WLAN_SYSARCH                WLAN_RPX
++ #elif defined(CONFIG_RPXCLASSIC)
++  #define WLAN_CPU_PART               WLAN_MPC860
++  #define WLAN_SYSARCH                WLAN_RPX
++ #else
++  #define WLAN_CPU_PART               WLAN_PPCPART
++  #define WLAN_SYSARCH                WLAN_PMAC
++ #endif
++#elif defined(__arm__)
++ #define WLAN_CPU_FAMILY      WLAN_ARM
++ #define WLAN_CPU_CORE                WLAN_ARMCORE
++ #define WLAN_CPU_PART                WLAN_ARM_PART
++ #define WLAN_SYSARCH         WLAN_SKIFF
++#elif defined(__alpha__)
++ #define WLAN_CPU_FAMILY      WLAN_ALPHA
++ #define WLAN_CPU_CORE                WLAN_ALPHACORE
++ #define WLAN_CPU_PART                WLAN_ALPHAPART
++ #define WLAN_SYSARCH         WLAN_ALPHAARCH
++#elif defined(__mips__)
++ #define WLAN_CPU_FAMILY      WLAN_MIPS
++ #define WLAN_CPU_CORE                WLAN_MIPSCORE
++ #define WLAN_CPU_PART                WLAN_MIPSPART
++ #define WLAN_SYSARCH         WLAN_MIPSARCH
++#elif defined(__hppa__)
++ #define WLAN_CPU_FAMILY      WLAN_HPPA
++ #define WLAN_CPU_CORE                WLAN_HPPACORE
++ #define WLAN_CPU_PART                WLAN_HPPAPART
++ #define WLAN_SYSARCH         WLAN_HPPAARCH
++#elif defined(__sparc__)
++ #define WLAN_CPU_FAMILY      WLAN_SPARC
++ #define WLAN_SYSARCH         WLAN_SPARC
++#elif defined(__sh__)
++ #define WLAN_CPU_FAMILY      WLAN_SH
++ #define WLAN_SYSARCH         WLAN_SHARCH
++ #ifndef __LITTLE_ENDIAN__
++  #define __LITTLE_ENDIAN__
++ #endif
++#else
++ #error "No CPU identified!"
++#endif
++
++/*
++   Some big endian machines implicitly do all I/O in little endian mode.
++
++   In particular:
++        Linux/PPC on PowerMacs (PCI)
++        Arm/Intel Xscale (PCI)
++
++   This may also affect PLX boards and other BE &| PPC platforms;
++   as new ones are discovered, add them below.
++*/
++
++#if ((WLAN_SYSARCH == WLAN_SKIFF) || (WLAN_SYSARCH == WLAN_PMAC))
++#define REVERSE_ENDIAN
++#endif
++
++/*=============================================================*/
++/*------ Hardware Portability Macros --------------------------*/
++/*=============================================================*/
++#if (WLAN_CPU_FAMILY == WLAN_PPC)
++#define wlan_inw(a)                     in_be16((unsigned short *)((a)+_IO_BASE))
++#define wlan_inw_le16_to_cpu(a)         inw((a))
++#define wlan_outw(v,a)                  out_be16((unsigned short *)((a)+_IO_BASE), (v))
++#define wlan_outw_cpu_to_le16(v,a)      outw((v),(a))
++#else
++#define wlan_inw(a)                     inw((a))
++#define wlan_inw_le16_to_cpu(a)         __cpu_to_le16(inw((a)))
++#define wlan_outw(v,a)                  outw((v),(a))
++#define wlan_outw_cpu_to_le16(v,a)      outw(__cpu_to_le16((v)),(a))
++#endif
++
++/*=============================================================*/
++/*------ Bit settings -----------------------------------------*/
++/*=============================================================*/
++#define ieee2host16(n)        __le16_to_cpu(n)
++#define ieee2host32(n)        __le32_to_cpu(n)
++#define host2ieee16(n)        __cpu_to_le16(n)
++#define host2ieee32(n)        __cpu_to_le32(n)
++
++/* for constants */
++#ifdef __LITTLE_ENDIAN
++ #define IEEE16(a,n)     a = n, a##i = n,
++#else
++ #ifdef __BIG_ENDIAN
++  /* shifts would produce gcc warnings. Oh well... */
++  #define IEEE16(a,n)     a = n, a##i = ((n&0xff)*256 + ((n&0xff00)/256)),
++ #else
++  #error give me endianness or give me death
++ #endif
++#endif
++
++/*=============================================================*/
++/*------ Compiler Portability Macros --------------------------*/
++/*=============================================================*/
++#define WLAN_PACKED   __attribute__ ((packed))
++
++/* Interrupt handler backwards compatibility stuff */
++#ifndef IRQ_NONE
++#define IRQ_NONE
++#define IRQ_HANDLED
++typedef void irqreturn_t;
++#endif
++
++#ifndef ARPHRD_IEEE80211_PRISM
++#define ARPHRD_IEEE80211_PRISM 802
++#endif
++
++#define ETH_P_80211_RAW               (ETH_P_ECONET + 1)
++
++/*============================================================================*
++ * Constants                                                                  *
++ *============================================================================*/
++#define WLAN_IEEE_OUI_LEN     3
++
++/*============================================================================*
++ * Types                                                                      *
++ *============================================================================*/
++
++/* local ether header type */
++typedef struct wlan_ethhdr {
++      u8      daddr[ETH_ALEN];
++      u8      saddr[ETH_ALEN];
++      u16     type;
++} WLAN_PACKED wlan_ethhdr_t;
++
++/* local llc header type */
++typedef struct wlan_llc {
++      u8      dsap;
++      u8      ssap;
++      u8      ctl;
++} WLAN_PACKED wlan_llc_t;
++
++/* local snap header type */
++typedef struct wlan_snap {
++      u8      oui[WLAN_IEEE_OUI_LEN];
++      u16     type;
++} WLAN_PACKED wlan_snap_t;
+Index: linux-2.6.22/drivers/net/wireless/acx/wlan_hdr.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/drivers/net/wireless/acx/wlan_hdr.h   2007-08-23 18:34:19.000000000 +0200
+@@ -0,0 +1,497 @@
++/***********************************************************************
++** Copyright (C) 2003  ACX100 Open Source Project
++**
++** The contents of this file are subject to the Mozilla Public
++** License Version 1.1 (the "License"); you may not use this file
++** except in compliance with the License. You may obtain a copy of
++** the License at http://www.mozilla.org/MPL/
++**
++** Software distributed under the License is distributed on an "AS
++** IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
++** implied. See the License for the specific language governing
++** rights and limitations under the License.
++**
++** Alternatively, the contents of this file may be used under the
++** terms of the GNU Public License version 2 (the "GPL"), in which
++** case the provisions of the GPL are applicable instead of the
++** above.  If you wish to allow the use of your version of this file
++** only under the terms of the GPL and not to allow others to use
++** your version of this file under the MPL, indicate your decision
++** by deleting the provisions above and replace them with the notice
++** and other provisions required by the GPL.  If you do not delete
++** the provisions above, a recipient may use your version of this
++** file under either the MPL or the GPL.
++** ---------------------------------------------------------------------
++** Inquiries regarding the ACX100 Open Source Project can be
++** made directly to:
++**
++** acx100-users@lists.sf.net
++** http://acx100.sf.net
++** ---------------------------------------------------------------------
++*/
++
++/***********************************************************************
++** This code is based on elements which are
++** Copyright (C) 1999 AbsoluteValue Systems, Inc.  All Rights Reserved.
++** info@linux-wlan.com
++** http://www.linux-wlan.com
++*/
++
++/* mini-doc
++
++Here are all 11b/11g/11a rates and modulations:
++
++     11b 11g 11a
++     --- --- ---
++ 1  |B  |B  |
++ 2  |Q  |Q  |
++ 5.5|Cp |C p|
++ 6  |   |Od |O
++ 9  |   |od |o
++11  |Cp |C p|
++12  |   |Od |O
++18  |   |od |o
++22  |   |  p|
++24  |   |Od |O
++33  |   |  p|
++36  |   |od |o
++48  |   |od |o
++54  |   |od |o
++
++Mandatory:
++ B - DBPSK (Differential Binary Phase Shift Keying)
++ Q - DQPSK (Differential Quaternary Phase Shift Keying)
++ C - CCK (Complementary Code Keying, a form of DSSS
++              (Direct Sequence Spread Spectrum) modulation)
++ O - OFDM (Orthogonal Frequency Division Multiplexing)
++Optional:
++ o - OFDM
++ d - CCK-OFDM (also known as DSSS-OFDM)
++ p - PBCC (Packet Binary Convolutional Coding)
++
++The term CCK-OFDM may be used interchangeably with DSSS-OFDM
++(the IEEE 802.11g-2003 standard uses the latter terminology).
++In the CCK-OFDM, the PLCP header of the frame uses the CCK form of DSSS,
++while the PLCP payload (the MAC frame) is modulated using OFDM.
++
++Basically, you must use CCK-OFDM if you have mixed 11b/11g environment,
++or else (pure OFDM) 11b equipment may not realize that AP
++is sending a packet and start sending its own one.
++Sadly, looks like acx111 does not support CCK-OFDM, only pure OFDM.
++
++Re PBCC: avoid using it. It makes sense only if you have
++TI "11b+" hardware. You _must_ use PBCC in order to reach 22Mbps on it.
++
++Preambles:
++
++Long preamble (at 1Mbit rate, takes 144 us):
++    16 bytes  ones
++     2 bytes  0xF3A0 (lsb sent first)
++PLCP header follows (at 1Mbit also):
++     1 byte   Signal: speed, in 0.1Mbit units, except for:
++              33Mbit: 33 (instead of 330 - doesn't fit in octet)
++              all CCK-OFDM rates: 30
++     1 byte   Service
++      0,1,4:  reserved
++      2:      1=locked clock
++      3:      1=PBCC
++      5:      Length Extension (PBCC 22,33Mbit (11g only))  <-
++      6:      Length Extension (PBCC 22,33Mbit (11g only))  <- BLACK MAGIC HERE
++      7:      Length Extension                              <-
++     2 bytes  Length (time needed to tx this frame)
++              a) 5.5 Mbit/s CCK
++                 Length = octets*8/5.5, rounded up to integer
++              b) 11 Mbit/s CCK
++                 Length = octets*8/11, rounded up to integer
++                 Service bit 7:
++                      0 = rounding took less than 8/11
++                      1 = rounding took more than or equal to 8/11
++              c) 5.5 Mbit/s PBCC
++                 Length = (octets+1)*8/5.5, rounded up to integer
++              d) 11 Mbit/s PBCC
++                 Length = (octets+1)*8/11, rounded up to integer
++                 Service bit 7:
++                      0 = rounding took less than 8/11
++                      1 = rounding took more than or equal to 8/11
++              e) 22 Mbit/s PBCC
++                 Length = (octets+1)*8/22, rounded up to integer
++                 Service bits 6,7:
++                      00 = rounding took less than 8/22ths
++                      01 = rounding took 8/22...15/22ths
++                      10 = rounding took 16/22ths or more.
++              f) 33 Mbit/s PBCC
++                 Length = (octets+1)*8/33, rounded up to integer
++                 Service bits 5,6,7:
++                      000 rounding took less than 8/33
++                      001 rounding took 8/33...15/33
++                      010 rounding took 16/33...23/33
++                      011 rounding took 24/33...31/33
++                      100 rounding took 32/33 or more
++     2 bytes  CRC
++
++PSDU follows (up to 2346 bytes at selected rate)
++
++While Signal value alone is not enough to determine rate and modulation,
++Signal+Service is always sufficient.
++
++Short preamble (at 1Mbit rate, takes 72 us):
++     7 bytes  zeroes
++     2 bytes  0x05CF (lsb sent first)
++PLCP header follows *at 2Mbit/s*. Format is the same as in long preamble.
++PSDU follows (up to 2346 bytes at selected rate)
++
++OFDM preamble is completely different, uses OFDM
++modulation from the start and thus easily identifiable.
++Not shown here.
++*/
++
++
++/***********************************************************************
++** Constants
++*/
++
++#define WLAN_HDR_A3_LEN                       24
++#define WLAN_HDR_A4_LEN                       30
++/* IV structure:
++** 3 bytes: Initialization Vector (24 bits)
++** 1 byte: 0..5: padding, must be 0; 6..7: key selector (0-3)
++*/
++#define WLAN_WEP_IV_LEN                       4
++/* 802.11 says 2312 but looks like 2312 is a max size of _WEPed data_ */
++#define WLAN_DATA_MAXLEN              2304
++#define WLAN_WEP_ICV_LEN              4
++#define WLAN_FCS_LEN                  4
++#define WLAN_A3FR_MAXLEN              (WLAN_HDR_A3_LEN + WLAN_DATA_MAXLEN)
++#define WLAN_A4FR_MAXLEN              (WLAN_HDR_A4_LEN + WLAN_DATA_MAXLEN)
++#define WLAN_A3FR_MAXLEN_FCS          (WLAN_HDR_A3_LEN + WLAN_DATA_MAXLEN + 4)
++#define WLAN_A4FR_MAXLEN_FCS          (WLAN_HDR_A4_LEN + WLAN_DATA_MAXLEN + 4)
++#define WLAN_A3FR_MAXLEN_WEP          (WLAN_A3FR_MAXLEN + 8)
++#define WLAN_A4FR_MAXLEN_WEP          (WLAN_A4FR_MAXLEN + 8)
++#define WLAN_A3FR_MAXLEN_WEP_FCS      (WLAN_A3FR_MAXLEN_FCS + 8)
++#define WLAN_A4FR_MAXLEN_WEP_FCS      (WLAN_A4FR_MAXLEN_FCS + 8)
++
++#define WLAN_BSS_TS_LEN                       8
++#define WLAN_SSID_MAXLEN              32
++#define WLAN_BEACON_FR_MAXLEN         (WLAN_HDR_A3_LEN + 334)
++#define WLAN_ATIM_FR_MAXLEN           (WLAN_HDR_A3_LEN + 0)
++#define WLAN_DISASSOC_FR_MAXLEN               (WLAN_HDR_A3_LEN + 2)
++#define WLAN_ASSOCREQ_FR_MAXLEN               (WLAN_HDR_A3_LEN + 48)
++#define WLAN_ASSOCRESP_FR_MAXLEN      (WLAN_HDR_A3_LEN + 16)
++#define WLAN_REASSOCREQ_FR_MAXLEN     (WLAN_HDR_A3_LEN + 54)
++#define WLAN_REASSOCRESP_FR_MAXLEN    (WLAN_HDR_A3_LEN + 16)
++#define WLAN_PROBEREQ_FR_MAXLEN               (WLAN_HDR_A3_LEN + 44)
++#define WLAN_PROBERESP_FR_MAXLEN      (WLAN_HDR_A3_LEN + 78)
++#define WLAN_AUTHEN_FR_MAXLEN         (WLAN_HDR_A3_LEN + 261)
++#define WLAN_DEAUTHEN_FR_MAXLEN               (WLAN_HDR_A3_LEN + 2)
++#define WLAN_CHALLENGE_IE_LEN         130
++#define WLAN_CHALLENGE_LEN            128
++#define WLAN_WEP_MAXKEYLEN            13
++#define WLAN_WEP_NKEYS                        4
++
++/*--- Frame Control Field -------------------------------------*/
++/* Frame Types */
++#define WLAN_FTYPE_MGMT                       0x00
++#define WLAN_FTYPE_CTL                        0x01
++#define WLAN_FTYPE_DATA                       0x02
++
++/* Frame subtypes */
++/* Management */
++#define WLAN_FSTYPE_ASSOCREQ          0x00
++#define WLAN_FSTYPE_ASSOCRESP         0x01
++#define WLAN_FSTYPE_REASSOCREQ                0x02
++#define WLAN_FSTYPE_REASSOCRESP               0x03
++#define WLAN_FSTYPE_PROBEREQ          0x04
++#define WLAN_FSTYPE_PROBERESP         0x05
++#define WLAN_FSTYPE_BEACON            0x08
++#define WLAN_FSTYPE_ATIM              0x09
++#define WLAN_FSTYPE_DISASSOC          0x0a
++#define WLAN_FSTYPE_AUTHEN            0x0b
++#define WLAN_FSTYPE_DEAUTHEN          0x0c
++
++/* Control */
++#define WLAN_FSTYPE_PSPOLL            0x0a
++#define WLAN_FSTYPE_RTS                       0x0b
++#define WLAN_FSTYPE_CTS                       0x0c
++#define WLAN_FSTYPE_ACK                       0x0d
++#define WLAN_FSTYPE_CFEND             0x0e
++#define WLAN_FSTYPE_CFENDCFACK                0x0f
++
++/* Data */
++#define WLAN_FSTYPE_DATAONLY          0x00
++#define WLAN_FSTYPE_DATA_CFACK                0x01
++#define WLAN_FSTYPE_DATA_CFPOLL               0x02
++#define WLAN_FSTYPE_DATA_CFACK_CFPOLL 0x03
++#define WLAN_FSTYPE_NULL              0x04
++#define WLAN_FSTYPE_CFACK             0x05
++#define WLAN_FSTYPE_CFPOLL            0x06
++#define WLAN_FSTYPE_CFACK_CFPOLL      0x07
++
++/*--- FC Constants v. 2.0 ------------------------------------*/
++/* Each constant is defined twice: WF_CONST is in host        */
++/* byteorder, WF_CONSTi is in ieee byteorder.                 */
++/* Usage:                                                     */
++/* printf("the frame subtype is %X", WF_FC_FTYPEi & rx.fc);   */
++/* tx.fc = WF_FTYPE_CTLi | WF_FSTYPE_RTSi;                    */
++/*------------------------------------------------------------*/
++
++enum {
++/*--- Frame Control Field -------------------------------------*/
++/* Protocol version: always 0 for current 802.11 standards */
++IEEE16(WF_FC_PVER,                    0x0003)
++IEEE16(WF_FC_FTYPE,                   0x000c)
++IEEE16(WF_FC_FSTYPE,                  0x00f0)
++IEEE16(WF_FC_TODS,                    0x0100)
++IEEE16(WF_FC_FROMDS,                  0x0200)
++IEEE16(WF_FC_FROMTODS,                        0x0300)
++IEEE16(WF_FC_MOREFRAG,                        0x0400)
++IEEE16(WF_FC_RETRY,                   0x0800)
++/* Indicates PS mode in which STA will be after successful completion
++** of current frame exchange sequence. Always 0 for AP frames */
++IEEE16(WF_FC_PWRMGT,                  0x1000)
++/* What MoreData=1 means:
++** From AP to STA in PS mode: don't sleep yet, I have more frames for you
++** From Contention-Free (CF) Pollable STA in response to a CF-Poll:
++**   STA has buffered frames for transmission in response to next CF-Poll
++** Bcast/mcast frames transmitted from AP:
++**   when additional bcast/mcast frames remain to be transmitted by AP
++**   during this beacon interval
++** In all other cases MoreData=0 */
++IEEE16(WF_FC_MOREDATA,                        0x2000)
++IEEE16(WF_FC_ISWEP,                   0x4000)
++IEEE16(WF_FC_ORDER,                   0x8000)
++
++/* Frame Types */
++IEEE16(WF_FTYPE_MGMT,                 0x00)
++IEEE16(WF_FTYPE_CTL,                  0x04)
++IEEE16(WF_FTYPE_DATA,                 0x08)
++
++/* Frame subtypes */
++/* Management */
++IEEE16(WF_FSTYPE_ASSOCREQ,            0x00)
++IEEE16(WF_FSTYPE_ASSOCRESP,           0x10)
++IEEE16(WF_FSTYPE_REASSOCREQ,          0x20)
++IEEE16(WF_FSTYPE_REASSOCRESP,         0x30)
++IEEE16(WF_FSTYPE_PROBEREQ,            0x40)
++IEEE16(WF_FSTYPE_PROBERESP,           0x50)
++IEEE16(WF_FSTYPE_BEACON,              0x80)
++IEEE16(WF_FSTYPE_ATIM,                        0x90)
++IEEE16(WF_FSTYPE_DISASSOC,            0xa0)
++IEEE16(WF_FSTYPE_AUTHEN,              0xb0)
++IEEE16(WF_FSTYPE_DEAUTHEN,            0xc0)
++
++/* Control */
++IEEE16(WF_FSTYPE_PSPOLL,              0xa0)
++IEEE16(WF_FSTYPE_RTS,                 0xb0)
++IEEE16(WF_FSTYPE_CTS,                 0xc0)
++IEEE16(WF_FSTYPE_ACK,                 0xd0)
++IEEE16(WF_FSTYPE_CFEND,                       0xe0)
++IEEE16(WF_FSTYPE_CFENDCFACK,          0xf0)
++
++/* Data */
++IEEE16(WF_FSTYPE_DATAONLY,            0x00)
++IEEE16(WF_FSTYPE_DATA_CFACK,          0x10)
++IEEE16(WF_FSTYPE_DATA_CFPOLL,         0x20)
++IEEE16(WF_FSTYPE_DATA_CFACK_CFPOLL,   0x30)
++IEEE16(WF_FSTYPE_NULL,                        0x40)
++IEEE16(WF_FSTYPE_CFACK,                       0x50)
++IEEE16(WF_FSTYPE_CFPOLL,              0x60)
++IEEE16(WF_FSTYPE_CFACK_CFPOLL,                0x70)
++};
++
++
++/***********************************************************************
++** Macros
++*/
++
++/*--- Duration Macros ----------------------------------------*/
++/* Macros to get/set the bitfields of the Duration Field      */
++/*  - the duration value is only valid when bit15 is zero     */
++/*  - the firmware handles these values, so I'm not going     */
++/*    to use these macros right now.                          */
++/*------------------------------------------------------------*/
++
++/*--- Sequence Control  Macros -------------------------------*/
++/* Macros to get/set the bitfields of the Sequence Control    */
++/* Field.                                                     */
++/*------------------------------------------------------------*/
++#define WLAN_GET_SEQ_FRGNUM(n) ((u16)(n) & 0x000f)
++#define WLAN_GET_SEQ_SEQNUM(n) (((u16)(n) & 0xfff0) >> 4)
++
++/*--- Data ptr macro -----------------------------------------*/
++/* Creates a u8* to the data portion of a frame               */
++/* Assumes you're passing in a ptr to the beginning of the hdr*/
++/*------------------------------------------------------------*/
++#define WLAN_HDR_A3_DATAP(p) (((u8*)(p)) + WLAN_HDR_A3_LEN)
++#define WLAN_HDR_A4_DATAP(p) (((u8*)(p)) + WLAN_HDR_A4_LEN)
++
++
++/***********************************************************************
++** Types
++*/
++
++/* 802.11 header type
++**
++** Note the following:
++** a1 *always* is receiver's mac or bcast/mcast
++** a2 *always* is transmitter's mac, if a2 exists
++** seq: [0:3] frag#, [4:15] seq# - used for dup detection
++** (dups from retries have same seq#) */
++typedef struct wlan_hdr {
++      u16     fc;
++      u16     dur;
++      u8      a1[ETH_ALEN];
++      u8      a2[ETH_ALEN];
++      u8      a3[ETH_ALEN];
++      u16     seq;
++      u8      a4[ETH_ALEN];
++} WLAN_PACKED wlan_hdr_t;
++
++/* Separate structs for use if frame type is known */
++typedef struct wlan_hdr_a3 {
++      u16     fc;
++      u16     dur;
++      u8      a1[ETH_ALEN];
++      u8      a2[ETH_ALEN];
++      u8      a3[ETH_ALEN];
++      u16     seq;
++} WLAN_PACKED wlan_hdr_a3_t;
++
++typedef struct wlan_hdr_mgmt {
++      u16     fc;
++      u16     dur;
++      u8      da[ETH_ALEN];
++      u8      sa[ETH_ALEN];
++      u8      bssid[ETH_ALEN];
++      u16     seq;
++} WLAN_PACKED wlan_hdr_mgmt_t;
++
++#ifdef NOT_NEEDED_YET
++typedef struct { /* ad-hoc peer->peer (to/from DS = 0/0) */
++      u16     fc;
++      u16     dur;
++      u8      da[ETH_ALEN];
++      u8      sa[ETH_ALEN];
++      u8      bssid[ETH_ALEN];
++      u16     seq;
++} WLAN_PACKED ibss;
++typedef struct { /* ap->sta (to/from DS = 0/1) */
++      u16     fc;
++      u16     dur;
++      u8      da[ETH_ALEN];
++      u8      bssid[ETH_ALEN];
++      u8      sa[ETH_ALEN];
++      u16     seq;
++} WLAN_PACKED fromap;
++typedef struct { /* sta->ap (to/from DS = 1/0) */
++      u16     fc;
++      u16     dur;
++      u8      bssid[ETH_ALEN];
++      u8      sa[ETH_ALEN];
++      u8      da[ETH_ALEN];
++      u16     seq;
++} WLAN_PACKED toap;
++typedef struct { /* wds->wds (to/from DS = 1/1), the only 4addr pkt */
++      u16     fc;
++      u16     dur;
++      u8      ra[ETH_ALEN];
++      u8      ta[ETH_ALEN];
++      u8      da[ETH_ALEN];
++      u16     seq;
++      u8      sa[ETH_ALEN];
++} WLAN_PACKED wds;
++typedef struct { /* all management packets */
++      u16     fc;
++      u16     dur;
++      u8      da[ETH_ALEN];
++      u8      sa[ETH_ALEN];
++      u8      bssid[ETH_ALEN];
++      u16     seq;
++} WLAN_PACKED mgmt;
++typedef struct { /* has no body, just a FCS */
++      u16     fc;
++      u16     dur;
++      u8      ra[ETH_ALEN];
++      u8      ta[ETH_ALEN];
++} WLAN_PACKED rts;
++typedef struct { /* has no body, just a FCS */
++      u16     fc;
++      u16     dur;
++      u8      ra[ETH_ALEN];
++} WLAN_PACKED cts;
++typedef struct { /* has no body, just a FCS */
++      u16     fc;
++      u16     dur;
++      u8      ra[ETH_ALEN];
++} WLAN_PACKED ack;
++typedef struct { /* has no body, just a FCS */
++      u16     fc;
++      /* NB: this one holds Assoc ID in dur field: */
++      u16     aid;
++      u8      bssid[ETH_ALEN];
++      u8      ta[ETH_ALEN];
++} WLAN_PACKED pspoll;
++typedef struct { /* has no body, just a FCS */
++      u16     fc;
++      u16     dur;
++      u8      ra[ETH_ALEN];
++      u8      bssid[ETH_ALEN];
++} WLAN_PACKED cfend;
++typedef struct { /* has no body, just a FCS */
++      u16     fc;
++      u16     dur;
++      u8      ra[ETH_ALEN];
++      u8      bssid[ETH_ALEN];
++} WLAN_PACKED cfendcfack;
++#endif
++
++/* Prism header emulation (monitor mode) */
++typedef struct wlanitem_u32 {
++      u32     did;
++      u16     status;
++      u16     len;
++      u32     data;
++} WLAN_PACKED wlanitem_u32_t;
++#define WLANITEM_STATUS_data_ok                       0
++#define WLANITEM_STATUS_no_value              1
++#define WLANITEM_STATUS_invalid_itemname      2
++#define WLANITEM_STATUS_invalid_itemdata      3
++#define WLANITEM_STATUS_missing_itemdata      4
++#define WLANITEM_STATUS_incomplete_itemdata   5
++#define WLANITEM_STATUS_invalid_msg_did               6
++#define WLANITEM_STATUS_invalid_mib_did               7
++#define WLANITEM_STATUS_missing_conv_func     8
++#define WLANITEM_STATUS_string_too_long               9
++#define WLANITEM_STATUS_data_out_of_range     10
++#define WLANITEM_STATUS_string_too_short      11
++#define WLANITEM_STATUS_missing_valid_func    12
++#define WLANITEM_STATUS_unknown                       13
++#define WLANITEM_STATUS_invalid_did           14
++#define WLANITEM_STATUS_missing_print_func    15
++
++#define WLAN_DEVNAMELEN_MAX   16
++typedef struct wlansniffrm {
++      u32             msgcode;
++      u32             msglen;
++      u8              devname[WLAN_DEVNAMELEN_MAX];
++      wlanitem_u32_t  hosttime;
++      wlanitem_u32_t  mactime;
++      wlanitem_u32_t  channel;
++      wlanitem_u32_t  rssi;
++      wlanitem_u32_t  sq;
++      wlanitem_u32_t  signal;
++      wlanitem_u32_t  noise;
++      wlanitem_u32_t  rate;
++      wlanitem_u32_t  istx;   /* tx? 0:no 1:yes */
++      wlanitem_u32_t  frmlen;
++} WLAN_PACKED wlansniffrm_t;
++#define WLANSNIFFFRM          0x0041
++#define WLANSNIFFFRM_hosttime 0x1041
++#define WLANSNIFFFRM_mactime  0x2041
++#define WLANSNIFFFRM_channel  0x3041
++#define WLANSNIFFFRM_rssi     0x4041
++#define WLANSNIFFFRM_sq               0x5041
++#define WLANSNIFFFRM_signal   0x6041
++#define WLANSNIFFFRM_noise    0x7041
++#define WLANSNIFFFRM_rate     0x8041
++#define WLANSNIFFFRM_istx     0x9041
++#define WLANSNIFFFRM_frmlen   0xA041
+Index: linux-2.6.22/drivers/net/wireless/acx/wlan_mgmt.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/drivers/net/wireless/acx/wlan_mgmt.h  2007-08-23 18:34:19.000000000 +0200
+@@ -0,0 +1,582 @@
++/***********************************************************************
++** Copyright (C) 2003  ACX100 Open Source Project
++**
++** The contents of this file are subject to the Mozilla Public
++** License Version 1.1 (the "License"); you may not use this file
++** except in compliance with the License. You may obtain a copy of
++** the License at http://www.mozilla.org/MPL/
++**
++** Software distributed under the License is distributed on an "AS
++** IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
++** implied. See the License for the specific language governing
++** rights and limitations under the License.
++**
++** Alternatively, the contents of this file may be used under the
++** terms of the GNU Public License version 2 (the "GPL"), in which
++** case the provisions of the GPL are applicable instead of the
++** above.  If you wish to allow the use of your version of this file
++** only under the terms of the GPL and not to allow others to use
++** your version of this file under the MPL, indicate your decision
++** by deleting the provisions above and replace them with the notice
++** and other provisions required by the GPL.  If you do not delete
++** the provisions above, a recipient may use your version of this
++** file under either the MPL or the GPL.
++** ---------------------------------------------------------------------
++** Inquiries regarding the ACX100 Open Source Project can be
++** made directly to:
++**
++** acx100-users@lists.sf.net
++** http://acx100.sf.net
++** ---------------------------------------------------------------------
++*/
++
++/***********************************************************************
++** This code is based on elements which are
++** Copyright (C) 1999 AbsoluteValue Systems, Inc.  All Rights Reserved.
++** info@linux-wlan.com
++** http://www.linux-wlan.com
++*/
++
++/***********************************************************************
++** Constants
++*/
++
++/*-- Information Element IDs --------------------*/
++#define WLAN_EID_SSID         0
++#define WLAN_EID_SUPP_RATES   1
++#define WLAN_EID_FH_PARMS     2
++#define WLAN_EID_DS_PARMS     3
++#define WLAN_EID_CF_PARMS     4
++#define WLAN_EID_TIM          5
++#define WLAN_EID_IBSS_PARMS   6
++#define WLAN_EID_COUNTRY      7 /* 802.11d */
++#define WLAN_EID_FH_HOP_PARMS 8 /* 802.11d */
++#define WLAN_EID_FH_TABLE     9 /* 802.11d */
++#define WLAN_EID_REQUEST      10 /* 802.11d */
++/*-- values 11-15 reserved --*/
++#define WLAN_EID_CHALLENGE    16
++/*-- values 17-31 reserved for challenge text extension --*/
++#define WLAN_EID_PWR_CONSTRAINT       32      /* 11h PowerConstraint */
++#define WLAN_EID_ERP_INFO     42      /* was seen from WRT54GS with OpenWrt */
++#define WLAN_EID_NONERP               47      /* was seen from WRT54GS with OpenWrt */
++#define WLAN_EID_RSN          48
++#define WLAN_EID_EXT_RATES    50
++#define WLAN_EID_UNKNOWN128   128
++#define WLAN_EID_UNKNOWN133   133
++#define WLAN_EID_GENERIC      221     /* was seen from WRT54GS with OpenWrt */
++#define WLAN_EID_UNKNOWN223   223
++
++#if 0
++#define WLAN_EID_PWR_CAP              33      /* 11h PowerCapability */
++#define WLAN_EID_TPC_REQUEST          34      /* 11h TPC Request */
++#define WLAN_EID_TPC_REPORT           35      /* 11h TPC Report */
++#define WLAN_EID_SUPP_CHANNELS                36      /* 11h Supported Channels */
++#define WLAN_EID_CHANNEL_SWITCH               37      /* 11h ChannelSwitch */
++#define WLAN_EID_MEASURE_REQUEST      38      /* 11h MeasurementRequest */
++#define WLAN_EID_MEASURE_REPORT               39      /* 11h MeasurementReport */
++#define WLAN_EID_QUIET_ID             40      /* 11h Quiet */
++#define WLAN_EID_IBSS_DFS_ID          41      /* 11h IBSS_DFS */
++#endif
++
++/*-- Reason Codes -------------------------------*/
++#define WLAN_MGMT_REASON_RSVD                 0
++#define WLAN_MGMT_REASON_UNSPEC                       1
++#define WLAN_MGMT_REASON_PRIOR_AUTH_INVALID   2
++#define WLAN_MGMT_REASON_DEAUTH_LEAVING               3
++#define WLAN_MGMT_REASON_DISASSOC_INACTIVE    4
++#define WLAN_MGMT_REASON_DISASSOC_AP_BUSY     5
++#define WLAN_MGMT_REASON_CLASS2_NONAUTH               6
++#define WLAN_MGMT_REASON_CLASS3_NONASSOC      7
++#define WLAN_MGMT_REASON_DISASSOC_STA_HASLEFT 8
++#define WLAN_MGMT_REASON_CANT_ASSOC_NONAUTH   9
++
++/*-- Status Codes -------------------------------*/
++#define WLAN_MGMT_STATUS_SUCCESS              0
++#define WLAN_MGMT_STATUS_UNSPEC_FAILURE               1
++#define WLAN_MGMT_STATUS_CAPS_UNSUPPORTED     10
++#define WLAN_MGMT_STATUS_REASSOC_NO_ASSOC     11
++#define WLAN_MGMT_STATUS_ASSOC_DENIED_UNSPEC  12
++#define WLAN_MGMT_STATUS_UNSUPPORTED_AUTHALG  13
++#define WLAN_MGMT_STATUS_RX_AUTH_NOSEQ                14
++#define WLAN_MGMT_STATUS_CHALLENGE_FAIL               15
++#define WLAN_MGMT_STATUS_AUTH_TIMEOUT         16
++#define WLAN_MGMT_STATUS_ASSOC_DENIED_BUSY    17
++#define WLAN_MGMT_STATUS_ASSOC_DENIED_RATES   18
++/* p80211b additions */
++#define WLAN_MGMT_STATUS_ASSOC_DENIED_NOSHORT 19
++#define WLAN_MGMT_STATUS_ASSOC_DENIED_NOPBCC  20
++#define WLAN_MGMT_STATUS_ASSOC_DENIED_NOAGILITY       21
++
++/*-- Auth Algorithm Field ---------------------------*/
++#define WLAN_AUTH_ALG_OPENSYSTEM              0
++#define WLAN_AUTH_ALG_SHAREDKEY                       1
++
++/*-- Management Frame Field Offsets -------------*/
++/* Note: Not all fields are listed because of variable lengths */
++/* Note: These offsets are from the start of the frame data */
++
++#define WLAN_BEACON_OFF_TS                    0
++#define WLAN_BEACON_OFF_BCN_INT                       8
++#define WLAN_BEACON_OFF_CAPINFO                       10
++#define WLAN_BEACON_OFF_SSID                  12
++
++#define WLAN_DISASSOC_OFF_REASON              0
++
++#define WLAN_ASSOCREQ_OFF_CAP_INFO            0
++#define WLAN_ASSOCREQ_OFF_LISTEN_INT          2
++#define WLAN_ASSOCREQ_OFF_SSID                        4
++
++#define WLAN_ASSOCRESP_OFF_CAP_INFO           0
++#define WLAN_ASSOCRESP_OFF_STATUS             2
++#define WLAN_ASSOCRESP_OFF_AID                        4
++#define WLAN_ASSOCRESP_OFF_SUPP_RATES         6
++
++#define WLAN_REASSOCREQ_OFF_CAP_INFO          0
++#define WLAN_REASSOCREQ_OFF_LISTEN_INT                2
++#define WLAN_REASSOCREQ_OFF_CURR_AP           4
++#define WLAN_REASSOCREQ_OFF_SSID              10
++
++#define WLAN_REASSOCRESP_OFF_CAP_INFO         0
++#define WLAN_REASSOCRESP_OFF_STATUS           2
++#define WLAN_REASSOCRESP_OFF_AID              4
++#define WLAN_REASSOCRESP_OFF_SUPP_RATES               6
++
++#define WLAN_PROBEREQ_OFF_SSID                        0
++
++#define WLAN_PROBERESP_OFF_TS                 0
++#define WLAN_PROBERESP_OFF_BCN_INT            8
++#define WLAN_PROBERESP_OFF_CAP_INFO           10
++#define WLAN_PROBERESP_OFF_SSID                       12
++
++#define WLAN_AUTHEN_OFF_AUTH_ALG              0
++#define WLAN_AUTHEN_OFF_AUTH_SEQ              2
++#define WLAN_AUTHEN_OFF_STATUS                        4
++#define WLAN_AUTHEN_OFF_CHALLENGE             6
++
++#define WLAN_DEAUTHEN_OFF_REASON              0
++
++enum {
++IEEE16(WF_MGMT_CAP_ESS,               0x0001)
++IEEE16(WF_MGMT_CAP_IBSS,      0x0002)
++/* In (re)assoc request frames by STA:
++** Pollable=0, PollReq=0: STA is not CF-Pollable
++** 0 1: STA is CF-Pollable, not requesting to be placed on the CF-Polling list
++** 1 0: STA is CF-Pollable, requesting to be placed on the CF-Polling list
++** 1 1: STA is CF-Pollable, requesting never to be polled
++** In beacon, proberesp, (re)assoc resp frames by AP:
++** 0 0: No point coordinator at AP
++** 0 1: Point coordinator at AP for delivery only (no polling)
++** 1 0: Point coordinator at AP for delivery and polling
++** 1 1: Reserved  */
++IEEE16(WF_MGMT_CAP_CFPOLLABLE,        0x0004)
++IEEE16(WF_MGMT_CAP_CFPOLLREQ, 0x0008)
++/* 1=non-WEP data frames are disallowed */
++IEEE16(WF_MGMT_CAP_PRIVACY,   0x0010)
++/* In beacon,  proberesp, (re)assocresp by AP/AdHoc:
++** 1=use of shortpre is allowed ("I can receive shortpre") */
++IEEE16(WF_MGMT_CAP_SHORT,     0x0020)
++IEEE16(WF_MGMT_CAP_PBCC,      0x0040)
++IEEE16(WF_MGMT_CAP_AGILITY,   0x0080)
++/* In (re)assoc request frames by STA:
++** 1=short slot time implemented and enabled
++**   NB: AP shall use long slot time beginning at the next Beacon after assoc
++**   of STA with this bit set to 0
++** In beacon, proberesp, (re)assoc resp frames by AP:
++** currently used slot time value: 0/1 - long/short */
++IEEE16(WF_MGMT_CAP_SHORTSLOT, 0x0400)
++/* In (re)assoc request frames by STA: 1=CCK-OFDM is implemented and enabled
++** In beacon, proberesp, (re)assoc resp frames by AP/AdHoc:
++** 1=CCK-OFDM is allowed */
++IEEE16(WF_MGMT_CAP_CCKOFDM,   0x2000)
++};
++
++
++/***********************************************************************
++** Types
++*/
++
++/* Information Element types */
++
++/* prototype structure, all IEs start with these members */
++typedef struct wlan_ie {
++      u8 eid;
++      u8 len;
++} WLAN_PACKED wlan_ie_t;
++
++/*-- Service Set Identity (SSID)  -----------------*/
++typedef struct wlan_ie_ssid {
++      u8 eid;
++      u8 len;
++      u8 ssid[1];     /* may be zero */
++} WLAN_PACKED wlan_ie_ssid_t;
++
++/*-- Supported Rates  -----------------------------*/
++typedef struct wlan_ie_supp_rates {
++      u8 eid;
++      u8 len;
++      u8 rates[1];    /* had better be at LEAST one! */
++} WLAN_PACKED wlan_ie_supp_rates_t;
++
++/*-- FH Parameter Set  ----------------------------*/
++typedef struct wlan_ie_fh_parms {
++      u8 eid;
++      u8 len;
++      u16 dwell;
++      u8 hopset;
++      u8 hoppattern;
++      u8 hopindex;
++} WLAN_PACKED wlan_ie_fh_parms_t;
++
++/*-- DS Parameter Set  ----------------------------*/
++typedef struct wlan_ie_ds_parms {
++      u8 eid;
++      u8 len;
++      u8 curr_ch;
++} WLAN_PACKED wlan_ie_ds_parms_t;
++
++/*-- CF Parameter Set  ----------------------------*/
++typedef struct wlan_ie_cf_parms {
++      u8 eid;
++      u8 len;
++      u8 cfp_cnt;
++      u8 cfp_period;
++      u16 cfp_maxdur;
++      u16 cfp_durremaining;
++} WLAN_PACKED wlan_ie_cf_parms_t;
++
++/*-- TIM ------------------------------------------*/
++typedef struct wlan_ie_tim {
++      u8 eid;
++      u8 len;
++      u8 dtim_cnt;
++      u8 dtim_period;
++      u8 bitmap_ctl;
++      u8 virt_bm[1];
++} WLAN_PACKED wlan_ie_tim_t;
++
++/*-- IBSS Parameter Set ---------------------------*/
++typedef struct wlan_ie_ibss_parms {
++      u8 eid;
++      u8 len;
++      u16 atim_win;
++} WLAN_PACKED wlan_ie_ibss_parms_t;
++
++/*-- Challenge Text  ------------------------------*/
++typedef struct wlan_ie_challenge {
++      u8 eid;
++      u8 len;
++      u8 challenge[1];
++} WLAN_PACKED wlan_ie_challenge_t;
++
++/*-- ERP (42) -------------------------------------*/
++typedef struct wlan_ie_erp {
++      u8 eid;
++      u8 len;
++      /* bit 0:Non ERP present
++      **     1:Use Protection
++      **     2:Barker Preamble mode
++      **     3-7:reserved */
++      u8 erp;
++} WLAN_PACKED wlan_ie_erp_t;
++
++/* Types for parsing mgmt frames */
++
++/* prototype structure, all mgmt frame types will start with these members */
++typedef struct wlan_fr_mgmt {
++      u16 type;
++      u16 len;                /* DOES NOT include FCS */
++      wlan_hdr_t *hdr;
++      /* used for target specific data, skb in Linux */
++      /*-- fixed fields -----------*/
++      /*-- info elements ----------*/
++} WLAN_PACKED wlan_fr_mgmt_t;
++
++/*-- Beacon ---------------------------------------*/
++typedef struct wlan_fr_beacon {
++      u16 type;
++      u16 len;
++      wlan_hdr_t *hdr;
++      /*-- fixed fields -----------*/
++      u64 *ts;
++      u16 *bcn_int;
++      u16 *cap_info;
++      /*-- info elements ----------*/
++      wlan_ie_ssid_t *ssid;
++      wlan_ie_supp_rates_t *supp_rates;
++      wlan_ie_supp_rates_t *ext_rates;
++      wlan_ie_fh_parms_t *fh_parms;
++      wlan_ie_ds_parms_t *ds_parms;
++      wlan_ie_cf_parms_t *cf_parms;
++      wlan_ie_ibss_parms_t *ibss_parms;
++      wlan_ie_tim_t *tim;     /* in beacon only, not proberesp */
++      wlan_ie_erp_t *erp;     /* in beacon only, not proberesp */
++} wlan_fr_beacon_t;
++#define wlan_fr_proberesp wlan_fr_beacon
++#define wlan_fr_proberesp_t wlan_fr_beacon_t
++
++/*-- IBSS ATIM ------------------------------------*/
++typedef struct wlan_fr_ibssatim {
++      u16 type;
++      u16 len;
++      wlan_hdr_t *hdr;
++      /*-- fixed fields -----------*/
++      /*-- info elements ----------*/
++      /* this frame type has a null body */
++} wlan_fr_ibssatim_t;
++
++/*-- Disassociation -------------------------------*/
++typedef struct wlan_fr_disassoc {
++      u16 type;
++      u16 len;
++      wlan_hdr_t *hdr;
++      /*-- fixed fields -----------*/
++      u16 *reason;
++      /*-- info elements ----------*/
++} wlan_fr_disassoc_t;
++
++/*-- Association Request --------------------------*/
++typedef struct wlan_fr_assocreq {
++      u16 type;
++      u16 len;
++      wlan_hdr_t *hdr;
++      /*-- fixed fields -----------*/
++      u16 *cap_info;
++      u16 *listen_int;
++      /*-- info elements ----------*/
++      wlan_ie_ssid_t *ssid;
++      wlan_ie_supp_rates_t *supp_rates;
++      wlan_ie_supp_rates_t *ext_rates;
++} wlan_fr_assocreq_t;
++
++/*-- Association Response -------------------------*/
++typedef struct wlan_fr_assocresp {
++      u16 type;
++      u16 len;
++      wlan_hdr_t *hdr;
++      /*-- fixed fields -----------*/
++      u16 *cap_info;
++      u16 *status;
++      u16 *aid;
++      /*-- info elements ----------*/
++      wlan_ie_supp_rates_t *supp_rates;
++      wlan_ie_supp_rates_t *ext_rates;
++} wlan_fr_assocresp_t;
++
++/*-- Reassociation Request ------------------------*/
++typedef struct wlan_fr_reassocreq {
++      u16 type;
++      u16 len;
++      wlan_hdr_t *hdr;
++      /*-- fixed fields -----------*/
++      u16 *cap_info;
++      u16 *listen_int;
++      u8 *curr_ap;
++      /*-- info elements ----------*/
++      wlan_ie_ssid_t *ssid;
++      wlan_ie_supp_rates_t *supp_rates;
++      wlan_ie_supp_rates_t *ext_rates;
++} wlan_fr_reassocreq_t;
++
++/*-- Reassociation Response -----------------------*/
++typedef struct wlan_fr_reassocresp {
++      u16 type;
++      u16 len;
++      wlan_hdr_t *hdr;
++      /*-- fixed fields -----------*/
++      u16 *cap_info;
++      u16 *status;
++      u16 *aid;
++      /*-- info elements ----------*/
++      wlan_ie_supp_rates_t *supp_rates;
++      wlan_ie_supp_rates_t *ext_rates;
++} wlan_fr_reassocresp_t;
++
++/*-- Probe Request --------------------------------*/
++typedef struct wlan_fr_probereq {
++      u16 type;
++      u16 len;
++      wlan_hdr_t *hdr;
++      /*-- fixed fields -----------*/
++      /*-- info elements ----------*/
++      wlan_ie_ssid_t *ssid;
++      wlan_ie_supp_rates_t *supp_rates;
++      wlan_ie_supp_rates_t *ext_rates;
++} wlan_fr_probereq_t;
++
++/*-- Authentication -------------------------------*/
++typedef struct wlan_fr_authen {
++      u16 type;
++      u16 len;
++      wlan_hdr_t *hdr;
++      /*-- fixed fields -----------*/
++      u16 *auth_alg;
++      u16 *auth_seq;
++      u16 *status;
++      /*-- info elements ----------*/
++      wlan_ie_challenge_t *challenge;
++} wlan_fr_authen_t;
++
++/*-- Deauthenication -----------------------------*/
++typedef struct wlan_fr_deauthen {
++      u16 type;
++      u16 len;
++      wlan_hdr_t *hdr;
++      /*-- fixed fields -----------*/
++      u16 *reason;
++      /*-- info elements ----------*/
++} wlan_fr_deauthen_t;
++
++/* Types for building mgmt frames */
++
++/* Warning. Several types used in below structs are
++** in fact variable length. Use structs with such fields with caution */
++typedef struct auth_frame_body {
++      u16     auth_alg;
++      u16     auth_seq;
++      u16     status;
++      wlan_ie_challenge_t challenge;
++} WLAN_PACKED auth_frame_body_t;
++
++typedef struct assocresp_frame_body {
++      u16     cap_info;
++      u16     status;
++      u16     aid;
++      wlan_ie_supp_rates_t rates;
++} WLAN_PACKED assocresp_frame_body_t;
++
++typedef struct reassocreq_frame_body {
++      u16     cap_info;
++      u16     listen_int;
++      u8      current_ap[ETH_ALEN];
++      wlan_ie_ssid_t ssid;
++/* access to this one is disabled since ssid_t is variable length: */
++     /* wlan_ie_supp_rates_t rates; */
++} WLAN_PACKED reassocreq_frame_body_t;
++
++typedef struct reassocresp_frame_body {
++      u16     cap_info;
++      u16     status;
++      u16     aid;
++      wlan_ie_supp_rates_t rates;
++} WLAN_PACKED reassocresp_frame_body_t;
++
++typedef struct deauthen_frame_body {
++      u16     reason;
++} WLAN_PACKED deauthen_frame_body_t;
++
++typedef struct disassoc_frame_body {
++      u16     reason;
++} WLAN_PACKED disassoc_frame_body_t;
++
++typedef struct probereq_frame_body {
++      wlan_ie_ssid_t ssid;
++      wlan_ie_supp_rates_t rates;
++} WLAN_PACKED probereq_frame_body_t;
++
++typedef struct proberesp_frame_body {
++      u8      timestamp[8];
++      u16     beacon_int;
++      u16     cap_info;
++      wlan_ie_ssid_t ssid;
++/* access to these is disabled since ssid_t is variable length: */
++     /* wlan_ie_supp_rates_t rates; */
++     /* fhps_t        fhps; */
++     /* dsps_t        dsps; */
++     /* cfps_t        cfps; */
++} WLAN_PACKED proberesp_frame_body_t;
++
++
++/***********************************************************************
++** Functions
++*/
++
++/* Helpers for parsing mgmt frames */
++void wlan_mgmt_decode_ibssatim(wlan_fr_ibssatim_t *f);
++void wlan_mgmt_decode_assocreq(wlan_fr_assocreq_t *f);
++void wlan_mgmt_decode_assocresp(wlan_fr_assocresp_t *f);
++void wlan_mgmt_decode_authen(wlan_fr_authen_t *f);
++void wlan_mgmt_decode_beacon(wlan_fr_beacon_t *f);
++void wlan_mgmt_decode_deauthen(wlan_fr_deauthen_t *f);
++void wlan_mgmt_decode_disassoc(wlan_fr_disassoc_t *f);
++void wlan_mgmt_decode_probereq(wlan_fr_probereq_t *f);
++void wlan_mgmt_decode_proberesp(wlan_fr_proberesp_t *f);
++void wlan_mgmt_decode_reassocreq(wlan_fr_reassocreq_t *f);
++void wlan_mgmt_decode_reassocresp(wlan_fr_reassocresp_t *f);
++
++/* Helpers for building mgmt frames */
++static inline u8*
++wlan_fill_ie_ssid(u8 *p, int len, const char *ssid)
++{
++      struct wlan_ie_ssid *ie = (void*)p;
++      ie->eid = WLAN_EID_SSID;
++      ie->len = len;
++      memcpy(ie->ssid, ssid, len);
++      return p + len + 2;
++}
++/* This controls whether we create 802.11g 'ext supported rates' IEs
++** or just create overlong 'supported rates' IEs instead
++** (non-11g compliant) */
++#define WE_OBEY_802_11G 1
++static inline u8*
++wlan_fill_ie_rates(u8 *p, int len, const u8 *rates)
++{
++      struct wlan_ie_supp_rates *ie = (void*)p;
++#if WE_OBEY_802_11G
++      if (len > 8 ) len = 8;
++#endif
++      /* supported rates (1 to 8 octets) */
++      ie->eid = WLAN_EID_SUPP_RATES;
++      ie->len = len;
++      memcpy(ie->rates, rates, len);
++      return p + len + 2;
++}
++/* This one wouldn't create an IE at all if not needed */
++static inline u8*
++wlan_fill_ie_rates_ext(u8 *p, int len, const u8 *rates)
++{
++      struct wlan_ie_supp_rates *ie = (void*)p;
++#if !WE_OBEY_802_11G
++      return p;
++#endif
++      len -= 8;
++      if (len <= 0) return p;
++      /* ext supported rates */
++      ie->eid = WLAN_EID_EXT_RATES;
++      ie->len = len;
++      memcpy(ie->rates, rates+8, len);
++      return p + len + 2;
++}
++static inline u8*
++wlan_fill_ie_ds_parms(u8 *p, int channel)
++{
++      struct wlan_ie_ds_parms *ie = (void*)p;
++      ie->eid = WLAN_EID_DS_PARMS;
++      ie->len = 1;
++      ie->curr_ch = channel;
++      return p + sizeof(*ie);
++}
++static inline u8*
++wlan_fill_ie_ibss_parms(u8 *p, int atim_win)
++{
++      struct wlan_ie_ibss_parms *ie = (void*)p;
++      ie->eid = WLAN_EID_IBSS_PARMS;
++      ie->len = 2;
++      ie->atim_win = atim_win;
++      return p + sizeof(*ie);
++}
++static inline u8*
++wlan_fill_ie_tim(u8 *p,       int rem, int period, int bcast,
++              int ofs, int len, const u8 *vbm)
++{
++      struct wlan_ie_tim *ie = (void*)p;
++      ie->eid = WLAN_EID_TIM;
++      ie->len = len + 3;
++      ie->dtim_cnt = rem;
++      ie->dtim_period = period;
++      ie->bitmap_ctl = ofs | (bcast!=0);
++      if (vbm)
++              memcpy(ie->virt_bm, vbm, len); /* min 1 byte */
++      else
++              ie->virt_bm[0] = 0;
++      return p + len + 3 + 2;
++}
+Index: linux-2.6.22/drivers/net/wireless/Kconfig
+===================================================================
+--- linux-2.6.22.orig/drivers/net/wireless/Kconfig     2007-07-09 01:32:17.000000000 +0200
++++ linux-2.6.22/drivers/net/wireless/Kconfig  2007-08-23 18:34:19.000000000 +0200
+@@ -5,6 +5,36 @@
+ menu "Wireless LAN"
+       depends on !S390
++config NET_RADIO
++      bool "Wireless LAN drivers (non-hamradio) & Wireless Extensions"
++      select WIRELESS_EXT
++      ---help---
++        Support for wireless LANs and everything having to do with radio,
++        but not with amateur radio or FM broadcasting.
++
++        Saying Y here also enables the Wireless Extensions (creates
++        /proc/net/wireless and enables iwconfig access). The Wireless
++        Extension is a generic API allowing a driver to expose to the user
++        space configuration and statistics specific to common Wireless LANs.
++        The beauty of it is that a single set of tool can support all the
++        variations of Wireless LANs, regardless of their type (as long as
++        the driver supports Wireless Extension). Another advantage is that
++        these parameters may be changed on the fly without restarting the
++        driver (or Linux). If you wish to use Wireless Extensions with
++        wireless PCMCIA (PC-) cards, you need to say Y here; you can fetch
++        the tools from
++        <http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>.
++
++config NET_WIRELESS_RTNETLINK
++      bool "Wireless Extension API over RtNetlink"
++      depends on NET_RADIO
++      ---help---
++        Support the Wireless Extension API over the RtNetlink socket
++        in addition to the traditional ioctl interface (selected above).
++
++        For now, few tools use this facility, but it might grow in the
++        future. The only downside is that it adds 4.5 kB to your kernel.
++
+ config WLAN_PRE80211
+       bool "Wireless LAN (pre-802.11)"
+       depends on NETDEVICES
+@@ -549,5 +579,6 @@
+ source "drivers/net/wireless/hostap/Kconfig"
+ source "drivers/net/wireless/bcm43xx/Kconfig"
+ source "drivers/net/wireless/zd1211rw/Kconfig"
++source "drivers/net/wireless/acx/Kconfig"
+ endmenu
+Index: linux-2.6.22/drivers/net/wireless/Makefile
+===================================================================
+--- linux-2.6.22.orig/drivers/net/wireless/Makefile    2007-07-09 01:32:17.000000000 +0200
++++ linux-2.6.22/drivers/net/wireless/Makefile 2007-08-23 18:34:19.000000000 +0200
+@@ -34,6 +34,8 @@
+ obj-$(CONFIG_PRISM54)         += prism54/
++obj-$(CONFIG_ACX)             += acx/
++
+ obj-$(CONFIG_HOSTAP)          += hostap/
+ obj-$(CONFIG_BCM43XX)         += bcm43xx/
+ obj-$(CONFIG_ZD1211RW)                += zd1211rw/
diff --git a/packages/kexecboot/linux-kexecboot-2.6.23/htcuni.patch b/packages/kexecboot/linux-kexecboot-2.6.23/htcuni.patch
new file mode 100644 (file)
index 0000000..4d74674
--- /dev/null
@@ -0,0 +1,8044 @@
+---
+ arch/arm/Kconfig                                         |    2 
+ arch/arm/mach-pxa/Kconfig                                |   89 +
+ arch/arm/mach-pxa/Makefile                               |    1 
+ arch/arm/mach-pxa/corgi.c                                |    3 
+ arch/arm/mach-pxa/generic.c                              |   13 
+ arch/arm/mach-pxa/htcuniversal/Makefile                  |   19 
+ arch/arm/mach-pxa/htcuniversal/htcuniversal.c            |  468 +++++
+ arch/arm/mach-pxa/htcuniversal/htcuniversal_ak4641.c     |  917 +++++++++++
+ arch/arm/mach-pxa/htcuniversal/htcuniversal_ak4641.h     |   65 
+ arch/arm/mach-pxa/htcuniversal/htcuniversal_asic3_leds.c |  143 +
+ arch/arm/mach-pxa/htcuniversal/htcuniversal_bl.c         |   61 
+ arch/arm/mach-pxa/htcuniversal/htcuniversal_bt.c         |  135 +
+ arch/arm/mach-pxa/htcuniversal/htcuniversal_bt.h         |   17 
+ arch/arm/mach-pxa/htcuniversal/htcuniversal_buttons.c    |   87 +
+ arch/arm/mach-pxa/htcuniversal/htcuniversal_core.c       |  226 ++
+ arch/arm/mach-pxa/htcuniversal/htcuniversal_lcd.c        |  212 ++
+ arch/arm/mach-pxa/htcuniversal/htcuniversal_phone.c      |  167 ++
+ arch/arm/mach-pxa/htcuniversal/htcuniversal_phone.h      |   16 
+ arch/arm/mach-pxa/htcuniversal/htcuniversal_pm.c         |   69 
+ arch/arm/mach-pxa/htcuniversal/htcuniversal_power2.c     |   97 +
+ arch/arm/mach-pxa/htcuniversal/htcuniversal_ts2.c        |  490 ++++++
+ arch/arm/mach-pxa/htcuniversal/htcuniversal_udc.c        |   71 
+ arch/arm/mach-pxa/htcuniversal/tsc2046_ts.h              |   20 
+ arch/arm/mach-pxa/spitz.c                                |    2 
+ drivers/input/keyboard/Kconfig                           |    7 
+ drivers/input/keyboard/Makefile                          |    2 
+ drivers/input/keyboard/asic3_keys.c                      |  131 +
+ drivers/leds/Kconfig                                     |    7 
+ drivers/leds/Makefile                                    |    1 
+ drivers/leds/leds-asic3.c                                |  189 ++
+ drivers/mfd/Kconfig                                      |   10 
+ drivers/mfd/Makefile                                     |    2 
+ drivers/mfd/asic3_base.c                                 | 1208 +++++++++++++++
+ drivers/mfd/soc-core.c                                   |  106 +
+ drivers/mfd/soc-core.h                                   |   30 
+ drivers/mmc/host/Kconfig                                 |    6 
+ drivers/mmc/host/Makefile                                |    2 
+ drivers/mmc/host/asic3_mmc.c                             |  900 +++++++++++
+ drivers/mmc/host/asic3_mmc.h                             |   25 
+ drivers/serial/pxa.c                                     |   22 
+ drivers/video/backlight/Kconfig                          |    2 
+ drivers/video/backlight/corgi_bl.c                       |    4 
+ include/asm-arm/arch-pxa/clock.h                         |   27 
+ include/asm-arm/arch-pxa/htcuniversal-asic.h             |  213 ++
+ include/asm-arm/arch-pxa/htcuniversal-gpio.h             |  220 ++
+ include/asm-arm/arch-pxa/htcuniversal-init.h             |   14 
+ include/asm-arm/arch-pxa/htcuniversal.h                  |    3 
+ include/asm-arm/arch-pxa/irqs.h                          |    2 
+ include/asm-arm/arch-pxa/pxa-pm_ll.h                     |    6 
+ include/asm-arm/arch-pxa/pxa-regs.h                      |    2 
+ include/asm-arm/arch-pxa/serial.h                        |   78 
+ include/asm-arm/arch-pxa/sharpsl.h                       |    6 
+ include/asm-arm/hardware/asic3_keys.h                    |   18 
+ include/asm-arm/hardware/asic3_leds.h                    |   34 
+ include/asm-arm/hardware/ipaq-asic3.h                    |  602 +++++++
+ include/linux/backlight.h                                |    7 
+ include/linux/gpiodev.h                                  |   44 
+ include/linux/input_pda.h                                |   47 
+ include/linux/ioport.h                                   |    1 
+ include/linux/soc/asic3_base.h                           |  104 +
+ include/linux/soc/tmio_mmc.h                             |   17 
+ 61 files changed, 7475 insertions(+), 14 deletions(-)
+
+Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/Makefile
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/Makefile       2007-09-11 12:53:37.000000000 +0200
+@@ -0,0 +1,19 @@
++#
++# Makefile for HTC Universal
++#
++
++snd-htcuniversal-ak4641-objs := htcuniversal_ak4641.o
++
++obj-$(CONFIG_MACH_HTCUNIVERSAL)               += htcuniversal.o
++obj-$(CONFIG_HTCUNIVERSAL_CORE)               += htcuniversal_core.o
++obj-$(CONFIG_HTCUNIVERSAL_POWER)      += htcuniversal_power2.o
++obj-$(CONFIG_HTCUNIVERSAL_LCD)                += htcuniversal_lcd.o
++obj-$(CONFIG_HTCUNIVERSAL_BACKLIGHT)  += htcuniversal_bl.o
++obj-$(CONFIG_HTCUNIVERSAL_TS2)                += htcuniversal_ts2.o
++obj-$(CONFIG_HTCUNIVERSAL_BUTTONS)    += htcuniversal_buttons.o
++obj-$(CONFIG_HTCUNIVERSAL_BLUETOOTH)  += htcuniversal_bt.o
++obj-$(CONFIG_HTCUNIVERSAL_PHONE)      += htcuniversal_phone.o
++obj-$(CONFIG_HTCUNIVERSAL_ASIC3_LEDS) += htcuniversal_asic3_leds.o
++obj-$(CONFIG_HTCUNIVERSAL_UDC)                += htcuniversal_udc.o
++
++obj-$(CONFIG_HTCUNIVERSAL_AK4641)     += htcuniversal_ak4641.o
+Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal.c 2007-09-11 12:53:37.000000000 +0200
+@@ -0,0 +1,468 @@
++/*
++ * Hardware definitions for HTC Universal
++ *
++ * Copyright (c) 2006 Oleg Gusev
++ *
++ * Use consistent with the GNU GPL is permitted,
++ * provided that this copyright notice is
++ * preserved in its entirety in all copies and derived works.
++ *
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/platform_device.h>
++#include <linux/irq.h>
++#include <linux/input.h>
++#include <linux/gpio_keys.h>
++#include <linux/soc/asic3_base.h>
++
++#include <asm/mach-types.h>
++#include <asm/hardware.h>
++#include <asm/setup.h>
++
++#include <asm/mach/irq.h>
++#include <asm/mach/arch.h>
++
++#include <asm/arch/bitfield.h>
++#include <asm/arch/pxa-regs.h>
++#include <asm/arch/serial.h>
++#include <asm/arch/pxa27x_keyboard.h>
++#include <asm/arch/pxafb.h>
++#include <asm/arch/irda.h>
++#include <asm/arch/ohci.h>
++
++#include <asm/arch/htcuniversal.h>
++#include <asm/arch/htcuniversal-gpio.h>
++#include <asm/arch/htcuniversal-init.h>
++#include <asm/arch/htcuniversal-asic.h>
++
++#include <asm/hardware/ipaq-asic3.h>
++
++#include "../generic.h"
++
++#include "htcuniversal_bt.h"
++#include "htcuniversal_phone.h"
++#include "tsc2046_ts.h"
++
++/*
++ * IRDA
++ */
++
++static void htcuniversal_irda_transceiver_mode(struct device *dev, int mode)
++{
++ /* */
++}
++
++static struct pxaficp_platform_data htcuniversal_ficp_platform_data = {
++      .transceiver_cap  = IR_SIRMODE | IR_FIRMODE,
++      .transceiver_mode = htcuniversal_irda_transceiver_mode,
++};
++
++/*
++ * Bluetooth - Relies on other loadable modules, like ASIC3 and Core,
++ * so make the calls indirectly through pointers. Requires that the
++ * htcuniversal_bt module be loaded before any attempt to use
++ * bluetooth (obviously).
++ */
++
++static struct htcuniversal_bt_funcs bt_funcs;
++
++static void
++htcuniversal_bt_configure( int state )
++{
++      if (bt_funcs.configure != NULL)
++              bt_funcs.configure( state );
++}
++
++static struct htcuniversal_phone_funcs phone_funcs;
++
++static void
++htcuniversal_phone_configure( int state )
++{
++      if (phone_funcs.configure != NULL)
++              phone_funcs.configure( state );
++}
++
++//void htcuniversal_ll_pm_init(void);
++
++extern struct platform_device htcuniversal_bl;
++static struct platform_device htcuniversal_lcd       = { .name = "htcuniversal_lcd", };
++//static struct platform_device htcuniversal_kbd       = { .name = "htcuniversal_kbd", };
++static struct platform_device htcuniversal_buttons   = { .name = "htcuniversal_buttons", };
++//static struct platform_device htcuniversal_ts        = { .name = "htcuniversal_ts", };
++//static struct platform_device htcuniversal_bt        = { .name = "htcuniversal_bt", };
++//static struct platform_device htcuniversal_phone        = { .name = "htcuniversal_phone", };
++static struct platform_device htcuniversal_power        = { .name = "htcuniversal_power", };
++static struct platform_device htcuniversal_udc       = { .name = "htcuniversal_udc", };
++
++static struct tsc2046_mach_info htcuniversal_ts_platform_data = {
++       .port     = 1,
++       .clock    = CKEN_SSP1,
++       .pwrbit_X = 1,
++       .pwrbit_Y = 1,
++       .irq    = 0  /* asic3 irq */
++};
++
++static struct platform_device htcuniversal_ts        = {
++       .name = "htcuniversal_ts",
++       .dev  = {
++              .platform_data = &htcuniversal_ts_platform_data,
++       },
++};
++
++
++/* Bluetooth */
++
++static struct platform_device htcuniversal_bt = {
++      .name = "htcuniversal_bt",
++      .id = -1,
++      .dev = {
++              .platform_data = &bt_funcs,
++      },
++};
++
++static struct platform_device htcuniversal_phone = {
++      .name = "htcuniversal_phone",
++      .id = -1,
++      .dev = {
++              .platform_data = &phone_funcs,
++      },
++};
++
++/* PXA2xx Keys */
++
++static struct gpio_keys_button htcuniversal_button_table[] = {
++      { KEY_POWER, GPIO_NR_HTCUNIVERSAL_KEY_ON_N, 1 },
++};
++
++static struct gpio_keys_platform_data htcuniversal_pxa_keys_data = {
++      .buttons = htcuniversal_button_table,
++      .nbuttons = ARRAY_SIZE(htcuniversal_button_table),
++};
++
++static struct platform_device htcuniversal_pxa_keys = {
++      .name = "gpio-keys",
++      .dev = {
++              .platform_data = &htcuniversal_pxa_keys_data,
++      },
++      .id = -1,
++};
++
++/****************************************************************
++ * Keyboard
++ ****************************************************************/
++
++static struct pxa27x_keyboard_platform_data htcuniversal_kbd = {
++      .nr_rows = 8,
++      .nr_cols = 8,
++      .keycodes = {
++              {
++                      /* row 0 */
++                      KEY_ENTER,
++                      KEY_MINUS,
++                      KEY_ESC,
++                      KEY_1,
++                      KEY_TAB,
++                      KEY_CAPSLOCK,
++                      KEY_LEFTSHIFT,
++                      KEY_RIGHTALT,   /* Fn */
++              }, {    /* row 1 */
++                      KEY_COMMA,
++                      KEY_EQUAL,
++                      KEY_F1,
++                      KEY_2,
++                      KEY_Q,
++                      KEY_A,
++                      KEY_Z,
++                      KEY_LEFTCTRL,
++              }, {    /* row 2 */
++                      KEY_UP,
++                      KEY_I,
++                      KEY_F2,
++                      KEY_3,
++                      KEY_W,
++                      KEY_S,
++                      KEY_X,
++                      KEY_F6,
++              }, {    /* row 3 */
++                      KEY_DOT,
++                      KEY_O,
++                      KEY_F3,
++                      KEY_4,
++                      KEY_E,
++                      KEY_D,
++                      KEY_C,
++                      KEY_LEFTALT,
++              }, {    /* row 4 */
++                      KEY_F9,
++                      KEY_P,
++                      KEY_F4,
++                      KEY_5,
++                      KEY_R,
++                      KEY_F,
++                      KEY_V,
++                      KEY_SPACE,
++              }, {    /* row 5 */
++                      KEY_RIGHT,
++                      KEY_BACKSPACE,
++                      KEY_F5,
++                      KEY_6,
++                      KEY_T,
++                      KEY_G,
++                      KEY_B,
++                      KEY_F7,
++              }, {    /* row 6 */
++                      KEY_F9,
++                      KEY_K,
++                      KEY_9,
++                      KEY_7,
++                      KEY_Y,
++                      KEY_H,
++                      KEY_N,
++                      KEY_LEFT,
++              }, {    /* row 7 */
++                      KEY_F10,
++                      KEY_L,
++                      KEY_0,
++                      KEY_8,
++                      KEY_U,
++                      KEY_J,
++                      KEY_M,
++                      KEY_DOWN,
++              },
++      },
++      .gpio_modes = {
++               GPIO_NR_HTCUNIVERSAL_KP_MKIN0_MD,
++               GPIO_NR_HTCUNIVERSAL_KP_MKIN1_MD,
++               GPIO_NR_HTCUNIVERSAL_KP_MKIN2_MD,
++               GPIO_NR_HTCUNIVERSAL_KP_MKIN3_MD,
++               GPIO_NR_HTCUNIVERSAL_KP_MKIN4_MD,
++               GPIO_NR_HTCUNIVERSAL_KP_MKIN5_MD,
++               GPIO_NR_HTCUNIVERSAL_KP_MKIN6_MD,
++               GPIO_NR_HTCUNIVERSAL_KP_MKIN7_MD,
++               GPIO_NR_HTCUNIVERSAL_KP_MKOUT0_MD,
++               GPIO_NR_HTCUNIVERSAL_KP_MKOUT1_MD,
++               GPIO_NR_HTCUNIVERSAL_KP_MKOUT2_MD,
++               GPIO_NR_HTCUNIVERSAL_KP_MKOUT3_MD,
++               GPIO_NR_HTCUNIVERSAL_KP_MKOUT4_MD,
++               GPIO_NR_HTCUNIVERSAL_KP_MKOUT5_MD,
++               GPIO_NR_HTCUNIVERSAL_KP_MKOUT6_MD,
++               GPIO_NR_HTCUNIVERSAL_KP_MKOUT7_MD,
++       },
++};
++
++static struct platform_device htcuniversal_pxa_keyboard = {
++        .name   = "pxa27x-keyboard",
++        .id     = -1,
++      .dev    =  {
++              .platform_data  = &htcuniversal_kbd,
++      },
++};
++/* Core Hardware Functions */
++
++struct platform_device htcuniversal_core = {
++      .name           = "htcuniversal_core",
++      .id             = 0,
++      .dev = {
++              .platform_data = NULL,
++      },
++};
++
++static struct platform_device *devices[] __initdata = {
++      &htcuniversal_core,
++//    &htcuniversal_flash,
++      &htcuniversal_pxa_keyboard,
++      &htcuniversal_pxa_keys,
++};
++
++static struct platform_device *htcuniversal_asic3_devices[] __initdata = {
++      &htcuniversal_lcd,
++#ifdef CONFIG_HTCUNIVERSAL_BACKLIGHT
++      &htcuniversal_bl,
++#endif
++      &htcuniversal_buttons,
++      &htcuniversal_ts,
++      &htcuniversal_bt,
++      &htcuniversal_phone,
++      &htcuniversal_power,
++      &htcuniversal_udc,
++};
++
++static struct asic3_platform_data htcuniversal_asic3_platform_data = {
++
++   /* Setting ASIC3 GPIO registers to the below initialization states
++    * HTC Universal asic3 information:
++    * http://wiki.xda-developers.com/index.php?pagename=UniversalASIC3
++    * http://wiki.xda-developers.com/index.php?pagename=ASIC3
++    *
++    * dir:    Direction of the GPIO pin. 0: input, 1: output.
++    *         If unknown, set as output to avoid power consuming floating input nodes
++    * init:   Initial state of the GPIO bits
++    *
++    * These registers are configured as they are on Wince.
++    */
++        .gpio_a = {
++              .dir            = (1<<GPIOA_LCD_PWR5_ON)    |
++                                (1<<GPIOA_FLASHLIGHT)     |
++                                (1<<GPIOA_UNKNOWN9)       |
++                                (1<<GPIOA_SPK_PWR2_ON)    |
++                                (1<<GPIOA_UNKNOWN4)       |
++                                (1<<GPIOA_EARPHONE_PWR_ON)|
++                                (1<<GPIOA_AUDIO_PWR_ON)   |
++                                (1<<GPIOA_SPK_PWR1_ON)    |
++                                (1<<GPIOA_I2C_EN),
++              .init           = (1<<GPIOA_LCD_PWR5_ON)    |
++                                (1<<GPIOA_I2C_EN),
++              .sleep_out      = 0x0000,
++              .batt_fault_out = 0x0000,
++              .alt_function   = 0x0000,
++              .sleep_conf     = 0x000c,
++        },
++        .gpio_b = {
++              .dir            = 0xc142,
++              .init           = 0x8842, // TODO: 0x0900
++              .sleep_out      = 0x0000,
++              .batt_fault_out = 0x0000,
++              .alt_function   = 0x0000,
++                .sleep_conf     = 0x000c,
++        },
++        .gpio_c = {
++                .dir            = 0xc7e7,
++                .init           = 0xc6e0, // TODO: 0x8000
++                .sleep_out      = 0x0000,
++                .batt_fault_out = 0x0000,
++              .alt_function   = 0x0007, // GPIOC_LED_RED | GPIOC_LED_GREEN | GPIOC_LED_BLUE
++                .sleep_conf     = 0x000c,
++        },
++        .gpio_d = {
++              .dir            = 0xffc0,
++              .init           = 0x7840, // TODO: 0x0000
++              .sleep_out      = 0x0000,
++              .batt_fault_out = 0x0000,
++              .alt_function   = 0x0000,
++              .sleep_conf     = 0x0008,
++        },
++      .bus_shift = 1,
++      .irq_base = HTCUNIVERSAL_ASIC3_IRQ_BASE,
++
++      .child_platform_devs     = htcuniversal_asic3_devices,
++      .num_child_platform_devs = ARRAY_SIZE(htcuniversal_asic3_devices),
++};
++
++static struct resource htcuniversal_asic3_resources[] = {
++      [0] = {
++              .start  = HTCUNIVERSAL_ASIC3_GPIO_PHYS,
++              .end    = HTCUNIVERSAL_ASIC3_GPIO_PHYS + IPAQ_ASIC3_MAP_SIZE,
++              .flags  = IORESOURCE_MEM,
++      },
++      [1] = {
++              .start  = HTCUNIVERSAL_IRQ(ASIC3_EXT_INT),
++              .end    = HTCUNIVERSAL_IRQ(ASIC3_EXT_INT),
++              .flags  = IORESOURCE_IRQ,
++      },
++      [2] = {
++              .start  = HTCUNIVERSAL_ASIC3_MMC_PHYS,
++              .end    = HTCUNIVERSAL_ASIC3_MMC_PHYS + IPAQ_ASIC3_MAP_SIZE,
++              .flags  = IORESOURCE_MEM,
++      },
++      [3] = {
++              .start  = HTCUNIVERSAL_IRQ(ASIC3_SDIO_INT_N),
++              .flags  = IORESOURCE_IRQ,
++      },
++};
++
++struct platform_device htcuniversal_asic3 = {
++      .name           = "asic3",
++      .id             = 0,
++      .num_resources  = ARRAY_SIZE(htcuniversal_asic3_resources),
++      .resource       = htcuniversal_asic3_resources,
++      .dev = { .platform_data = &htcuniversal_asic3_platform_data, },
++};
++EXPORT_SYMBOL(htcuniversal_asic3);
++
++static struct pxafb_mode_info htcuniversal_lcd_modes[] = {
++{
++      .pixclock               = 96153,
++      .xres                   = 480,
++      .yres                   = 640,
++      .bpp                    = 16,
++      .hsync_len              = 4,
++      .vsync_len              = 1,
++      .left_margin            = 20,
++      .right_margin           = 8,
++      .upper_margin           = 7,
++      .lower_margin           = 8,
++
++//    .sync                   = FB_SYNC_HOR_LOW_ACT|FB_SYNC_VERT_LOW_ACT,
++
++},
++};
++
++static struct pxafb_mach_info sony_acx526akm = {
++        .modes                = htcuniversal_lcd_modes,
++        .num_modes    = ARRAY_SIZE(htcuniversal_lcd_modes),
++
++      /* fixme: use constants defined in pxafb.h */
++      .lccr0                  = 0x00000080,
++      .lccr3                  = 0x00400000,
++//    .lccr4                  = 0x80000000,
++};
++
++static void __init htcuniversal_init_irq(void)
++{
++      pxa27x_init_irq();
++}
++
++static struct platform_pxa_serial_funcs htcuniversal_pxa_bt_funcs = {
++      .configure = htcuniversal_bt_configure,
++};
++static struct platform_pxa_serial_funcs htcuniversal_pxa_phone_funcs = {
++      .configure = htcuniversal_phone_configure,
++};
++
++/* USB OHCI */
++
++static int htcuniversal_ohci_init(struct device *dev)
++{
++      /* missing GPIO setup here */
++
++      /* got the value from wince */
++      UHCHR=UHCHR_CGR;
++
++      return 0;
++}
++
++static struct pxaohci_platform_data htcuniversal_ohci_platform_data = {
++      .port_mode = PMM_PERPORT_MODE,
++      .init = htcuniversal_ohci_init,
++};
++
++static void __init htcuniversal_map_io(void)
++{
++      pxa_map_io();
++
++      pxa_set_btuart_info(&htcuniversal_pxa_bt_funcs);
++      pxa_set_ffuart_info(&htcuniversal_pxa_phone_funcs);
++}
++
++static void __init htcuniversal_init(void)
++{
++      set_pxa_fb_info(&sony_acx526akm);
++
++      platform_device_register(&htcuniversal_asic3);
++      platform_add_devices(devices, ARRAY_SIZE(devices) );
++      pxa_set_ficp_info(&htcuniversal_ficp_platform_data);
++      pxa_set_ohci_info(&htcuniversal_ohci_platform_data);
++}
++
++MACHINE_START(HTCUNIVERSAL, "HTC Universal")
++      /* Maintainer xanadux.org */
++      .phys_io        = 0x40000000,
++      .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
++      .boot_params    = 0xa0000100,
++      .map_io         = htcuniversal_map_io,
++      .init_irq       = htcuniversal_init_irq,
++      .init_machine   = htcuniversal_init,
++      .timer          = &pxa_timer,
++MACHINE_END
+Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_ak4641.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_ak4641.c  2007-09-11 12:53:37.000000000 +0200
+@@ -0,0 +1,917 @@
++/*
++ * Audio support for codec Asahi Kasei AK4641
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * Copyright (c) 2006 Giorgio Padrin <giorgio@mandarinlogiq.org>
++ *
++ * History:
++ *
++ * 2006-03    Written -- Giorgio Padrin
++ * 2006-09    Test and debug on machine (HP hx4700) -- Elshin Roman <roxmail@list.ru>
++ *
++ * AK4641 codec device driver
++ *
++ * Copyright (c) 2005 SDG Systems, LLC
++ *
++ * Based on code:
++ *   Copyright (c) 2002 Hewlett-Packard Company
++ *   Copyright (c) 2000 Nicolas Pitre <nico@cam.org>
++ *   Copyright (c) 2000 Lernout & Hauspie Speech Products, N.V.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License.
++ */
++
++#include <sound/driver.h>
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/types.h>
++#include <linux/string.h>
++#include <linux/slab.h>
++#include <linux/errno.h>
++#include <linux/ioctl.h>
++#include <linux/delay.h>
++#include <linux/i2c.h>
++
++#include <sound/core.h>
++#include <sound/control.h>
++#include <sound/initval.h>
++#include <sound/info.h>
++
++#include "htcuniversal_ak4641.h"
++
++/* Registers */
++#define R_PM1         0x00
++#define R_PM2         0x01
++#define R_SEL1                0x02
++#define R_SEL2                0x03
++#define       R_MODE1         0x04
++#define R_MODE2               0x05
++#define R_DAC         0x06
++#define R_MIC         0x07
++#define REG_TIMER     0x08
++#define REG_ALC1      0x09
++#define REG_ALC2      0x0a
++#define R_PGA         0x0b
++#define R_ATTL                0x0c
++#define R_ATTR                0x0d
++#define REG_VOL               0x0e
++#define R_STATUS      0x0f
++#define REG_EQLO      0x10
++#define REG_EQMID     0x11
++#define REG_EQHI      0x12
++#define REG_BTIF      0x13
++
++/* Register flags */
++/* REG_PWR1 */
++#define R_PM1_PMADC   0x01
++#define R_PM1_PMMIC   0x02
++#define REG_PWR1_PMAUX  0x04
++#define REG_PWR1_PMMO   0x08
++#define R_PM1_PMLO    0x10
++/* unused               0x20 */
++/* unused               0x40 */
++#define R_PM1_PMVCM   0x80
++
++/* REG_PWR2 */
++#define R_PM2_PMDAC   0x01
++/* unused               0x02 */
++/* unused               0x04 */
++#define R_PM2_PMMO2   0x08
++#define REG_PWR2_MCKAC  0x10
++/* unused               0x20 */
++/* unused               0x40 */
++#define R_PM2_MCKPD   0x80
++
++/* REG_SEL1 */
++#define R_SEL1_PSMO2  0x01
++/* unused               0x02 */
++/* unused               0x04 */
++/* unused               0x08 */
++#define REG_SEL1_MICM   0x10
++#define REG_SEL1_DACM   0x20
++#define REG_SEL1_PSMO   0x40
++#define REG_SEL1_MOGN   0x80
++
++/* REG_SEL2 */
++#define R_SEL2_PSLOR  0x01
++#define R_SEL2_PSLOL  0x02
++#define REG_SEL2_AUXSI  0x04
++/* unused               0x08 */
++#define REG_SEL2_MICL   0x10
++#define REG_SEL2_AUXL   0x20
++/* unused               0x40 */
++#define R_SEL2_DACL   0x80
++
++/* REG_MODE1 */
++#define REG_MODE1_DIF0  0x01
++#define REG_MODE1_DIF1  0x02
++/* unused               0x04 */
++/* unused               0x08 */
++/* unused               0x10 */
++/* unused               0x20 */
++/* unused               0x40 */
++/* unused               0x80 */
++
++/* REG_MODE2 */
++/* unused               0x01 */
++#define REG_MODE2_LOOP  0x02
++#define REG_MODE2_HPM   0x04
++/* unused               0x08 */
++/* unused               0x10 */
++#define REG_MODE2_MCK0  0x20
++#define REG_MODE2_MCK1  0x40
++/* unused               0x80 */
++
++/* REG_DAC */
++#define REG_DAC_DEM0    0x01
++#define REG_DAC_DEM1    0x02
++#define REG_DAC_EQ      0x04
++/* unused               0x08 */
++#define R_DAC_DATTC   0x10
++#define R_DAC_SMUTE   0x20
++#define REG_DAC_TM      0x40
++/* unused               0x80 */
++
++/* REG_MIC */
++#define R_MIC_MGAIN   0x01
++#define R_MIC_MSEL    0x02
++#define R_MIC_MICAD   0x04
++#define R_MIC_MPWRI   0x08
++#define R_MIC_MPWRE   0x10
++#define REG_MIC_AUXAD   0x20
++/* unused               0x40 */
++/* unused               0x80 */
++
++/* REG_TIMER */
++
++#define REG_TIMER_LTM0  0x01
++#define REG_TIMER_LTM1  0x02
++#define REG_TIMER_WTM0  0x04
++#define REG_TIMER_WTM1  0x08
++#define REG_TIMER_ZTM0  0x10
++#define REG_TIMER_ZTM1  0x20
++/* unused               0x40 */
++/* unused               0x80 */
++
++#define REG_ALC1_LMTH   0x01
++#define REG_ALC1_RATT   0x02
++#define REG_ALC1_LMAT0  0x04
++#define REG_ALC1_LMAT1  0x08
++#define REG_ALC1_ZELM   0x10
++#define REG_ALC1_ALC1   0x20
++/* unused               0x40 */
++/* unused               0x80 */
++
++/* REG_ALC2 */
++
++/* REG_PGA */
++
++/* REG_ATTL */
++
++/* REG_ATTR */
++
++/* REG_VOL */
++#define REG_VOL_ATTM  0x80
++
++/* REG_STATUS */
++#define R_STATUS_DTMIC        0x01
++
++/* REG_EQ controls use 4 bits for each of 5 EQ levels */
++
++/* Bluetooth not yet implemented */
++#define REG_BTIF_PMAD2  0x01
++#define REG_BTIF_PMDA2  0x02
++#define REG_BTIF_PMBIF  0x04
++#define REG_BTIF_ADC2   0x08
++#define REG_BTIF_DAC2   0x10
++#define REG_BTIF_BTFMT0 0x20
++#define REG_BTIF_BTFMT1 0x40
++/* unused               0x80 */
++
++/* begin {{ I2C }} */
++
++static struct i2c_driver snd_ak4641_i2c_driver = {
++      .driver = {
++              .name = "ak4641-i2c"
++      },
++};
++
++static int snd_ak4641_i2c_init(void)
++{
++      return i2c_add_driver(&snd_ak4641_i2c_driver);
++}
++
++static void snd_ak4641_i2c_free(void)
++{
++      i2c_del_driver(&snd_ak4641_i2c_driver);
++}
++
++static inline int snd_ak4641_i2c_probe(struct snd_ak4641 *ak)
++{
++      if (ak->i2c_client.adapter == NULL) return -EINVAL;
++      ak->i2c_client.addr = 0x12;
++      if (i2c_smbus_xfer(ak->i2c_client.adapter, ak->i2c_client.addr,
++                         0, 0, 0, I2C_SMBUS_QUICK, NULL) < 0)
++              return -ENODEV;
++      else return 0;
++}
++
++static int snd_ak4641_i2c_attach(struct snd_ak4641 *ak)
++{
++      int ret = 0;
++      if ((ret = snd_ak4641_i2c_probe(ak)) < 0) return ret;
++      snprintf(ak->i2c_client.name, sizeof(ak->i2c_client.name),
++               "ak4641-i2c at %d-%04x",
++               i2c_adapter_id(ak->i2c_client.adapter), ak->i2c_client.addr);
++      return i2c_attach_client(&ak->i2c_client);
++}
++
++static void snd_ak4641_i2c_detach(struct snd_ak4641 *ak)
++{
++      i2c_detach_client(&ak->i2c_client);
++}
++
++/* end {{ I2C }} */
++
++
++/* begin {{ Registers & Cache Ops }} */
++
++static int snd_ak4641_hwsync(struct snd_ak4641 *ak, int read, u8 reg)
++{
++      struct i2c_msg msgs[2];
++      u8 buf[2];
++      int ret;
++
++      snd_assert(reg < ARRAY_SIZE(ak->regs), return -EINVAL);
++
++      /* setup i2c msgs */
++      msgs[0].addr = ak->i2c_client.addr;
++      msgs[0].flags = 0;
++      msgs[0].buf = buf;
++      if (!read)
++              msgs[0].len = 2;
++      else {
++              msgs[1].flags = I2C_M_RD;
++              msgs[1].addr = msgs[0].addr;
++              msgs[1].buf = msgs[0].buf + 1;
++              msgs[0].len = 1;
++              msgs[1].len = 1;
++      }
++
++      buf[0] = reg;
++
++      /* regs[reg] -> buffer, on write */
++      if (!read) buf[1] = ak->regs[reg];
++
++      /* i2c transfer */
++      ret = i2c_transfer(ak->i2c_client.adapter, msgs, read ? 2 : 1);
++      if (ret != (read ? 2 : 1)) return ret; /* transfer error */ //@@ error ret < 0, or not ?
++
++      /* regs[reg] <- buffer, on read */
++      if (read) ak->regs[reg] = buf[1];
++
++      return 0;
++}
++
++static inline int snd_ak4641_hwsync_read(struct snd_ak4641 *ak, u8 reg)
++{
++      return snd_ak4641_hwsync(ak, 1, reg);
++}
++
++static inline int snd_ak4641_hwsync_write(struct snd_ak4641 *ak, u8 reg)
++{
++      return snd_ak4641_hwsync(ak, 0, reg);
++}
++
++static int snd_ak4641_hwsync_read_all(struct snd_ak4641 *ak)
++{
++      u8 reg;
++      for (reg = 0; reg < ARRAY_SIZE(ak->regs); reg++)
++              if (snd_ak4641_hwsync_read(ak, reg) < 0) return -1;
++      return 0;
++}
++
++static int snd_ak4641_hwsync_write_all(struct snd_ak4641 *ak)
++{
++      u8 reg;
++      for (reg = 0; reg < ARRAY_SIZE(ak->regs); reg++)
++              if (snd_ak4641_hwsync_write(ak, reg) < 0) return -1;
++      return 0;
++}
++
++static int snd_ak4641_reg_changed(struct snd_ak4641 *ak, u8 reg)
++{
++      if ((reg != R_PGA && ak->powered_on) ||
++          (reg == R_PGA && (ak->regs[R_PM1] & R_PM1_PMMIC)))
++              return snd_ak4641_hwsync_write(ak, reg);
++      return 0;
++}
++
++/* end {{ Registers & Cache Ops }}*/
++
++
++static inline void snd_ak4641_lock(struct snd_ak4641 *ak)
++{
++      down(&ak->sem);
++}
++
++static inline void snd_ak4641_unlock(struct snd_ak4641 *ak)
++{
++      up(&ak->sem);
++}
++
++#define WRITE_MASK(i, val, mask)      (((i) & ~(mask)) | ((val) & (mask)))
++
++
++/* begin {{ Controls }} */
++
++#define INV_RANGE(val, mask) \
++      (~(val) & (mask))
++
++/*-begin----------------------------------------------------------*/
++static int snd_ak4641_actl_playback_volume_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 = 0xff;
++      return 0;
++}
++
++static int snd_ak4641_actl_playback_volume_get(struct snd_kcontrol *kcontrol,
++                                             struct snd_ctl_elem_value *ucontrol)
++{
++      struct snd_ak4641 *ak = (struct snd_ak4641 *) kcontrol->private_data;
++
++      snd_ak4641_lock(ak);
++      ucontrol->value.integer.value[0] = INV_RANGE(ak->regs[R_ATTL], 0xff);
++      ucontrol->value.integer.value[1] = INV_RANGE(ak->regs[R_ATTR], 0xff);
++      snd_ak4641_unlock(ak);
++      return 0;
++}
++
++static int snd_ak4641_actl_playback_volume_put(struct snd_kcontrol *kcontrol,
++                                             struct snd_ctl_elem_value *ucontrol)
++{
++      struct snd_ak4641 *ak = (struct snd_ak4641 *) kcontrol->private_data;
++
++      snd_ak4641_lock(ak);
++      ak->regs[R_ATTL] = INV_RANGE(ucontrol->value.integer.value[0], 0xff);
++      ak->regs[R_ATTR] = INV_RANGE(ucontrol->value.integer.value[1], 0xff);
++      snd_ak4641_reg_changed(ak, R_ATTL);
++      snd_ak4641_reg_changed(ak, R_ATTR);
++      snd_ak4641_unlock(ak);
++      return 0;
++}
++/*-end------------------------------------------------------------*/
++
++/*-begin----------------------------------------------------------*/
++static int snd_ak4641_actl_mic_gain_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 = 0x7f;
++      return 0;
++}
++
++static int snd_ak4641_actl_mic_gain_get(struct snd_kcontrol *kcontrol,
++                                      struct snd_ctl_elem_value *ucontrol)
++{
++      struct snd_ak4641 *ak = (struct snd_ak4641 *) kcontrol->private_data;
++
++      ucontrol->value.integer.value[0] = ak->regs[R_PGA];
++      return 0;
++}
++
++static int snd_ak4641_actl_mic_gain_put(struct snd_kcontrol *kcontrol,
++                                      struct snd_ctl_elem_value *ucontrol)
++{
++      struct snd_ak4641 *ak = (struct snd_ak4641 *) kcontrol->private_data;
++
++      snd_ak4641_lock(ak);
++      ak->regs[R_PGA] = ucontrol->value.integer.value[0];
++      snd_ak4641_reg_changed(ak, R_PGA);
++      snd_ak4641_unlock(ak);
++      return 0;
++}
++/*-end------------------------------------------------------------*/
++
++#define ACTL(ctl_name, _name) \
++static struct snd_kcontrol_new snd_ak4641_actl_ ## ctl_name = \
++{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = _name, \
++  .info = snd_ak4641_actl_ ## ctl_name ## _info, \
++  .get = snd_ak4641_actl_ ## ctl_name ## _get, .put = snd_ak4641_actl_ ## ctl_name ## _put };
++
++ACTL(playback_volume, "Master Playback Volume")
++ACTL(mic_gain, "Mic Capture Gain")
++
++struct snd_ak4641_uctl_bool {
++      int (*get) (struct snd_ak4641 *uda);
++      int (*set) (struct snd_ak4641 *uda, int on);
++};
++
++static int snd_ak4641_actl_bool_info(struct snd_kcontrol *kcontrol,
++                                    struct snd_ctl_elem_info *uinfo)
++{
++      uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
++      uinfo->count = 1;
++      return 0;
++}
++
++static int snd_ak4641_actl_bool_get(struct snd_kcontrol *kcontrol,
++                                   struct snd_ctl_elem_value *ucontrol)
++{
++      struct snd_ak4641 *ak = (struct snd_ak4641 *) kcontrol->private_data;
++      struct snd_ak4641_uctl_bool *uctl =
++              (struct snd_ak4641_uctl_bool *) kcontrol->private_value;
++
++      ucontrol->value.integer.value[0] = uctl->get(ak);
++      return 0;
++}
++
++static int snd_ak4641_actl_bool_put(struct snd_kcontrol *kcontrol,
++                                   struct snd_ctl_elem_value *ucontrol)
++{
++      struct snd_ak4641 *ak = (struct snd_ak4641 *) kcontrol->private_data;
++      struct snd_ak4641_uctl_bool *uctl =
++              (struct snd_ak4641_uctl_bool *) kcontrol->private_value;
++
++      return uctl->set(ak, ucontrol->value.integer.value[0]);
++}
++
++/*-begin----------------------------------------------------------*/
++static int snd_ak4641_uctl_playback_switch_get(struct snd_ak4641 *ak)
++{
++      return (ak->regs[R_DAC] & R_DAC_SMUTE) == 0x00;
++}
++
++static int snd_ak4641_uctl_playback_switch_set(struct snd_ak4641 *ak, int on)
++{
++      snd_ak4641_lock(ak);
++      ak->regs[R_DAC] = WRITE_MASK(ak->regs[R_DAC],
++                                   on ? 0x00 : R_DAC_SMUTE, R_DAC_SMUTE);
++      snd_ak4641_reg_changed(ak, R_DAC);
++      snd_ak4641_unlock(ak);
++      return 0;
++}
++/*-end------------------------------------------------------------*/
++
++/*-begin----------------------------------------------------------*/
++static int snd_ak4641_uctl_mic_boost_get(struct snd_ak4641 *ak)
++{
++      return (ak->regs[R_MIC] & R_MIC_MGAIN) == R_MIC_MGAIN;
++}
++
++static int snd_ak4641_uctl_mic_boost_set(struct snd_ak4641 *ak, int on)
++{
++      snd_ak4641_lock(ak);
++      ak->regs[R_MIC] = WRITE_MASK(ak->regs[R_MIC],
++                                   on ? R_MIC_MGAIN : 0x00, R_MIC_MGAIN);
++      snd_ak4641_reg_changed(ak, R_MIC);
++      snd_ak4641_unlock(ak);
++      return 0;
++}
++/*-end------------------------------------------------------------*/
++
++/*-begin----------------------------------------------------------*/
++static int snd_ak4641_uctl_mono_out_get(struct snd_ak4641 *ak)
++{
++        printk("mono_out status 0x%8.8x -> 0x%8.8x\n",ak->regs[R_SEL1], ak->regs[R_SEL1] & REG_SEL1_PSMO);
++      return (ak->regs[R_SEL1] & REG_SEL1_PSMO) == REG_SEL1_PSMO;
++}
++
++static int snd_ak4641_uctl_mono_out_set(struct snd_ak4641 *ak, int on)
++{
++        printk("phone mic enable called. on=%d\n",on);
++      snd_ak4641_lock(ak);
++      ak->regs[R_PM1] = WRITE_MASK(ak->regs[R_PM1], on ? R_PM1_PMMIC : 0x00, R_PM1_PMMIC);
++      ak->regs[R_PM1] = WRITE_MASK(ak->regs[R_PM1], on ? REG_PWR1_PMMO : 0x00, REG_PWR1_PMMO);
++      snd_ak4641_reg_changed(ak, R_PM1);
++
++      snd_ak4641_hwsync_write(ak, R_PGA);     /* mic PGA gain is reset when PMMIC = 0 */
++
++      /* internal mic */
++        ak->regs[R_MIC]       = WRITE_MASK(ak->regs[R_MIC], on ? R_MIC_MPWRI : 0x0, R_MIC_MPWRI);
++        ak->regs[R_MIC]       = WRITE_MASK(ak->regs[R_MIC],                    0x0, R_MIC_MSEL);
++        snd_ak4641_hwsync_write(ak, R_MIC);
++
++//        ak->regs[REG_BTIF]  = WRITE_MASK(ak->regs[REG_BTIF], 0x0, REG_BTIF_DAC2);
++//        snd_ak4641_hwsync_write(ak, REG_BTIF);
++      /* */
++//    ak->regs[REG_VOL] = WRITE_MASK(ak->regs[REG_VOL], on ? REG_VOL_ATTM : 0x00, REG_VOL_ATTM);
++//    ak->regs[R_SEL1] = WRITE_MASK(ak->regs[R_SEL1], on ? REG_SEL1_MOGN : 0x00, REG_SEL1_MOGN);
++      ak->regs[R_SEL1] = WRITE_MASK(ak->regs[R_SEL1], on ? REG_SEL1_MICM : 0x00, REG_SEL1_MICM);
++      ak->regs[R_SEL1] = WRITE_MASK(ak->regs[R_SEL1], on ? REG_SEL1_PSMO : 0x00, REG_SEL1_PSMO);
++      snd_ak4641_reg_changed(ak, R_SEL1);
++      snd_ak4641_unlock(ak);
++      return 0;
++}
++/*-end------------------------------------------------------------*/
++
++#define ACTL_BOOL(ctl_name, _name) \
++static struct snd_ak4641_uctl_bool snd_ak4641_actl_ ## ctl_name ## _pvalue = \
++{ .get = snd_ak4641_uctl_ ## ctl_name ## _get, \
++  .set = snd_ak4641_uctl_ ## ctl_name ## _set }; \
++static struct snd_kcontrol_new snd_ak4641_actl_ ## ctl_name = \
++{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = _name, .info = snd_ak4641_actl_bool_info, \
++  .get = snd_ak4641_actl_bool_get, .put = snd_ak4641_actl_bool_put, \
++  .private_value = (unsigned long) &snd_ak4641_actl_ ## ctl_name ## _pvalue };
++
++ACTL_BOOL(playback_switch, "Master Playback Switch")
++ACTL_BOOL(mic_boost, "Mic Boost (+20dB)")
++ACTL_BOOL(mono_out, "Phone mic enable")
++
++static void snd_ak4641_headphone_on(struct snd_ak4641 *ak, int on);
++static void snd_ak4641_speaker_on(struct snd_ak4641 *ak, int on);
++static void snd_ak4641_select_mic(struct snd_ak4641 *ak);
++
++void snd_ak4641_hp_connected(struct snd_ak4641 *ak, int connected)
++{
++      snd_ak4641_lock(ak);
++      if (connected != ak->hp_connected) {
++              ak->hp_connected = connected;
++
++              /* headphone or speaker, on playback */
++              if (ak->playback_on) {
++                      if (connected) {
++                              snd_ak4641_headphone_on(ak, 1);
++                              snd_ak4641_speaker_on(ak, 0);
++                      } else {
++                              snd_ak4641_speaker_on(ak, 1);
++                              snd_ak4641_headphone_on(ak, 0);
++                      }
++              }
++
++              /* headset or internal mic, on capture */
++              if (ak->capture_on)
++                      snd_ak4641_select_mic(ak);
++      }
++      snd_ak4641_unlock(ak);
++}
++
++/* end {{ Controls }} */
++
++
++/* begin {{ Headphone Detected Notification }} */
++
++static void snd_ak4641_hp_detected_w_fn(void *p)
++{
++      struct snd_ak4641 *ak = (struct snd_ak4641 *)p;
++
++      snd_ak4641_hp_connected(ak, ak->hp_detected.detected);
++}
++
++void snd_ak4641_hp_detected(struct snd_ak4641 *ak, int detected)
++{
++      if (detected != ak->hp_detected.detected) {
++              ak->hp_detected.detected = detected;
++              queue_work(ak->hp_detected.wq, &ak->hp_detected.w);
++      }
++}
++
++static int snd_ak4641_hp_detected_init(struct snd_ak4641 *ak)
++{
++      INIT_WORK(&ak->hp_detected.w, snd_ak4641_hp_detected_w_fn);
++      ak->hp_detected.detected = ak->hp_connected;
++      ak->hp_detected.wq = create_singlethread_workqueue("ak4641");
++      if (ak->hp_detected.wq) return 0;
++      else return -1;
++}
++
++static void snd_ak4641_hp_detected_free(struct snd_ak4641 *ak)
++{
++      destroy_workqueue(ak->hp_detected.wq);
++}
++
++/* end {{ Headphone Detected Notification }} */
++
++
++/* begin {{ Codec Control }} */
++
++static void snd_ak4641_headphone_on(struct snd_ak4641 *ak, int on)
++{
++      if (on) {
++              ak->regs[R_PM1] = WRITE_MASK(ak->regs[R_PM1], R_PM1_PMLO, R_PM1_PMLO);
++              snd_ak4641_hwsync_write(ak, R_PM1);
++              ak->headphone_out_on(1);
++              ak->regs[R_SEL2] = WRITE_MASK(ak->regs[R_SEL2],
++                                            R_SEL2_PSLOL | R_SEL2_PSLOR,
++                                            R_SEL2_PSLOL | R_SEL2_PSLOR);
++              snd_ak4641_hwsync_write(ak, R_SEL2);
++      } else {
++              ak->regs[R_SEL2] = WRITE_MASK(ak->regs[R_SEL2],
++                                            0x00, R_SEL2_PSLOL | R_SEL2_PSLOR);
++              snd_ak4641_hwsync_write(ak, R_SEL2);
++              ak->headphone_out_on(0);
++              ak->regs[R_PM1] = WRITE_MASK(ak->regs[R_PM1], 0x00, R_PM1_PMLO);
++              snd_ak4641_hwsync_write(ak, R_PM1);
++      }
++}
++
++static void snd_ak4641_speaker_on(struct snd_ak4641 *ak, int on)
++{
++      if (on) {
++              ak->regs[R_PM1] = WRITE_MASK(ak->regs[R_PM1], R_PM1_PMLO, R_PM1_PMLO);
++              snd_ak4641_hwsync_write(ak, R_PM1);
++              ak->speaker_out_on(1);
++              ak->regs[R_SEL2] = WRITE_MASK(ak->regs[R_SEL2],
++                                            R_SEL2_PSLOL | R_SEL2_PSLOR,
++                                            R_SEL2_PSLOL | R_SEL2_PSLOR);
++              snd_ak4641_hwsync_write(ak, R_SEL2);
++      } else {
++              ak->regs[R_SEL2] = WRITE_MASK(ak->regs[R_SEL2],
++                                            0x00, R_SEL2_PSLOL | R_SEL2_PSLOR);
++              snd_ak4641_hwsync_write(ak, R_SEL2);
++              ak->speaker_out_on(0);
++              ak->regs[R_PM1] = WRITE_MASK(ak->regs[R_PM1], 0x00, R_PM1_PMLO);
++              snd_ak4641_hwsync_write(ak, R_PM1);
++      }
++}
++
++static inline int snd_ak4641_power_on(struct snd_ak4641 *ak)
++{
++      ak->reset_pin(1);
++      ak->power_on_chip(1);
++      msleep(1);
++      ak->reset_pin(0);
++      ak->powered_on = 1;
++      return 0;
++}
++
++static inline int snd_ak4641_power_off(struct snd_ak4641 *ak)
++{
++      ak->powered_on = 0;
++      ak->power_on_chip(0);
++      return 0;
++}
++
++static inline void snd_ak4641_headphone_out_on(struct snd_ak4641 *ak, int on)
++{
++      if (ak->headphone_out_on) ak->headphone_out_on(on);
++}
++
++static inline void snd_ak4641_speaker_out_on(struct snd_ak4641 *ak, int on)
++{
++      if (ak->speaker_out_on) ak->speaker_out_on(on);
++}
++
++static int snd_ak4641_playback_on(struct snd_ak4641 *ak)
++{
++      if (ak->playback_on) return 0;
++
++      ak->regs[R_PM2] = WRITE_MASK(ak->regs[R_PM2],
++                                   R_PM2_PMDAC, R_PM2_MCKPD | R_PM2_PMDAC);
++      ak->regs[R_PM1] = WRITE_MASK(ak->regs[R_PM1], R_PM1_PMLO, R_PM1_PMLO);
++      snd_ak4641_hwsync_write(ak, R_PM2);
++      snd_ak4641_hwsync_write(ak, R_PM1);
++      if (ak->hp_connected) snd_ak4641_headphone_on(ak, 1);
++      else snd_ak4641_speaker_on(ak, 1);
++
++      ak->playback_on = 1;
++
++      return 0;
++}
++
++static int snd_ak4641_playback_off(struct snd_ak4641 *ak)
++{
++      if (!ak->playback_on) return 0;
++
++      ak->playback_on = 0;
++
++      if (ak->hp_connected) snd_ak4641_headphone_on(ak, 0);
++      else snd_ak4641_speaker_on(ak, 0);
++      ak->regs[R_PM1] = WRITE_MASK(ak->regs[R_PM1], 0x00, R_PM1_PMLO);
++      ak->regs[R_PM2] = WRITE_MASK(ak->regs[R_PM2],
++                                  (!ak->capture_on ? R_PM2_MCKPD : 0x00) | R_PM2_PMDAC,
++                                  R_PM2_MCKPD | R_PM2_PMDAC);
++      snd_ak4641_hwsync_write(ak, R_PM1);
++      snd_ak4641_hwsync_write(ak, R_PM2);
++
++      return 0;
++}
++
++static void snd_ak4641_select_mic(struct snd_ak4641 *ak)
++{
++      int mic = 0;
++      u8 r_mic;
++
++      if (ak->hp_connected) {
++              /* check headset mic */
++              ak->regs[R_MIC] = WRITE_MASK(ak->regs[R_MIC], R_MIC_MPWRE, R_MIC_MPWRE);
++              snd_ak4641_hwsync_write(ak, R_MIC);
++              snd_ak4641_hwsync_read(ak, R_STATUS);
++              mic = (ak->regs[R_STATUS] & R_STATUS_DTMIC) == R_STATUS_DTMIC;
++
++              printk("htcuniversal_ak4641_select_mic: mic=%d\n",mic);
++
++       r_mic = WRITE_MASK(ak->regs[R_MIC],
++                         R_MIC_MSEL | (ak->capture_on ? R_MIC_MPWRE : 0x00),
++                         R_MIC_MSEL | R_MIC_MPWRI | R_MIC_MPWRE);
++      }
++      else
++       r_mic = WRITE_MASK(ak->regs[R_MIC],
++                               0x00 | (ak->capture_on ? R_MIC_MPWRI : 0x00),
++                         R_MIC_MSEL | R_MIC_MPWRI | R_MIC_MPWRE);
++
++      if (r_mic != ak->regs[R_MIC]) {
++              ak->regs[R_MIC] = r_mic;
++              snd_ak4641_hwsync_write(ak, R_MIC);
++      }
++}
++
++static int snd_ak4641_capture_on(struct snd_ak4641 *ak)
++{
++      if (ak->capture_on) return 0;
++
++      if (!ak->playback_on) {
++              ak->regs[R_PM2] = WRITE_MASK(ak->regs[R_PM2], 0x00, R_PM2_MCKPD);
++              snd_ak4641_hwsync_write(ak, R_PM2);
++      }
++      ak->regs[R_PM1] = WRITE_MASK(ak->regs[R_PM1], R_PM1_PMMIC | R_PM1_PMADC,
++                                                    R_PM1_PMMIC | R_PM1_PMADC);
++      snd_ak4641_hwsync_write(ak, R_PM1);
++      snd_ak4641_hwsync_write(ak, R_PGA);     /* mic PGA gain is reset when PMMIC = 0 */
++
++      ak->capture_on = 1;
++
++      snd_ak4641_select_mic(ak);
++
++      msleep(47);     /* accounts for ADC init cycle, time enough for fs >= 44.1 kHz */
++
++      return 0;
++}
++
++static int snd_ak4641_capture_off(struct snd_ak4641 *ak)
++{
++      if (!ak->capture_on) return 0;
++
++      ak->regs[R_MIC] = WRITE_MASK(ak->regs[R_MIC],
++                                   0x00, R_MIC_MPWRI | R_MIC_MPWRE | R_MIC_MSEL);
++      ak->regs[R_PM1] = WRITE_MASK(ak->regs[R_PM1], 0x00, R_PM1_PMMIC | R_PM1_PMADC);
++      snd_ak4641_hwsync_write(ak, R_MIC);
++      snd_ak4641_hwsync_write(ak, R_PM1);
++      if (!ak->playback_on) {
++              ak->regs[R_PM2] = WRITE_MASK(ak->regs[R_PM2], R_PM2_MCKPD, R_PM2_MCKPD);
++              snd_ak4641_hwsync_write(ak, R_PM2);
++      }
++
++      ak->capture_on = 0;
++
++      return 0;
++}
++
++int snd_ak4641_open_stream(struct snd_ak4641 *ak, int stream)
++{
++      snd_ak4641_lock(ak);
++      if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
++              ak->playback_stream_opened = 1;
++              snd_ak4641_playback_on(ak);
++      } else {
++              ak->capture_stream_opened = 1;
++              snd_ak4641_capture_on(ak);
++      }
++      snd_ak4641_unlock(ak);
++      return 0;
++}
++
++int snd_ak4641_close_stream(struct snd_ak4641 *ak, int stream)
++{
++      snd_ak4641_lock(ak);
++      if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
++              ak->playback_stream_opened = 0;
++              snd_ak4641_playback_off(ak);
++      } else {
++              ak->capture_stream_opened = 0;
++              snd_ak4641_capture_off(ak);
++      }
++      snd_ak4641_unlock(ak);
++      return 0;
++}
++
++static int snd_ak4641_init_regs(struct snd_ak4641 *ak)
++{
++      snd_ak4641_hwsync_read_all(ak);
++
++      //@@ MEMO: add some configs
++
++      ak->regs[R_PM1] = WRITE_MASK(ak->regs[R_PM1], R_PM1_PMVCM, R_PM1_PMVCM);
++      ak->regs[R_DAC] = WRITE_MASK(ak->regs[R_DAC], 0x00, R_DAC_DATTC);
++      snd_ak4641_hwsync_write(ak, R_PM1);
++      snd_ak4641_hwsync_write(ak, R_DAC);
++
++      return 0;
++}
++
++int snd_ak4641_suspend(struct snd_ak4641 *ak, pm_message_t state)
++{
++      snd_ak4641_lock(ak);
++      if (ak->playback_on) snd_ak4641_playback_off(ak);
++      if (ak->capture_on) snd_ak4641_capture_off(ak);
++      snd_ak4641_power_off(ak);
++      snd_ak4641_unlock(ak);
++      return 0;
++}
++
++int snd_ak4641_resume(struct snd_ak4641 *ak)
++{
++      snd_ak4641_lock(ak);
++      snd_ak4641_power_on(ak);
++      snd_ak4641_hwsync_write_all(ak);
++      if (ak->playback_stream_opened) snd_ak4641_playback_on(ak);
++      if (ak->capture_stream_opened) snd_ak4641_capture_on(ak);
++      snd_ak4641_unlock(ak);
++      return 0;
++}
++
++static void snd_ak4641_init_ak(struct snd_ak4641 *ak)
++{
++      init_MUTEX(&ak->sem);
++      ak->i2c_client.driver = &snd_ak4641_i2c_driver;
++}
++
++int snd_ak4641_activate(struct snd_ak4641 *ak)
++{
++      int ret = 0;
++
++      snd_ak4641_init_ak(ak);
++      snd_ak4641_lock(ak);
++      snd_ak4641_power_on(ak);
++      if ((ret = snd_ak4641_i2c_attach(ak)) < 0)
++              goto failed_i2c_attach;
++      snd_ak4641_init_regs(ak);
++      if ((ret = snd_ak4641_hp_detected_init(ak)) < 0)
++              goto failed_hp_detected_init;
++      snd_ak4641_unlock(ak);
++      return 0;
++
++ failed_hp_detected_init:
++      snd_ak4641_i2c_detach(ak);
++ failed_i2c_attach:
++      snd_ak4641_power_off(ak);
++      snd_ak4641_unlock(ak);
++      return ret;
++}
++
++void snd_ak4641_deactivate(struct snd_ak4641 *ak)
++{
++      snd_ak4641_lock(ak);
++      snd_ak4641_hp_detected_free(ak);
++      snd_ak4641_i2c_detach(ak);
++      snd_ak4641_power_off(ak);
++      snd_ak4641_unlock(ak);
++}
++
++int snd_ak4641_add_mixer_controls(struct snd_ak4641 *ak, struct snd_card *card)
++{
++      snd_ak4641_lock(ak);
++      snd_ctl_add(card, snd_ctl_new1(&snd_ak4641_actl_playback_volume, ak));
++      snd_ctl_add(card, snd_ctl_new1(&snd_ak4641_actl_playback_switch, ak));
++      snd_ctl_add(card, snd_ctl_new1(&snd_ak4641_actl_mic_gain, ak));
++      snd_ctl_add(card, snd_ctl_new1(&snd_ak4641_actl_mic_boost, ak));
++      snd_ctl_add(card, snd_ctl_new1(&snd_ak4641_actl_mono_out, ak));
++      snd_ak4641_unlock(ak);
++      return 0;
++}
++
++/* end {{ Codec Control }} */
++
++
++/* begin {{ Module }} */
++
++static int __init snd_ak4641_module_on_load(void)
++{
++      snd_ak4641_i2c_init();
++      return 0;
++}
++
++static void __exit snd_ak4641_module_on_unload(void)
++{
++      snd_ak4641_i2c_free();
++}
++
++module_init(snd_ak4641_module_on_load);
++module_exit(snd_ak4641_module_on_unload);
++
++EXPORT_SYMBOL(snd_ak4641_activate);
++EXPORT_SYMBOL(snd_ak4641_deactivate);
++EXPORT_SYMBOL(snd_ak4641_add_mixer_controls);
++EXPORT_SYMBOL(snd_ak4641_open_stream);
++EXPORT_SYMBOL(snd_ak4641_close_stream);
++EXPORT_SYMBOL(snd_ak4641_suspend);
++EXPORT_SYMBOL(snd_ak4641_resume);
++EXPORT_SYMBOL(snd_ak4641_hp_connected);
++EXPORT_SYMBOL(snd_ak4641_hp_detected);
++
++MODULE_AUTHOR("Giorgio Padrin");
++MODULE_DESCRIPTION("Audio support for codec Asahi Kasei AK4641");
++MODULE_LICENSE("GPL");
++
++/* end {{ Module }} */
+Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_ak4641.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_ak4641.h  2007-09-11 12:53:37.000000000 +0200
+@@ -0,0 +1,65 @@
++/*
++ * Audio support for codec Asahi Kasei AK4641
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * Copyright (c) 2006 Giorgio Padrin <giorgio@mandarinlogiq.org>
++ */
++
++#ifndef __SOUND_AK4641_H
++#define __SOUND_AK4641_H
++
++#include <linux/i2c.h>
++
++struct snd_ak4641 {
++      struct semaphore sem;
++
++      u8 regs[0x14];  /* registers cache */
++
++      unsigned int
++              powered_on:1,
++              playback_on:1,
++              playback_stream_opened:1,
++              capture_on:1,
++              capture_stream_opened:1;
++
++      unsigned int
++              hp_connected:1;
++
++      /* -- configuration (to fill before activation) -- */
++      void (*power_on_chip)(int on);
++      void (*reset_pin)(int on);
++      void (*headphone_out_on)(int on);
++      void (*speaker_out_on)(int on);
++
++      struct i2c_client i2c_client; /* to fill .adapter */
++      /* ----------------------------------------------- */
++
++      struct {
++              int detected;
++              struct workqueue_struct *wq;
++              struct work_struct w;
++      } hp_detected;
++};
++
++
++/* Note: opening, closing, suspending and resuming a stream
++ * require the clocks (MCLK and I2S ones) running
++ */
++
++/* don't forget to specify I2C adapter in i2c_client field */
++int snd_ak4641_activate(struct snd_ak4641 *ak);
++
++void snd_ak4641_deactivate(struct snd_ak4641 *ak);
++int snd_ak4641_add_mixer_controls(struct snd_ak4641 *ak, struct snd_card *card);
++int snd_ak4641_open_stream(struct snd_ak4641 *ak, int stream);
++int snd_ak4641_close_stream(struct snd_ak4641 *ak, int stream);
++int snd_ak4641_suspend(struct snd_ak4641 *ak, pm_message_t state);
++int snd_ak4641_resume(struct snd_ak4641 *ak);
++
++void snd_ak4641_hp_connected(struct snd_ak4641 *ak, int connected); /* non atomic context */
++void snd_ak4641_hp_detected(struct snd_ak4641 *ak, int detected); /* atomic context */
++
++#endif /* __SOUND_AK4641_H */
+Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_asic3_leds.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_asic3_leds.c      2007-09-11 12:53:37.000000000 +0200
+@@ -0,0 +1,143 @@
++/*
++ * LEDs support for the HP iPaq hx4700
++ *
++ * Copyright (c) 2006  Anton Vorontsov <cbou@mail.ru>
++ *
++ * 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/init.h>
++#include <linux/platform_device.h>
++#include <linux/leds.h>
++#include <linux/soc/asic3_base.h>
++
++#include <asm/hardware/ipaq-asic3.h>
++#include <asm/mach-types.h>
++#include <asm/hardware/asic3_leds.h>
++#include <asm/arch/htcuniversal-asic.h>
++
++//FIXME
++//DEFINE_LED_TRIGGER_SHARED_GLOBAL(htcuniversal_radio_trig);
++//EXPORT_LED_TRIGGER_SHARED(htcuniversal_radio_trig);
++
++static struct asic3_led htcuniversal_leds[] = {
++      {
++              .led_cdev  = {
++                      .name           = "htcuniversal:red",
++                      .default_trigger = "htcuniversal-charging",
++              },
++              .hw_num = 2,
++
++      },
++      {
++              .led_cdev  = {
++                      .name            = "htcuniversal:green",
++                      .default_trigger = "htcuniversal-chargefull",
++              },
++              .hw_num = 1,
++      },
++      {
++              .led_cdev  = {
++                      .name            = "htcuniversal:wifi-bt",
++                      .default_trigger = "htcuniversal-radio",
++              },
++              .hw_num = 0,
++      },
++      {
++              .led_cdev  = {
++                      .name            = "htcuniversal:phonebuttons",
++                      .default_trigger = "htcuniversal-phonebuttons",
++              },
++              .hw_num = -1,
++              .gpio_num = ('D'-'A')*16+GPIOD_BL_KEYP_PWR_ON,
++      },
++      {
++              .led_cdev  = {
++                      .name            = "htcuniversal:vibra",
++                      .default_trigger = "htcuniversal-vibra",
++              },
++              .hw_num = -1,
++              .gpio_num = ('D'-'A')*16+GPIOD_VIBRA_PWR_ON,
++      },
++      {
++              .led_cdev  = {
++                      .name            = "htcuniversal:flashlight1",
++                      .default_trigger = "htcuniversal-flashlight1",
++              },
++              .hw_num = -1,
++              .gpio_num = ('A'-'A')*16+GPIOA_FLASHLIGHT,
++      },
++      {
++              .led_cdev  = {
++                      .name            = "htcuniversal:kbdbacklight",
++                      .default_trigger = "htcuniversal-kbdbacklight",
++              },
++              .hw_num = -1,
++              .gpio_num = ('D'-'A')*16+GPIOD_BL_KEYB_PWR_ON,
++      },
++};
++
++void htcuniversal_leds_release(struct device *dev)
++{
++      return;
++}
++
++static
++struct asic3_leds_machinfo htcuniversal_leds_machinfo = {
++      .num_leds = ARRAY_SIZE(htcuniversal_leds),
++      .leds = htcuniversal_leds,
++      .asic3_pdev = &htcuniversal_asic3,
++};
++
++static
++struct platform_device htcuniversal_leds_pdev = {
++      .name = "asic3-leds",
++      .dev = {
++              .platform_data = &htcuniversal_leds_machinfo,
++              .release = htcuniversal_leds_release,
++      },
++};
++
++static
++int __init htcuniversal_leds_init(void)
++{
++      int ret;
++      printk("htcuniversal LEDs Driver\n");
++//    led_trigger_register_shared("htcuniversal-radio", &htcuniversal_radio_trig);
++
++      ret = asic3_leds_register();
++      if (ret) goto asic3_leds_failed;
++
++      ret = platform_device_register(&htcuniversal_leds_pdev);
++      if (ret) goto platform_device_failed;
++
++      goto success;
++
++platform_device_failed:
++      asic3_leds_unregister();
++asic3_leds_failed:
++//    led_trigger_unregister_shared(htcuniversal_radio_trig);
++      printk("htcuniversal LEDs Driver failed to init");
++success:
++      return ret;
++}
++
++static
++void __exit htcuniversal_leds_exit(void)
++{
++//    led_trigger_unregister_shared(htcuniversal_radio_trig);
++      platform_device_unregister(&htcuniversal_leds_pdev);
++      asic3_leds_unregister();
++      return;
++}
++
++module_init(htcuniversal_leds_init);
++module_exit(htcuniversal_leds_exit);
++
++MODULE_AUTHOR("Anton Vorontsov <cbou@mail.ru>");
++MODULE_DESCRIPTION("htcuniversal LEDs driver");
++MODULE_LICENSE("GPL");
+Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_bl.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_bl.c      2007-09-11 12:53:37.000000000 +0200
+@@ -0,0 +1,61 @@
++/*
++ * Use consistent with the GNU GPL is permitted,
++ * provided that this copyright notice is
++ * preserved in its entirety in all copies and derived works.
++ *
++ * Copyright (C) 2006 Paul Sokolosvky
++ * Based on code from older versions of htcuniversal_lcd.c
++ *
++ */
++
++#include <linux/types.h>
++#include <linux/platform_device.h>
++#include <asm/arch/hardware.h>  /* for pxa-regs.h (__REG) */
++#include <asm/arch/pxa-regs.h>
++#include <asm/mach-types.h>     /* machine_is_htcuniversal */
++//#include <linux/corgi_bl.h>
++#include <linux/backlight.h>
++#include <linux/err.h>
++
++#include <asm/arch/htcuniversal-gpio.h>
++#include <asm/arch/htcuniversal-asic.h>
++#include <asm/hardware/ipaq-asic3.h>
++#include <linux/soc/asic3_base.h>
++
++#define HTCUNIVERSAL_MAX_INTENSITY 0xc7
++
++static void htcuniversal_set_bl_intensity(int intensity)
++{
++      PWM_CTRL1 = 1;            /* pre-scaler */
++      PWM_PWDUTY1 = intensity; /* duty cycle */
++      PWM_PERVAL1 = HTCUNIVERSAL_MAX_INTENSITY+1;      /* period */
++
++      if (intensity > 0) {
++              pxa_set_cken(CKEN_PWM1, 1);
++                asic3_set_gpio_out_d(&htcuniversal_asic3.dev,
++                        (1<<GPIOD_FL_PWR_ON), (1<<GPIOD_FL_PWR_ON));
++      } else {
++              pxa_set_cken(CKEN_PWM1, 0);
++                asic3_set_gpio_out_d(&htcuniversal_asic3.dev,
++                        (1<<GPIOD_FL_PWR_ON), 0);
++      }
++}
++
++
++static struct generic_bl_info htcuniversal_bl_machinfo = {
++        .default_intensity = HTCUNIVERSAL_MAX_INTENSITY / 4,
++        .limit_mask = 0xff,
++        .max_intensity = HTCUNIVERSAL_MAX_INTENSITY,
++        .set_bl_intensity = htcuniversal_set_bl_intensity,
++};
++
++struct platform_device htcuniversal_bl = {
++        .name = "corgi-bl",
++        .dev = {
++              .platform_data = &htcuniversal_bl_machinfo,
++      },
++};
++
++MODULE_AUTHOR("Paul Sokolovsky <pmiscml@gmail.com>");
++MODULE_DESCRIPTION("Backlight driver for HTC Universal");
++MODULE_LICENSE("GPL");
+Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_bt.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_bt.c      2007-09-11 12:53:37.000000000 +0200
+@@ -0,0 +1,135 @@
++/* Bluetooth interface driver for TI BRF6150 on HX4700
++ *
++ * Copyright (c) 2005 SDG Systems, LLC
++ *
++ * 2005-04-21   Todd Blumer             Created.
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/delay.h>
++#include <linux/platform_device.h>
++#include <linux/soc/asic3_base.h>
++
++#include <asm/hardware.h>
++#include <asm/arch/serial.h>
++#include <asm/hardware/ipaq-asic3.h>
++#include <asm/arch/htcuniversal-gpio.h>
++#include <asm/arch/htcuniversal-asic.h>
++
++#include "htcuniversal_bt.h"
++
++static uint use_led=1;
++
++static void
++htcuniversal_bt_configure( int state )
++{
++      int tries;
++
++      printk( KERN_NOTICE "htcuniversal configure bluetooth: %d\n", state );
++      switch (state) {
++
++      case PXA_UART_CFG_PRE_STARTUP:
++              break;
++
++      case PXA_UART_CFG_POST_STARTUP:
++              /* pre-serial-up hardware configuration */
++              htcuniversal_egpio_enable(1<<EGPIO5_BT_3V3_ON);
++              mdelay(50);
++              asic3_set_gpio_out_c(&htcuniversal_asic3.dev, 1<<GPIOC_BT_PWR_ON, 1<<GPIOC_BT_PWR_ON);
++              mdelay(10);
++              asic3_set_gpio_out_c(&htcuniversal_asic3.dev, 1<<GPIOC_BT_RESET, 0);
++              mdelay(10);
++              asic3_set_gpio_out_c(&htcuniversal_asic3.dev, 1<<GPIOC_BT_RESET, 1<<GPIOC_BT_RESET);
++              mdelay(10);
++
++              /*
++               * BRF6150's RTS goes low when firmware is ready
++               * so check for CTS=1 (nCTS=0 -> CTS=1). Typical 150ms
++               */
++              tries = 0;
++              do {
++                      mdelay(10);
++              } while ((BTMSR & MSR_CTS) == 0 && tries++ < 50);
++              if (use_led) {
++//                    htcuniversal_set_led(2, 16, 16);
++              }
++              break;
++
++      case PXA_UART_CFG_PRE_SHUTDOWN:
++              htcuniversal_egpio_disable(1<<EGPIO5_BT_3V3_ON );
++              mdelay(50);
++//            htcuniversal_clear_led(2);
++              asic3_set_gpio_out_c(&htcuniversal_asic3.dev, 1<<GPIOC_BT_PWR_ON, 0);
++              break;
++
++      default:
++              break;
++      }
++}
++
++
++static int
++htcuniversal_bt_probe( struct platform_device *dev )
++{
++      struct htcuniversal_bt_funcs *funcs = dev->dev.platform_data;
++
++      /* configure bluetooth UART */
++      pxa_gpio_mode( GPIO_NR_HTCUNIVERSAL_BT_RXD_MD );
++      pxa_gpio_mode( GPIO_NR_HTCUNIVERSAL_BT_TXD_MD );
++      pxa_gpio_mode( GPIO_NR_HTCUNIVERSAL_BT_UART_CTS_MD );
++      pxa_gpio_mode( GPIO_NR_HTCUNIVERSAL_BT_UART_RTS_MD );
++
++      funcs->configure = htcuniversal_bt_configure;
++
++      /* Make sure the LED is off */
++//    htcuniversal_clear_led(2);
++
++      return 0;
++}
++
++static int
++htcuniversal_bt_remove( struct platform_device *dev )
++{
++      struct htcuniversal_bt_funcs *funcs = dev->dev.platform_data;
++
++      funcs->configure = NULL;
++
++      /* Make sure the LED is off */
++//    htcuniversal_clear_led(2);
++
++      return 0;
++}
++
++static struct platform_driver bt_driver = {
++      .driver = {
++              .name     = "htcuniversal_bt",
++      },
++      .probe    = htcuniversal_bt_probe,
++      .remove   = htcuniversal_bt_remove,
++};
++
++module_param(use_led, uint, 0);
++
++static int __init
++htcuniversal_bt_init( void )
++{
++      printk(KERN_NOTICE "htcuniversal Bluetooth Driver\n");
++      return platform_driver_register( &bt_driver );
++}
++
++static void __exit
++htcuniversal_bt_exit( void )
++{
++      platform_driver_unregister( &bt_driver );
++}
++
++module_init( htcuniversal_bt_init );
++module_exit( htcuniversal_bt_exit );
++
++MODULE_AUTHOR("Todd Blumer, SDG Systems, LLC");
++MODULE_DESCRIPTION("HTC Universal Bluetooth Support Driver");
++MODULE_LICENSE("GPL");
++
++/* vim600: set noexpandtab sw=8 ts=8 :*/
++
+Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_bt.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_bt.h      2007-09-11 12:53:37.000000000 +0200
+@@ -0,0 +1,17 @@
++/*
++ * Bluetooth support file for calling bluetooth configuration functions
++ *
++ * Copyright (c) 2005 SDG Systems, LLC
++ *
++ * 2005-06    Todd Blumer             Initial Revision
++ */
++
++#ifndef _HTCUNIVERSAL_BT_H
++#define _HTCUNIVERSAL_BT_H
++
++struct htcuniversal_bt_funcs {
++      void (*configure) ( int state );
++};
++
++
++#endif
+Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_buttons.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_buttons.c 2007-09-11 12:53:37.000000000 +0200
+@@ -0,0 +1,87 @@
++/*
++ * Buttons driver for HTC Universal
++ *
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License.
++ *
++ * Copyright (C) 2005 Pawel Kolodziejski
++ * Copyright (C) 2003 Joshua Wise
++ *
++ */
++
++#include <linux/input.h>
++#include <linux/input_pda.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <linux/irq.h>
++#include <linux/platform_device.h>
++#include <linux/gpio_keys.h>
++#include <linux/soc/asic3_base.h>
++#include <asm/mach-types.h>
++#include <asm/hardware/asic3_keys.h>
++#include <asm/arch/htcuniversal-gpio.h>
++#include <asm/arch/htcuniversal-asic.h>
++
++static struct asic3_keys_button asic3_buttons[] = {
++//{KEY_SCREEN,                ASIC3_GPIOA_IRQ_BASE+GPIOA_COVER_ROTATE_N,      1,      "screen_cover", EV_SW},
++//{KEY_SWITCHVIDEOMODE,       ASIC3_GPIOB_IRQ_BASE+GPIOB_CLAMSHELL_N,         1,      "clamshell_rotate", EV_SW},
++//{KEY_KBDILLUMTOGGLE,        ASIC3_GPIOB_IRQ_BASE+GPIOB_NIGHT_SENSOR,        1,      "night_sensor", EV_SW},
++{SW_LID,              ASIC3_GPIOA_IRQ_BASE+GPIOA_COVER_ROTATE_N,      1,      "screen_cover", EV_SW},
++{SW_TABLET_MODE,      ASIC3_GPIOB_IRQ_BASE+GPIOB_CLAMSHELL_N,         1,      "clamshell_rotate", EV_SW},
++//{SW_NIGHT_SENSOR,   ASIC3_GPIOB_IRQ_BASE+GPIOB_NIGHT_SENSOR,        1,      "night_sensor", EV_SW},
++{KEY_F10,             ASIC3_GPIOA_IRQ_BASE+GPIOA_BUTTON_BACKLIGHT_N,  1,      "backlight_button"},
++{KEY_RECORD,          ASIC3_GPIOA_IRQ_BASE+GPIOA_BUTTON_RECORD_N,     1,      "record_button"},
++{KEY_CAMERA,          ASIC3_GPIOA_IRQ_BASE+GPIOA_BUTTON_CAMERA_N,     1,      "camera_button"},
++{KEY_VOLUMEDOWN,      ASIC3_GPIOA_IRQ_BASE+GPIOA_VOL_UP_N,            1,      "volume_slider_down"},
++{KEY_VOLUMEUP,                ASIC3_GPIOA_IRQ_BASE+GPIOA_VOL_DOWN_N,          1,      "volume_slider_up"},
++{KEY_KPENTER,         ASIC3_GPIOD_IRQ_BASE+GPIOD_KEY_OK_N,            1,      "select"},
++{KEY_RIGHT,           ASIC3_GPIOD_IRQ_BASE+GPIOD_KEY_RIGHT_N,         1,      "right"},
++{KEY_LEFT,            ASIC3_GPIOD_IRQ_BASE+GPIOD_KEY_LEFT_N,          1,      "left"},
++{KEY_DOWN,            ASIC3_GPIOD_IRQ_BASE+GPIOD_KEY_DOWN_N,          1,      "down"},
++{KEY_UP,              ASIC3_GPIOD_IRQ_BASE+GPIOD_KEY_UP_N,            1,      "up"},
++};
++
++static struct asic3_keys_platform_data asic3_keys_data = {
++        .buttons = asic3_buttons,
++        .nbuttons = ARRAY_SIZE(asic3_buttons),
++        .asic3_dev = &htcuniversal_asic3.dev,
++};
++
++static struct platform_device htcuniversal_keys_asic3 = {
++        .name = "asic3-keys",
++        .dev = { .platform_data = &asic3_keys_data, }
++};
++
++static int __init htcuniversal_buttons_probe(struct platform_device *dev)
++{
++      platform_device_register(&htcuniversal_keys_asic3);
++      return 0;
++}
++
++static struct platform_driver htcuniversal_buttons_driver = {
++      .driver         = {
++          .name       = "htcuniversal_buttons",
++      },
++      .probe          = htcuniversal_buttons_probe,
++};
++
++static int __init htcuniversal_buttons_init(void)
++{
++      if (!machine_is_htcuniversal())
++              return -ENODEV;
++
++      return platform_driver_register(&htcuniversal_buttons_driver);
++}
++
++static void __exit htcuniversal_buttons_exit(void)
++{
++      platform_driver_unregister(&htcuniversal_buttons_driver);
++}
++
++module_init(htcuniversal_buttons_init);
++module_exit(htcuniversal_buttons_exit);
++
++MODULE_AUTHOR ("Joshua Wise, Pawel Kolodziejski, Paul Sokolosvky");
++MODULE_DESCRIPTION ("Buttons support for HTC Universal");
++MODULE_LICENSE ("GPL");
+Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_core.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_core.c    2007-09-11 12:53:37.000000000 +0200
+@@ -0,0 +1,226 @@
++/* Core Hardware driver for Hx4700 (Serial, ASIC3, EGPIOs)
++ *
++ * Copyright (c) 2005 SDG Systems, LLC
++ *
++ * 2005-03-29   Todd Blumer             Converted  basic structure to support hx4700
++ * 2005-04-30 Todd Blumer             Add IRDA code from H2200
++ */
++
++#include <linux/module.h>
++#include <linux/version.h>
++#include <linux/interrupt.h>
++#include <linux/platform_device.h>
++#include <linux/delay.h>
++#include <linux/pm.h>
++#include <linux/irq.h>
++
++#include <asm/io.h>
++#include <asm/mach/irq.h>
++#include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa-pm_ll.h>
++#include <asm/arch/htcuniversal-gpio.h>
++#include <asm/arch/htcuniversal-asic.h>
++
++#include <linux/soc/asic3_base.h>
++#include <asm/hardware/ipaq-asic3.h>
++
++volatile u_int16_t *egpios;
++u_int16_t egpio_reg;
++
++static int htc_bootloader = 0;        /* Is the stock HTC bootloader installed? */
++
++/*
++ * may make sense to put egpios elsewhere, but they're here now
++ * since they share some of the same address space with the TI WLAN
++ *
++ * EGPIO register is write-only
++ */
++
++void
++htcuniversal_egpio_enable( u_int16_t bits )
++{
++      unsigned long flags;
++
++      local_irq_save(flags);
++
++      egpio_reg |= bits;
++      *egpios = egpio_reg;
++
++      local_irq_restore(flags);
++}
++EXPORT_SYMBOL_GPL(htcuniversal_egpio_enable);
++
++void
++htcuniversal_egpio_disable( u_int16_t bits )
++{
++      unsigned long flags;
++
++      local_irq_save(flags);
++
++      egpio_reg &= ~bits;
++      *egpios = egpio_reg;
++
++      local_irq_restore(flags);
++}
++EXPORT_SYMBOL_GPL(htcuniversal_egpio_disable);
++
++#ifdef CONFIG_PM
++
++//void htcuniversal_ll_pm_init(void);
++
++static int htcuniversal_suspend(struct platform_device *dev, pm_message_t state)
++{
++      /* Turn off external clocks here, because htcuniversal_power and asic3_mmc
++       * scared to do so to not hurt each other. (-5 mA) */
++
++
++      /* 0x20c2 is HTC clock value
++       * CLOCK_CDEX_SOURCE            2
++       * CLOCK_CDEX_SPI               0
++       * CLOCK_CDEX_OWM               0
++       *
++       * CLOCK_CDEX_PWM0              0
++       * CLOCK_CDEX_PWM1              0
++       * CLOCK_CDEX_LED0              1
++       * CLOCK_CDEX_LED1              1
++       *
++       * CLOCK_CDEX_LED2              0
++       * CLOCK_CDEX_SD_HOST           0
++       * CLOCK_CDEX_SD_BUS            0
++       * CLOCK_CDEX_SMBUS             0
++       *
++       * CLOCK_CDEX_CONTROL_CX        0
++       * CLOCK_CDEX_EX0               1
++       * CLOCK_CDEX_EX1               0
++       * */
++      asic3_set_clock_cdex(&htcuniversal_asic3.dev, 0xffff, CLOCK_CDEX_SOURCE1
++                                                           |CLOCK_CDEX_LED0
++                                                           |CLOCK_CDEX_LED1
++                                                           |CLOCK_CDEX_LED2
++                                                           |CLOCK_CDEX_EX0
++                                                           |CLOCK_CDEX_EX1);
++
++      *egpios = 0;    /* turn off all egpio power */
++
++      /* Wake up enable. */
++      PWER =    PWER_GPIO0
++              | PWER_GPIO1 /* reset */
++              | PWER_GPIO9 /* USB */
++              | PWER_GPIO10 /* AC on USB */
++              | PWER_GPIO14 /* ASIC3 mux */
++              | PWER_RTC;
++      /* Wake up on falling edge. */
++      PFER =    PWER_GPIO0
++              | PWER_GPIO1
++              | PWER_GPIO9
++              | PWER_GPIO10
++              | PWER_GPIO14;
++
++      /* Wake up on rising edge. */
++      PRER =    PWER_GPIO0
++              | PWER_GPIO1
++              | PWER_GPIO9
++              | PWER_GPIO10;
++      /* 3.6864 MHz oscillator power-down enable */
++      PCFR = PCFR_OPDE | PCFR_PI2CEN | PCFR_GPROD | PCFR_GPR_EN;
++
++      PGSR0 = 0x09088004;
++      PGSR1 = 0x00020002;
++      PGSR2 = 0x8001c000;
++      PGSR3 = 0x00106284;
++
++      PSLR  = 0xcc000000;
++
++#if 0
++      /*
++       * If we're using bootldr and not the stock HTC bootloader,
++       * we want to wake up periodically to see if the charge is full while
++       * it is suspended.  We do this with the OS timer 4 in the pxa270.
++       */
++      if (!htc_bootloader) {
++              OMCR4 = 0x4b;   /* Periodic, self-resetting, 1-second timer */
++              OSMR4 = 5;      /* Wake up bootldr after x seconds so it can
++                                 figure out what to do with the LEDs. */
++              OIER |= 0x10;   /* Enable interrupt source for Timer 4 */
++              OSCR4 = 0;      /* This starts the timer */
++      }
++#endif
++
++      asic3_set_extcf_select(&htcuniversal_asic3.dev, ASIC3_EXTCF_OWM_EN, 0);
++
++      return 0;
++}
++
++static int htcuniversal_resume(struct platform_device *dev)
++{
++      htcuniversal_egpio_enable(0);
++
++      return 0;
++}
++#else
++#   define htcuniversal_suspend NULL
++#   define htcuniversal_resume NULL
++#endif
++
++static int
++htcuniversal_core_probe( struct platform_device *dev )
++{
++
++      printk( KERN_NOTICE "HTC Universal Core Hardware Driver\n" );
++
++      egpios = (volatile u_int16_t *)ioremap_nocache(HTCUNIVERSAL_EGPIO_BASE, sizeof *egpios );
++      if (!egpios)
++              return -ENODEV;
++      else
++       printk( KERN_NOTICE "HTC Universal Core: egpio at phy=0x%8.8x is at virt=0x%p\n",
++        HTCUNIVERSAL_EGPIO_BASE, egpios );
++
++      printk("Using stock HTC first stage bootloader\n");
++      htc_bootloader = 1;
++
++//    htcuniversal_ll_pm_init();
++
++      return 0;
++}
++
++static int
++htcuniversal_core_remove( struct platform_device *dev )
++{
++
++      if (egpios != NULL)
++              iounmap( (void *)egpios );
++
++      return 0;
++}
++
++static struct platform_driver htcuniversal_core_driver = {
++      .driver = {
++              .name     = "htcuniversal_core",
++      },
++      .probe    = htcuniversal_core_probe,
++      .remove   = htcuniversal_core_remove,
++      .suspend  = htcuniversal_suspend,
++      .resume   = htcuniversal_resume,
++};
++
++static int __init
++htcuniversal_core_init( void )
++{
++      return platform_driver_register( &htcuniversal_core_driver );
++}
++
++
++static void __exit
++htcuniversal_core_exit( void )
++{
++      platform_driver_unregister( &htcuniversal_core_driver );
++}
++
++module_init( htcuniversal_core_init );
++module_exit( htcuniversal_core_exit );
++
++MODULE_AUTHOR("Todd Blumer, SDG Systems, LLC");
++MODULE_DESCRIPTION("HTC Universal Core Hardware Driver");
++MODULE_LICENSE("GPL");
++
++/* vim600: set noexpandtab sw=8 ts=8 :*/
+Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_lcd.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_lcd.c     2007-09-11 12:53:37.000000000 +0200
+@@ -0,0 +1,212 @@
++/*
++ * Use consistent with the GNU GPL is permitted,
++ * provided that this copyright notice is
++ * preserved in its entirety in all copies and derived works.
++ *
++ * History:
++ *
++ * 2004-03-01   Eddi De Pieri      Adapted for htcuniversal using h3900_lcd.c
++ * 2004         Shawn Anderson     Lcd hacking on htcuniversal
++ * see h3900_lcd.c for more history.
++ *
++ */
++
++#include <linux/types.h>
++#include <asm/arch/hardware.h>  /* for pxa-regs.h (__REG) */
++#include <linux/platform_device.h>
++#include <asm/arch/pxa-regs.h>  /* LCCR[0,1,2,3]* */
++#include <asm/arch/bitfield.h>  /* for pxa-regs.h (Fld, etc) */
++#include <asm/arch/pxafb.h>     /* pxafb_mach_info, set_pxa_fb_info */
++#include <asm/mach-types.h>     /* machine_is_htcuniversal */
++#include <linux/lcd.h>          /* lcd_device */
++#include <linux/err.h>
++#include <linux/delay.h>
++
++#include <asm/arch/htcuniversal-gpio.h>
++#include <asm/arch/htcuniversal-asic.h>
++#include <asm/hardware/ipaq-asic3.h>
++#include <linux/soc/asic3_base.h>
++
++static int saved_lcdpower=-1;
++
++static int powerup_lcd(void)
++{
++      printk( KERN_INFO "htcuniversal powerup_lcd: called\n");
++
++              asic3_set_gpio_out_c(&htcuniversal_asic3.dev, 1<<GPIOC_LCD_PWR1_ON, 0);
++              asic3_set_gpio_out_c(&htcuniversal_asic3.dev, 1<<GPIOC_LCD_PWR2_ON, 0);
++              asic3_set_gpio_out_b(&htcuniversal_asic3.dev, 1<<GPIOB_LCD_PWR3_ON, 0);
++              asic3_set_gpio_out_d(&htcuniversal_asic3.dev, 1<<GPIOD_LCD_PWR4_ON, 0);
++              asic3_set_gpio_out_a(&htcuniversal_asic3.dev, 1<<GPIOA_LCD_PWR5_ON, 0);
++#if 1
++              LCCR4|=LCCR4_PCDDIV;
++#endif
++              pxa_set_cken(CKEN_LCD, 0);
++
++              mdelay(100);
++              asic3_set_gpio_out_a(&htcuniversal_asic3.dev, 1<<GPIOA_LCD_PWR5_ON, 1<<GPIOA_LCD_PWR5_ON);
++              mdelay(5);
++              asic3_set_gpio_out_b(&htcuniversal_asic3.dev, 1<<GPIOB_LCD_PWR3_ON, 1<<GPIOB_LCD_PWR3_ON);
++              mdelay(2);
++              asic3_set_gpio_out_c(&htcuniversal_asic3.dev, 1<<GPIOC_LCD_PWR1_ON, 1<<GPIOC_LCD_PWR1_ON);
++              mdelay(2);
++              asic3_set_gpio_out_c(&htcuniversal_asic3.dev, 1<<GPIOC_LCD_PWR2_ON, 1<<GPIOC_LCD_PWR2_ON);
++              mdelay(20);
++              asic3_set_gpio_out_d(&htcuniversal_asic3.dev, 1<<GPIOD_LCD_PWR4_ON, 1<<GPIOD_LCD_PWR4_ON);
++              mdelay(1);
++              pxa_set_cken(CKEN_LCD, 1);
++
++              SET_HTCUNIVERSAL_GPIO(LCD1,1);
++              SET_HTCUNIVERSAL_GPIO(LCD2,1);
++ return 0;
++}
++
++static int powerdown_lcd(void)
++{
++      printk( KERN_INFO "htcuniversal powerdown_lcd: called\n");
++
++#if 1
++              asic3_set_gpio_out_c(&htcuniversal_asic3.dev, 1<<GPIOC_LCD_PWR2_ON, 0);
++              mdelay(100);
++              asic3_set_gpio_out_d(&htcuniversal_asic3.dev, 1<<GPIOD_LCD_PWR4_ON, 0);
++              mdelay(10);
++              asic3_set_gpio_out_a(&htcuniversal_asic3.dev, 1<<GPIOA_LCD_PWR5_ON, 0);
++              mdelay(1);
++              asic3_set_gpio_out_b(&htcuniversal_asic3.dev, 1<<GPIOB_LCD_PWR3_ON, 0);
++              mdelay(1);
++              asic3_set_gpio_out_c(&htcuniversal_asic3.dev, 1<<GPIOC_LCD_PWR1_ON, 0);
++              pxa_set_cken(CKEN_LCD, 0);
++
++              SET_HTCUNIVERSAL_GPIO(LCD1,0);
++              SET_HTCUNIVERSAL_GPIO(LCD2,0);
++#else
++              pxa_set_cken(CKEN_LCD, 0);
++
++              SET_HTCUNIVERSAL_GPIO(LCD1,0);
++              SET_HTCUNIVERSAL_GPIO(LCD2,0);
++
++              asic3_set_gpio_out_c(&htcuniversal_asic3.dev, 1<<GPIOC_LCD_PWR2_ON, 0);
++              mdelay(100);
++              asic3_set_gpio_out_d(&htcuniversal_asic3.dev, 1<<GPIOD_LCD_PWR4_ON, 0);
++              mdelay(10);
++              asic3_set_gpio_out_a(&htcuniversal_asic3.dev, 1<<GPIOA_LCD_PWR5_ON, 0);
++              mdelay(1);
++              asic3_set_gpio_out_b(&htcuniversal_asic3.dev, 1<<GPIOB_LCD_PWR3_ON, 0);
++              mdelay(1);
++              asic3_set_gpio_out_c(&htcuniversal_asic3.dev, 1<<GPIOC_LCD_PWR1_ON, 0);
++#endif
++ return 0;
++}
++
++static int htcuniversal_lcd_set_power(struct lcd_device *lm, int power)
++{
++       /* Enable or disable power to the LCD (0: on; 4: off) */
++
++      if ( power < 1 ) {
++
++      powerup_lcd();
++
++      } else {
++
++      powerdown_lcd();
++
++      }
++
++      saved_lcdpower=power;
++
++      return 0;
++}
++
++static int htcuniversal_lcd_get_power(struct lcd_device *lm)
++{
++      /* Get the LCD panel power status (0: full on, 1..3: controller
++       * power on, flat panel power off, 4: full off) */
++
++      if (saved_lcdpower == -1)
++      {
++       htcuniversal_lcd_set_power(lm, 4);
++       saved_lcdpower=4;
++      }
++
++ return saved_lcdpower;
++}
++
++static struct lcd_ops htcuniversal_lcd_properties =
++{
++      .get_power      = htcuniversal_lcd_get_power,
++      .set_power      = htcuniversal_lcd_set_power,
++};
++
++static struct lcd_device *htcuniversal_lcd_dev;
++
++static int htcuniversal_lcd_probe(struct platform_device * dev)
++{
++      htcuniversal_lcd_dev = lcd_device_register("pxa2xx-fb", &dev->dev, NULL,
++                      &htcuniversal_lcd_properties);
++      if (IS_ERR(htcuniversal_lcd_dev)) {
++              printk("htcuniversal_lcd_probe: error registering devices\n");
++              return -1;
++      }
++
++      return 0;
++}
++
++static int htcuniversal_lcd_remove(struct platform_device * dev)
++{
++      htcuniversal_lcd_set_power(htcuniversal_lcd_dev, 4);
++      lcd_device_unregister(htcuniversal_lcd_dev);
++
++      return 0;
++}
++
++static int htcuniversal_lcd_suspend(struct platform_device * dev, pm_message_t state)
++{
++//    printk("htcuniversal_lcd_suspend: called.\n");
++      htcuniversal_lcd_set_power(htcuniversal_lcd_dev, 4);
++      return 0;
++}
++
++static int htcuniversal_lcd_resume(struct platform_device * dev)
++{
++//    printk("htcuniversal_lcd_resume: called.\n");
++
++      /* */
++#if 1
++      LCCR4|=LCCR4_PCDDIV;
++#endif
++
++      htcuniversal_lcd_set_power(htcuniversal_lcd_dev, 0);
++      return 0;
++}
++
++static struct platform_driver htcuniversal_lcd_driver = {
++      .driver = {
++              .name     = "htcuniversal_lcd",
++      },
++      .probe    = htcuniversal_lcd_probe,
++      .remove   = htcuniversal_lcd_remove,
++      .suspend  = htcuniversal_lcd_suspend,
++      .resume   = htcuniversal_lcd_resume,
++};
++
++static int htcuniversal_lcd_init(void)
++{
++      if (!machine_is_htcuniversal())
++              return -ENODEV;
++
++      return platform_driver_register(&htcuniversal_lcd_driver);
++}
++
++static void htcuniversal_lcd_exit(void)
++{
++      lcd_device_unregister(htcuniversal_lcd_dev);
++      platform_driver_unregister(&htcuniversal_lcd_driver);
++}
++
++module_init(htcuniversal_lcd_init);
++module_exit(htcuniversal_lcd_exit);
++
++MODULE_AUTHOR("xanadux.org");
++MODULE_DESCRIPTION("Framebuffer driver for HTC Universal");
++MODULE_LICENSE("GPL");
++
+Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_phone.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_phone.c   2007-09-11 12:53:37.000000000 +0200
+@@ -0,0 +1,167 @@
++
++/* Phone interface driver for Qualcomm MSM6250 on HTC Universal
++ *
++ * Copyright (c) 2005 SDG Systems, LLC
++ *
++ * 2005-04-21   Todd Blumer             Created.
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/delay.h>
++#include <linux/platform_device.h>
++#include <linux/soc/asic3_base.h>
++
++#include <asm/hardware.h>
++#include <asm/arch/serial.h>
++#include <asm/hardware/ipaq-asic3.h>
++#include <asm/arch/htcuniversal-gpio.h>
++#include <asm/arch/htcuniversal-asic.h>
++
++#include "htcuniversal_phone.h"
++
++static void phone_reset(void)
++{
++      asic3_set_gpio_out_b(&htcuniversal_asic3.dev, 1<<GPIOB_BB_RESET2, 0);
++
++      SET_HTCUNIVERSAL_GPIO(PHONE_RESET,0);
++      asic3_set_gpio_out_d(&htcuniversal_asic3.dev, 1<<GPIOD_BB_RESET1, 0);
++      mdelay(1);
++      asic3_set_gpio_out_d(&htcuniversal_asic3.dev, 1<<GPIOD_BB_RESET1, 1<<GPIOD_BB_RESET1);
++      mdelay(20);
++      SET_HTCUNIVERSAL_GPIO(PHONE_RESET,1);
++      mdelay(200);
++      asic3_set_gpio_out_d(&htcuniversal_asic3.dev, 1<<GPIOD_BB_RESET1, 0);
++}
++
++static void phone_off(void)
++{
++      asic3_set_gpio_out_d(&htcuniversal_asic3.dev, 1<<GPIOD_BB_RESET1, 1<<GPIOD_BB_RESET1);
++      mdelay(2000);
++      asic3_set_gpio_out_d(&htcuniversal_asic3.dev, 1<<GPIOD_BB_RESET1, 0);
++
++      asic3_set_gpio_out_b(&htcuniversal_asic3.dev, 1<<GPIOB_BB_RESET2, 1<<GPIOB_BB_RESET2);
++      SET_HTCUNIVERSAL_GPIO(PHONE_OFF,0);
++}
++
++static void
++htcuniversal_phone_configure( int state )
++{
++      int tries;
++      unsigned short statusb;
++
++      printk( KERN_NOTICE "htcuniversal configure phone: %d\n", state );
++      switch (state) {
++
++      case PXA_UART_CFG_PRE_STARTUP:
++              break;
++
++      case PXA_UART_CFG_POST_STARTUP:
++              /* pre-serial-up hardware configuration */
++
++              SET_HTCUNIVERSAL_GPIO(PHONE_START,0);   /* "bootloader" */
++              SET_HTCUNIVERSAL_GPIO(PHONE_UNKNOWN,0); /* not used     */
++              SET_HTCUNIVERSAL_GPIO(PHONE_OFF,0);     /* PHONE_OFF    */
++
++              phone_reset();
++
++              SET_HTCUNIVERSAL_GPIO(PHONE_START,1); /* phone */
++
++              phone_reset();
++
++              asic3_set_gpio_dir_b(&htcuniversal_asic3.dev, 1<<GPIOB_BB_READY, 0);
++              asic3_set_gpio_dir_b(&htcuniversal_asic3.dev, 1<<GPIOB_BB_UNKNOWN3, 0);
++
++              /*
++               */
++              tries = 0;
++              do {
++                      mdelay(10);
++                      statusb = asic3_get_gpio_status_b( &htcuniversal_asic3.dev );
++              } while ( (statusb & (1<<GPIOB_UMTS_DCD)) == 0 && tries++ < 200);
++
++              printk("UMTS_DCD tries=%d of 200\n",tries);
++
++              tries = 0;
++              do {
++                      SET_HTCUNIVERSAL_GPIO(PHONE_OFF,1);
++                      mdelay(10);
++                      SET_HTCUNIVERSAL_GPIO(PHONE_OFF,0);
++                      mdelay(20);
++                      statusb = asic3_get_gpio_status_b( &htcuniversal_asic3.dev );
++              } while ( (statusb & (1<<GPIOB_BB_READY)) == 0 && tries++ < 200);
++
++              printk("BB_READY tries=%d of 200\n",tries);
++
++              break;
++
++      case PXA_UART_CFG_PRE_SHUTDOWN:
++
++                      phone_off();
++
++              break;
++
++      default:
++              break;
++      }
++}
++
++
++static int
++htcuniversal_phone_probe( struct platform_device *dev )
++{
++      struct htcuniversal_phone_funcs *funcs = dev->dev.platform_data;
++
++      /* configure phone UART */
++      pxa_gpio_mode( GPIO_NR_HTCUNIVERSAL_PHONE_RXD_MD );
++      pxa_gpio_mode( GPIO_NR_HTCUNIVERSAL_PHONE_TXD_MD );
++      pxa_gpio_mode( GPIO_NR_HTCUNIVERSAL_PHONE_UART_CTS_MD );
++      pxa_gpio_mode( GPIO_NR_HTCUNIVERSAL_PHONE_UART_RTS_MD );
++
++      funcs->configure = htcuniversal_phone_configure;
++
++      return 0;
++}
++
++static int
++htcuniversal_phone_remove( struct platform_device *dev )
++{
++      struct htcuniversal_phone_funcs *funcs = dev->dev.platform_data;
++
++      funcs->configure = NULL;
++
++      asic3_set_gpio_dir_b(&htcuniversal_asic3.dev, 1<<GPIOB_BB_READY, 1<<GPIOB_BB_READY);
++      asic3_set_gpio_dir_b(&htcuniversal_asic3.dev, 1<<GPIOB_BB_UNKNOWN3, 1<<GPIOB_BB_UNKNOWN3);
++
++      return 0;
++}
++
++static struct platform_driver phone_driver = {
++      .driver   = {
++              .name     = "htcuniversal_phone",
++      },
++      .probe    = htcuniversal_phone_probe,
++      .remove   = htcuniversal_phone_remove,
++};
++
++static int __init
++htcuniversal_phone_init( void )
++{
++      printk(KERN_NOTICE "htcuniversal Phone Driver\n");
++      return platform_driver_register( &phone_driver );
++}
++
++static void __exit
++htcuniversal_phone_exit( void )
++{
++      platform_driver_unregister( &phone_driver );
++}
++
++module_init( htcuniversal_phone_init );
++module_exit( htcuniversal_phone_exit );
++
++MODULE_AUTHOR("Todd Blumer, SDG Systems, LLC");
++MODULE_DESCRIPTION("HTC Universal Phone Support Driver");
++MODULE_LICENSE("GPL");
++
++/* vim600: set noexpandtab sw=8 ts=8 :*/
+Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_phone.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_phone.h   2007-09-11 12:53:37.000000000 +0200
+@@ -0,0 +1,16 @@
++/*
++ * Bluetooth support file for calling bluetooth configuration functions
++ *
++ * Copyright (c) 2005 SDG Systems, LLC
++ *
++ * 2005-06    Todd Blumer             Initial Revision
++ */
++
++#ifndef _HTCUNIVERSAL_PHONE_H
++#define _HTCUNIVERSAL_PHONE_H
++
++struct htcuniversal_phone_funcs {
++      void (*configure) ( int state );
++};
++
++#endif
+Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_pm.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_pm.c      2007-09-11 12:53:37.000000000 +0200
+@@ -0,0 +1,69 @@
++/*
++ * MyPal 716 power management support for the original HTC IPL in DoC G3
++ *
++ * Use consistent with the GNU GPL is permitted, provided that this
++ * copyright notice is preserved in its entirety in all copies and
++ * derived works.
++ *
++ * Copyright (C) 2005 Pawel Kolodziejski
++ *
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/device.h>
++#include <linux/pm.h>
++
++#include <asm/mach-types.h>
++#include <asm/hardware.h>
++#include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa-pm_ll.h>
++
++#ifdef CONFIG_PM
++
++static u32 *addr_a0040000;
++static u32 *addr_a0040004;
++static u32 *addr_a0040008;
++static u32 *addr_a004000c;
++
++static u32 save_a0040000;
++static u32 save_a0040004;
++static u32 save_a0040008;
++static u32 save_a004000c;
++
++static void htcuniversal_pxa_ll_pm_suspend(unsigned long resume_addr)
++{
++      save_a0040000 = *addr_a0040000;
++      save_a0040004 = *addr_a0040004;
++      save_a0040008 = *addr_a0040008;
++      save_a004000c = *addr_a004000c;
++
++      /* jump to PSPR */
++      *addr_a0040000 = 0xe3a00101; // mov r0, #0x40000000
++      *addr_a0040004 = 0xe380060f; // orr r0, r0, #0x0f000000
++      *addr_a0040008 = 0xe3800008; // orr r0, r0, #8
++      *addr_a004000c = 0xe590f000; // ldr pc, [r0]
++}
++
++static void htcuniversal_pxa_ll_pm_resume(void)
++{
++      *addr_a0040000 = save_a0040000;
++      *addr_a0040004 = save_a0040004;
++      *addr_a0040008 = save_a0040008;
++      *addr_a004000c = save_a004000c;
++}
++
++static struct pxa_ll_pm_ops htcuniversal_ll_pm_ops = {
++      .suspend = htcuniversal_pxa_ll_pm_suspend,
++      .resume  = htcuniversal_pxa_ll_pm_resume,
++};
++
++void htcuniversal_ll_pm_init(void) {
++      addr_a0040000 = phys_to_virt(0xa0040000);
++      addr_a0040004 = phys_to_virt(0xa0040004);
++      addr_a0040008 = phys_to_virt(0xa0040008);
++      addr_a004000c = phys_to_virt(0xa004000c);
++
++      pxa_pm_set_ll_ops(&htcuniversal_ll_pm_ops);
++}
++#endif /* CONFIG_PM */
+Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_power2.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_power2.c  2007-09-11 12:53:37.000000000 +0200
+@@ -0,0 +1,97 @@
++/*
++ * pda_power driver for HTC Universal
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the 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/pda_power.h>
++#include <linux/soc/asic3_base.h>
++
++#include <asm/mach-types.h>
++#include <asm/hardware.h>
++#include <asm/arch/htcuniversal-gpio.h>
++#include <asm/arch/htcuniversal-asic.h>
++
++static void charge_on(int flags)
++{
++        asic3_set_gpio_out_b(&htcuniversal_asic3.dev, 1<<GPIOB_CHARGE_EN, 0);
++}
++
++static int ac_on(void)
++{
++ return (GET_HTCUNIVERSAL_GPIO(POWER_DET) == 0);
++}
++
++static int usb_on(void)
++{
++ return (GET_HTCUNIVERSAL_GPIO(USB_DET) == 0);
++}
++
++static char *supplicants[] = {
++      "ds2760-battery.0", "backup-battery"
++};
++
++static struct pda_power_pdata power_pdata = {
++      .is_ac_online   = ac_on,
++      .is_usb_online  = usb_on,
++      .set_charge     = charge_on,
++      .supplied_to = supplicants,
++      .num_supplicants = ARRAY_SIZE(supplicants),
++};
++
++static struct resource power_resources[] = {
++      [0] = {
++              .name   = "ac",
++              .start  = HTCUNIVERSAL_IRQ(POWER_DET),
++              .end    = HTCUNIVERSAL_IRQ(POWER_DET),
++              .flags  = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE | IORESOURCE_IRQ_LOWEDGE,
++      },
++      [1] = {
++              .name   = "usb",
++              .start  = HTCUNIVERSAL_IRQ(USB_DET),
++              .end    = HTCUNIVERSAL_IRQ(USB_DET),
++              .flags  = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE | IORESOURCE_IRQ_LOWEDGE,
++      },
++};
++
++static void dev_release(struct device *dev)
++{
++      return;
++}
++
++static struct platform_device power_dev =
++{
++      .name           = "pda-power",
++      .id             = -1,
++      .resource       = power_resources,
++      .num_resources  = ARRAY_SIZE(power_resources),
++      .dev =
++       {
++              .platform_data  = &power_pdata,
++              .release        = dev_release,
++       },
++};
++
++static int htcuniversal_power_init(void)
++{
++ return platform_device_register(&power_dev);
++}
++
++static void htcuniversal_power_exit(void)
++{
++      platform_device_unregister(&power_dev);
++
++      return;
++}
++
++module_init(htcuniversal_power_init);
++module_exit(htcuniversal_power_exit);
++
++MODULE_DESCRIPTION("Power driver for HTC Universal");
++MODULE_LICENSE("GPL");
+Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_ts2.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_ts2.c     2007-09-11 12:53:37.000000000 +0200
+@@ -0,0 +1,490 @@
++/* Touch screen driver for the TI something-or-other
++ *
++ * Copyright Â© 2005 SDG Systems, LLC
++ *
++ * Based on code that was based on the SAMCOP driver.
++ *     Copyright Â© 2003, 2004 Compaq Computer Corporation.
++ *
++ * Use consistent with the GNU GPL is permitted,
++ * provided that this copyright notice is
++ * preserved in its entirety in all copies and derived works.
++ *
++ * COMPAQ COMPUTER CORPORATION MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
++ * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
++ * FITNESS FOR ANY PARTICULAR PURPOSE.
++ *
++ * Author:  Keith Packard <keith.packard@hp.com>
++ *          May 2003
++ *
++ * Updates:
++ *
++ * 2004-02-11   Michael Opdenacker      Renamed names from samcop to shamcop,
++ *                                      Goal:support HAMCOP and SAMCOP.
++ * 2004-02-14   Michael Opdenacker      Temporary fix for device id handling
++ *
++ * 2005-02-18   Aric Blumer             Converted  basic structure to support hx4700
++ *
++ * 2005-06-07   Aric Blumer             Added tssim device handling so we can
++ *                                      hook in the fbvncserver.
++ */
++
++#include <linux/module.h>
++#include <linux/version.h>
++
++#include <linux/init.h>
++#include <linux/fs.h>
++#include <linux/cdev.h>
++#include <linux/interrupt.h>
++#include <linux/sched.h>
++#include <linux/pm.h>
++#include <linux/delay.h>
++#include <linux/input.h>
++#include <linux/platform_device.h>
++#include <linux/irq.h>
++
++#include <asm/arch/hardware.h>
++#include <asm/mach/irq.h>
++#include <asm/io.h>
++
++/* remove me */
++#include <asm/arch/pxa-regs.h>
++#include <asm/arch/htcuniversal-gpio.h>
++#include <asm/arch/htcuniversal-asic.h>
++#include <asm/mach-types.h>
++
++#include <asm/hardware/ipaq-asic3.h>
++#include <linux/soc/asic3_base.h>
++
++
++#include "tsc2046_ts.h"
++
++enum touchscreen_state {
++    STATE_WAIT_FOR_TOUCH,   /* Waiting for a PEN interrupt */
++    STATE_SAMPLING          /* Actively sampling ADC */
++};
++
++struct touchscreen_data {
++    enum touchscreen_state state;
++    struct timer_list      timer;
++    int                    irq;
++    struct input_dev       *input;
++    /* */
++    int                       port;
++    int                       clock;
++    int                       pwrbit_X;
++    int                       pwrbit_Y;
++    int                       (*pen_down)(void);
++};
++
++static unsigned long poll_sample_time   = 10; /* Sample every 10 milliseconds */
++
++static struct touchscreen_data *ts_data;
++
++static int irqblock;
++
++module_param(poll_sample_time, ulong, 0644);
++MODULE_PARM_DESC(poll_sample_time, "Poll sample time");
++
++static inline void
++report_touchpanel(struct touchscreen_data *ts, int pressure, int x, int y)
++{
++    input_report_abs(ts->input, ABS_PRESSURE, pressure);
++    input_report_abs(ts->input, ABS_X, x);
++    input_report_abs(ts->input, ABS_Y, y);
++    input_sync(ts->input);
++}
++
++static void start_read(struct touchscreen_data *touch);
++
++static irqreturn_t
++pen_isr(int irq, void *irq_desc)
++{
++    struct touchscreen_data *ts = ts_data;
++
++    if(irq == ts->irq /* && !irqblock */) {
++        irqblock = 1;
++
++        /*
++         * Disable the pen interrupt.  It's reenabled when the user lifts the
++         * pen.
++         */
++        disable_irq(ts->irq);
++
++        if (ts->state == STATE_WAIT_FOR_TOUCH) {
++            ts->state = STATE_SAMPLING;
++            start_read(ts);
++        } else {
++            /* Shouldn't happen */
++            printk(KERN_ERR "Unexpected ts interrupt\n");
++        }
++
++    }
++    return IRQ_HANDLED;
++}
++
++static void
++ssp_init(int port, int clock)
++{
++
++    pxa_set_cken(clock, 0);
++
++    pxa_gpio_mode(GPIO_NR_HTCUNIVERSAL_TOUCHSCREEN_SPI_CLK_MD);
++    pxa_gpio_mode(GPIO_NR_HTCUNIVERSAL_TOUCHSCREEN_SPI_FRM_MD);
++    pxa_gpio_mode(GPIO_NR_HTCUNIVERSAL_TOUCHSCREEN_SPI_DO_MD);
++    pxa_gpio_mode(GPIO_NR_HTCUNIVERSAL_TOUCHSCREEN_SPI_DI_MD);
++
++    SET_HTCUNIVERSAL_GPIO(SPI_FRM,1);
++
++    /* *** Set up the SPI Registers *** */
++    SSCR0_P(port) =
++          SSCR0_EDSS         /* Extended Data Size Select */
++        | SSCR0_SerClkDiv(7) /* Serial Clock Rate */
++                             /* Synchronous Serial Enable (Disable for now) */
++        | SSCR0_Motorola     /* Motorola SPI Interface */
++        | SSCR0_DataSize(8)  /* Data Size Select  (24-bit) */
++        ;
++    SSCR1_P(port) = 0;
++    SSPSP_P(port) = 0;
++
++    /* Clear the Status */
++    SSSR_P(port)  = SSSR_P(port) & 0x00fcfffc;
++
++    /* Now enable it */
++    SSCR0_P(port) =
++          SSCR0_EDSS         /* Extended Data Size Select */
++        | SSCR0_SerClkDiv(7) /* Serial Clock Rate */
++        | SSCR0_SSE          /* Synchronous Serial Enable */
++        | SSCR0_Motorola     /* Motorola SPI Interface */
++        | SSCR0_DataSize(8)  /* Data Size Select  (24-bit) */
++        ;
++
++    pxa_set_cken(clock, 1);
++}
++
++static void
++start_read(struct touchscreen_data *touch)
++{
++    unsigned long inc = (poll_sample_time * HZ) / 1000;
++    int i;
++
++    /* Write here to the serial port. We request X and Y only for now.
++     * Then we have to wait for poll_sample_time before we read out the serial
++     * port.  Then, when we read it out, we check to see if the pen is still
++     * down.  If so, then we issue another request here.
++     */
++#define TS_SAMPLES 7
++
++    /*
++     * We do four samples for each, and throw out the highest and lowest, then
++     * average the other two.
++     */
++
++    for(i = 0; i < TS_SAMPLES; i++) {
++        while(!(SSSR_P(touch->port) & SSSR_TNF))
++            ;
++        /* It's not full. Write the command for X */
++        SSDR_P(touch->port) = (TSC2046_SAMPLE_X|(touch->pwrbit_X))<<16;
++    }
++
++    for(i = 0; i < TS_SAMPLES; i++) {
++        while(!(SSSR_P(touch->port) & SSSR_TNF))
++            ;
++        /* It's not full. Write the command for Y */
++        SSDR_P(touch->port)  = (TSC2046_SAMPLE_Y|(touch->pwrbit_Y))<<16;
++    }
++
++    /*
++     * Enable the timer. We should get an interrupt, but we want keep a timer
++     * to ensure that we can detect missing data
++     */
++    mod_timer(&touch->timer, jiffies + inc);
++}
++
++static void
++ts_timer_callback(unsigned long data)
++{
++    struct touchscreen_data *ts = (struct touchscreen_data *)data;
++    int x, a[TS_SAMPLES], y;
++    static int oldx, oldy;
++    int ssrval;
++
++    /*
++     * Check here to see if there is anything in the SPI FIFO.  If so,
++     * return it if there has been a change.  If not, then we have a
++     * timeout.  Generate an erro somehow.
++     */
++    ssrval = SSSR_P(ts->port);
++
++    if(ssrval & SSSR_RNE) { /* Look at Rx Not Empty bit */
++        int number_of_entries_in_fifo;
++
++        /* The FIFO is not emtpy. Good! Now make sure there are at least two
++         * entries. (Should be two exactly.) */
++
++        number_of_entries_in_fifo = ((ssrval >> 12) & 0xf) + 1;
++
++        if(number_of_entries_in_fifo < TS_SAMPLES * 2) {
++            /* Not ready yet. Come back later. */
++            unsigned long inc = (poll_sample_time * HZ) / 1000;
++            mod_timer(&ts->timer, jiffies + inc);
++            return;
++        }
++
++        if(number_of_entries_in_fifo == TS_SAMPLES * 2) {
++            int i, j;
++
++            for(i = 0; i < TS_SAMPLES; i++) {
++                a[i] = SSDR_P(ts->port);
++            }
++            /* Sort them (bubble) */
++            for(j = TS_SAMPLES - 1; j > 0; j--) {
++                for(i = 0; i < j; i++) {
++                    if(a[i] > a[i + 1]) {
++                        int tmp;
++                        tmp    = a[i+1];
++                        a[i+1] = a[i];
++                        a[i]   = tmp;
++                    }
++                }
++            }
++
++            /* Take the average of the middle two */
++            /* x = (a[TS_SAMPLES/2 - 1] + a[TS_SAMPLES/2] + a[TS_SAMPLES/2+1] + a[TS_SAMPLES/2+2]) >> 2; */
++            x = a[TS_SAMPLES/2];
++
++            for(i = 0; i < TS_SAMPLES; i++) {
++                a[i] = SSDR_P(ts->port);
++            }
++            /* Sort them (bubble) */
++            for(j = TS_SAMPLES - 1; j > 0; j--) {
++                for(i = 0; i < j; i++) {
++                    if(a[i] > a[i + 1]) {
++                        int tmp;
++                        tmp    = a[i+1];
++                        a[i+1] = a[i];
++                        a[i]   = tmp;
++                    }
++                }
++            }
++
++
++            /* Take the average of the middle two */
++            /* y = (a[TS_SAMPLES/2 - 1] + a[TS_SAMPLES/2] + a[TS_SAMPLES/2+1] + a[TS_SAMPLES/2+2]) >> 2; */
++            y = a[TS_SAMPLES/2];
++        } else {
++            /* We have an error! Too many entries. */
++            printk(KERN_ERR "TS: Expected %d entries. Got %d\n", TS_SAMPLES*2, number_of_entries_in_fifo);
++            /* Try to clear the FIFO */
++            while(number_of_entries_in_fifo--) {
++                (void)SSDR_P(ts->port);
++            }
++
++            if (ts->pen_down())
++                start_read(ts);
++
++            return;
++        }
++    } else {
++        /* Not ready yet. Come back later. */
++        unsigned long inc = (poll_sample_time * HZ) / 1000;
++        mod_timer(&ts->timer, jiffies + inc);
++        return;
++    }
++
++    /*
++     * Now we check to see if the pen is still down.  If it is, then call
++     * start_read().
++     */
++    if (ts->pen_down())
++    {
++        /* Still down */
++        if(oldx != x || oldy != y) {
++            oldx = x;
++            oldy = y;
++            report_touchpanel(ts, 1, x, y);
++        }
++        start_read(ts);
++    } else {
++        /* Up */
++        report_touchpanel(ts, 0, 0, 0);
++        irqblock = 0;
++        ts->state = STATE_WAIT_FOR_TOUCH;
++        /* Re-enable pen down interrupt */
++        enable_irq(ts->irq);
++    }
++}
++
++static int pen_down(void)
++{
++ return ( asic3_get_gpio_status_a( &htcuniversal_asic3.dev ) & (1<<GPIOA_TOUCHSCREEN_N)) == 0 ;
++}
++
++static int
++ts_probe (struct platform_device *dev)
++{
++    int retval;
++    struct touchscreen_data *ts;
++    struct tsc2046_mach_info *mach = dev->dev.platform_data;
++
++    printk("htcuniversal: ts_probe\n");
++
++    ts = ts_data = kmalloc (sizeof (*ts), GFP_KERNEL);
++    if (ts == NULL) {
++      printk( KERN_NOTICE "htcuniversal_ts: unable to allocate memory\n" );
++      return -ENOMEM;
++    }
++    memset (ts, 0, sizeof (*ts));
++
++    ts->input = input_allocate_device();
++    if (ts->input == NULL) {
++      printk( KERN_NOTICE "htcuniversal_ts: unable to allocation touchscreen input\n" );
++      kfree(ts);
++      return -ENOMEM;
++    }
++    ts->input->evbit[0]             = BIT(EV_ABS);
++    ts->input->absbit[0]            = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE);
++    ts->input->absmin[ABS_X]        = 0;
++    ts->input->absmax[ABS_X]        = 32767;
++    ts->input->absmin[ABS_Y]        = 0;
++    ts->input->absmax[ABS_Y]        = 32767;
++    ts->input->absmin[ABS_PRESSURE] = 0;
++    ts->input->absmax[ABS_PRESSURE] = 1;
++
++    ts->input->name = "htcuniversal_ts";
++    ts->input->phys =  "touchscreen/htcuniversal_ts";
++    ts->input->private = ts;
++
++    input_register_device(ts->input);
++
++    ts->timer.function = ts_timer_callback;
++    ts->timer.data = (unsigned long)ts;
++    ts->state = STATE_WAIT_FOR_TOUCH;
++    init_timer (&ts->timer);
++
++    platform_set_drvdata(dev, ts);
++
++    ts->port=-1;
++
++    if (mach) {
++        ts->port = mach->port;
++        ts->clock = mach->clock;
++        ts->pwrbit_X = mach->pwrbit_X;
++        ts->pwrbit_Y = mach->pwrbit_Y;
++
++        /* static irq */
++        if (mach->irq)
++         ts->irq = mach->irq;
++
++        if (mach->pen_down)
++         ts->pen_down=mach->pen_down;
++    }
++
++    if (ts->port == -1)
++    {
++     printk("tsc2046: your device is not supported by this driver\n");
++     return -ENODEV;
++    }
++
++    /* *** Initialize the SSP interface *** */
++    ssp_init(ts->port, ts->clock);
++
++    while(!(SSSR_P(ts->port) & SSSR_TNF))
++        ;
++    SSDR_P(ts->port) = (TSC2046_SAMPLE_X|(ts->pwrbit_X))<<16;
++
++    for(retval = 0; retval < 100; retval++) {
++        if(SSSR_P(ts->port) & SSSR_RNE) {
++            while(SSSR_P(ts->port) & SSSR_RNE) {
++                (void)SSDR_P(ts->port);
++            }
++            break;
++        }
++        mdelay(1);
++    }
++
++    if (machine_is_htcuniversal() )
++    {
++     ts->irq = asic3_irq_base( &htcuniversal_asic3.dev ) + ASIC3_GPIOA_IRQ_BASE + GPIOA_TOUCHSCREEN_N;
++     ts->pen_down=pen_down;
++    }
++
++    retval = request_irq(ts->irq, pen_isr, IRQF_DISABLED, "tsc2046_ts", ts);
++    if(retval) {
++        printk("Unable to get interrupt\n");
++        input_unregister_device (ts->input);
++        return -ENODEV;
++    }
++    set_irq_type(ts->irq, IRQ_TYPE_EDGE_FALLING);
++
++    return 0;
++}
++
++static int
++ts_remove (struct platform_device *dev)
++{
++    struct touchscreen_data *ts = platform_get_drvdata(dev);
++
++    input_unregister_device (ts->input);
++    del_timer_sync (&ts->timer);
++    free_irq (ts->irq, ts);
++    pxa_set_cken(ts->clock, 0);
++
++    kfree(ts);
++    return 0;
++}
++
++static int
++ts_suspend (struct platform_device *dev, pm_message_t state)
++{
++    struct touchscreen_data *ts = platform_get_drvdata(dev);
++
++    disable_irq(ts->irq);
++
++    printk("htcuniversal_ts2_suspend: called.\n");
++    return 0;
++}
++
++static int
++ts_resume (struct platform_device *dev)
++{
++    struct touchscreen_data *ts = platform_get_drvdata(dev);
++
++    ts->state = STATE_WAIT_FOR_TOUCH;
++    ssp_init(ts->port, ts->clock);
++    enable_irq(ts->irq);
++
++    printk("htcuniversal_ts2_resume: called.\n");
++    return 0;
++}
++
++static struct platform_driver ts_driver = {
++    .probe    = ts_probe,
++    .remove   = ts_remove,
++    .suspend  = ts_suspend,
++    .resume   = ts_resume,
++    .driver = {
++              .name = "htcuniversal_ts",
++      },
++};
++
++
++static int
++ts_module_init (void)
++{
++    printk(KERN_NOTICE "HTC Universal Touch Screen Driver\n");
++
++    return platform_driver_register(&ts_driver);
++}
++
++static void
++ts_module_cleanup (void)
++{
++    platform_driver_unregister (&ts_driver);
++}
++
++module_init(ts_module_init);
++module_exit(ts_module_cleanup);
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Aric Blumer, SDG Systems, LLC");
++MODULE_DESCRIPTION("HTC Universal Touch Screen Driver");
+Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_udc.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_udc.c     2007-09-11 12:53:37.000000000 +0200
+@@ -0,0 +1,71 @@
++
++/*
++ *
++ * htcuniversal_udc.c:
++ * htcuniversal specific code for the pxa27x usb device controller.
++ *
++ * Use consistent with the GNU GPL is permitted.
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/platform_device.h>
++#include <asm/arch/hardware.h>
++#include <asm/arch/pxa-regs.h>
++#include <asm/arch/udc.h>
++#include <linux/soc/asic3_base.h>
++#include <asm/arch/htcuniversal-gpio.h>
++#include <asm/arch/htcuniversal-asic.h>
++
++static void htcuniversal_udc_command(int cmd)
++{
++      switch (cmd) {
++      case PXA2XX_UDC_CMD_DISCONNECT:
++              asic3_set_gpio_out_b(&htcuniversal_asic3.dev,
++                                         1<<GPIOB_USB_PUEN, 0);
++//            SET_HTCUNIVERSAL_GPIO(USB_PUEN,0);
++              break;
++      case PXA2XX_UDC_CMD_CONNECT:
++              asic3_set_gpio_out_b(&htcuniversal_asic3.dev,
++                                         1<<GPIOB_USB_PUEN,  1<<GPIOB_USB_PUEN);
++//            SET_HTCUNIVERSAL_GPIO(USB_PUEN,1);
++              break;
++      default:
++              printk("_udc_control: unknown command!\n");
++              break;
++      }
++}
++
++static int htcuniversal_udc_is_connected(void)
++{
++      return (GET_HTCUNIVERSAL_GPIO(USB_DET) != 0);
++}
++
++static struct pxa2xx_udc_mach_info htcuniversal_udc_info __initdata = {
++      .udc_is_connected = htcuniversal_udc_is_connected,
++      .udc_command      = htcuniversal_udc_command,
++};
++
++static int htcuniversal_udc_probe(struct platform_device * dev)
++{
++      asic3_set_gpio_dir_b(&htcuniversal_asic3.dev, 1<<GPIOB_USB_PUEN, 1<<GPIOB_USB_PUEN);
++
++      pxa_set_udc_info(&htcuniversal_udc_info);
++      return 0;
++}
++
++static struct platform_driver htcuniversal_udc_driver = {
++      .driver   = {
++              .name     = "htcuniversal_udc",
++      },
++      .probe    = htcuniversal_udc_probe,
++};
++
++static int __init htcuniversal_udc_init(void)
++{
++      return platform_driver_register(&htcuniversal_udc_driver);
++}
++
++module_init(htcuniversal_udc_init);
++MODULE_LICENSE("GPL");
+Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/tsc2046_ts.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/tsc2046_ts.h   2007-09-11 12:53:37.000000000 +0200
+@@ -0,0 +1,20 @@
++/*
++ * temporary TSC2046 touchscreen hack
++ */
++
++#ifndef _TSC2046_TS_H
++#define _TSC2046_TS_H
++
++struct tsc2046_mach_info {
++    int port;
++    int clock;
++    int pwrbit_X;
++    int pwrbit_Y;
++    int irq;
++    int (*pen_down)(void);
++};
++
++#define TSC2046_SAMPLE_X 0xd0
++#define TSC2046_SAMPLE_Y 0x90
++
++#endif
+Index: linux-2.6.22/arch/arm/mach-pxa/Kconfig
+===================================================================
+--- linux-2.6.22.orig/arch/arm/mach-pxa/Kconfig        2007-09-11 12:53:33.000000000 +0200
++++ linux-2.6.22/arch/arm/mach-pxa/Kconfig     2007-09-11 12:53:37.000000000 +0200
+@@ -50,6 +50,14 @@
+       help
+         This enables support for the HP iPAQ HX2750 handheld.
++config MACH_HTCUNIVERSAL
++      bool "HTC Universal"
++      select PXA27x
++      help
++        Say Y here if you intend to run this kernel on a
++        HTC Universal. Currently there is only basic support
++        for this PDA.
++
+ endchoice
+ if PXA_SHARPSL
+@@ -84,6 +92,86 @@
+ endif
++if MACH_HTCUNIVERSAL
++
++menu "HTC Universal support"
++
++config HTCUNIVERSAL_CORE
++        tristate "HTC Universal core"
++        depends on MACH_HTCUNIVERSAL
++        help
++          This selection enables HTC Universal core support.
++
++config HTCUNIVERSAL_UDC
++        bool "USB Device Controller support"
++        depends on MACH_HTCUNIVERSAL && HTC_ASIC3 && USB_PXA27X
++        help
++          Enables HTC Universal specific USB detection
++
++config HTCUNIVERSAL_POWER
++        tristate "HTC Universal power"
++        depends on MACH_HTCUNIVERSAL && HTC_ASIC3
++        help
++          This selection enables HTC Universal power monitoring
++                  hardware support (through ASIC3).
++
++config HTCUNIVERSAL_BACKLIGHT
++      bool "HTC Universal Backlight"
++      depends on MACH_HTCUNIVERSAL && HTC_ASIC3 && BACKLIGHT_CLASS_DEVICE
++      help
++        This driver provides support for changing power and brightness
++        on HTC Universal LCD backlight.
++
++config HTCUNIVERSAL_LCD
++      tristate "HTC Universal LCD"
++      depends on MACH_HTCUNIVERSAL && HTC_ASIC3 && LCD_CLASS_DEVICE
++      help
++        This driver provides support for changing power and brightness
++        on HTC Universal LCD display.
++
++config HTCUNIVERSAL_TS2
++      tristate "HTC Universal Touchscreen (old)"
++      depends on MACH_HTCUNIVERSAL && HTC_ASIC3
++      help
++        Enable support for the HTC Universal Touchscreen Panel.
++
++config HTCUNIVERSAL_BUTTONS
++        tristate "HTC Universal buttons support"
++        depends on MACH_HTCUNIVERSAL && HTC_ASIC3
++
++config HTCUNIVERSAL_BLUETOOTH
++      tristate "HTC Universal Bluetooth"
++      depends on MACH_HTCUNIVERSAL && HTCUNIVERSAL_CORE && HTC_ASIC3
++      help
++        Enables support for the TI BRF6150 Bluetooth Module
++        in the HTC Universal.
++
++config HTCUNIVERSAL_ASIC3_LEDS
++      tristate "HTC Universal ASIC3 LED support"
++      select LEDS_ASIC3
++      depends on MACH_HTCUNIVERSAL && HTCUNIVERSAL_CORE && HTC_ASIC3
++      ---help---
++      Support for right (colors red+green+(amber)) and left (green+blue) led
++      Off/on hook keys LED backlight
++      Keyboard backlight
++      Vibra
++      Flashlight
++
++config HTCUNIVERSAL_PHONE
++      tristate "HTC Universal Phone"
++      depends on MACH_HTCUNIVERSAL && HTCUNIVERSAL_CORE && HTC_ASIC3
++      help
++        Enables support for the Qualcomm MSM6520 Phone Module
++        in the HTC Universal.
++
++config HTCUNIVERSAL_AK4641
++      depends on SND && I2C
++      tristate "AK4641 chipset support"
++
++endmenu
++
++endif
++
+ endmenu
+ config MACH_POODLE
+@@ -164,4 +252,3 @@
+       depends on (PXA25x || PXA27x) && INPUT
+ endif
+-
+Index: linux-2.6.22/arch/arm/mach-pxa/Makefile
+===================================================================
+--- linux-2.6.22.orig/arch/arm/mach-pxa/Makefile       2007-09-11 12:53:33.000000000 +0200
++++ linux-2.6.22/arch/arm/mach-pxa/Makefile    2007-09-11 12:53:37.000000000 +0200
+@@ -20,6 +20,7 @@
+ obj-$(CONFIG_MACH_TOSA)         += tosa.o
+ obj-$(CONFIG_MACH_EM_X270) += em-x270.o
+ obj-$(CONFIG_MACH_HX2750)     += hx2750.o hx2750_test.o
++obj-$(CONFIG_MACH_HTCUNIVERSAL) += htcuniversal/
+ # Support for blinky lights
+ led-y := leds.o
+Index: linux-2.6.22/drivers/leds/Kconfig
+===================================================================
+--- linux-2.6.22.orig/drivers/leds/Kconfig     2007-09-11 12:53:14.000000000 +0200
++++ linux-2.6.22/drivers/leds/Kconfig  2007-09-11 12:53:37.000000000 +0200
+@@ -101,6 +101,13 @@
+         outputs. To be useful the particular board must have LEDs
+         and they must be connected to the GPIO lines.
++config LEDS_ASIC3
++      tristate "LED Support for the HTC ASIC3 chip"
++      depends LEDS_CLASS && HTC_ASIC3
++      help
++        This option enables support for the LEDs connected to the
++        HTC ASIC3 chip.
++
+ comment "LED Triggers"
+ config LEDS_TRIGGERS
+Index: linux-2.6.22/drivers/leds/leds-asic3.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/drivers/leds/leds-asic3.c     2007-09-11 12:53:37.000000000 +0200
+@@ -0,0 +1,189 @@
++/*
++ * LEDs support for HTC ASIC3 devices.
++ *
++ * Copyright (c) 2006  Anton Vorontsov <cbou@mail.ru>
++ *
++ * 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/init.h>
++#include <linux/platform_device.h>
++#include <linux/leds.h>
++#include "leds.h"
++
++#include <asm/hardware/ipaq-asic3.h>
++#include <linux/soc/asic3_base.h>
++#include <asm/mach-types.h>
++#include <asm/hardware/asic3_leds.h>
++
++#ifdef DEBUG
++#define dbg(msg, ...) printk(msg, __VA_ARGS__)
++#else
++#define dbg(msg, ...)
++#endif
++
++static
++void asic3_leds_set(struct led_classdev *led_cdev, enum led_brightness b)
++{
++      struct asic3_led *led = container_of(led_cdev, struct asic3_led,
++                                           led_cdev);
++      struct asic3_leds_machinfo *machinfo = led->machinfo;
++      struct device *asic3_dev = &machinfo->asic3_pdev->dev;
++
++      dbg("%s:%s %d(%d)-%s %d\n", __FILE__, __FUNCTION__, led->hw_num,
++          led->gpio_num, led->led_cdev.name, b);
++
++      if (led->hw_num == -1) {
++              asic3_gpio_set_value(asic3_dev, led->gpio_num, b);
++              return;
++      }
++
++      if (b == LED_OFF) {
++              asic3_set_led(asic3_dev, led->hw_num, 0, 16, 6);
++              asic3_set_gpio_out_c(asic3_dev, led->hw_num, 0);
++      }
++      else {
++              asic3_set_gpio_out_c(asic3_dev, led->hw_num, led->hw_num);
++              #ifdef CONFIG_LEDS_TRIGGER_HWTIMER
++              if (led_cdev->trigger && led_cdev->trigger->is_led_supported &&
++                             (led_cdev->trigger->is_led_supported(led_cdev) &
++                              LED_SUPPORTS_HWTIMER)) {
++                      struct hwtimer_data *td = led_cdev->trigger_data;
++                      if (!td) return;
++                      asic3_set_led(asic3_dev, led->hw_num, td->delay_on/8,
++                                         (td->delay_on + td->delay_off)/8, 6);
++              }
++              else
++              #endif
++              asic3_set_led(asic3_dev, led->hw_num, 16, 16, 6);
++      }
++
++      return;
++}
++
++static
++int asic3_leds_probe(struct platform_device *pdev)
++{
++      struct asic3_leds_machinfo *machinfo = pdev->dev.platform_data;
++      struct asic3_led *leds = machinfo->leds;
++      int ret, i = 0;
++
++      dbg("%s:%s\n", __FILE__, __FUNCTION__);
++
++      // Turn on clocks early, for the case if trigger would enable
++      // led immediately after led_classdev_register().
++      asic3_set_clock_cdex(&machinfo->asic3_pdev->dev,
++              CLOCK_CDEX_LED0 | CLOCK_CDEX_LED1 | CLOCK_CDEX_LED2,
++              CLOCK_CDEX_LED0 | CLOCK_CDEX_LED1 | CLOCK_CDEX_LED2);
++
++      for (i = 0; i < machinfo->num_leds; i++) {
++              leds[i].machinfo = machinfo;
++              leds[i].led_cdev.brightness_set = asic3_leds_set;
++              ret = led_classdev_register(&pdev->dev, &leds[i].led_cdev);
++              if (ret) {
++                      printk(KERN_ERR "Error: can't register %s led\n",
++                             leds[i].led_cdev.name);
++                      goto out_err;
++              }
++      }
++
++      return 0;
++
++out_err:
++      while (--i >= 0) led_classdev_unregister(&leds[i].led_cdev);
++
++      asic3_set_clock_cdex(&machinfo->asic3_pdev->dev,
++              CLOCK_CDEX_LED0 | CLOCK_CDEX_LED1 | CLOCK_CDEX_LED2,
++              0               | 0               | 0);
++
++      return ret;
++}
++
++static
++int asic3_leds_remove(struct platform_device *pdev)
++{
++      struct asic3_leds_machinfo *machinfo = pdev->dev.platform_data;
++      struct asic3_led *leds = machinfo->leds;
++      int i = 0;
++
++      dbg("%s:%s\n", __FILE__, __FUNCTION__);
++
++      for (i = 0; i < machinfo->num_leds; i++)
++              led_classdev_unregister(&leds[i].led_cdev);
++
++      asic3_set_clock_cdex(&machinfo->asic3_pdev->dev,
++              CLOCK_CDEX_LED0 | CLOCK_CDEX_LED1 | CLOCK_CDEX_LED2,
++              0               | 0               | 0);
++
++      return 0;
++}
++
++#ifdef CONFIG_PM
++
++static
++int asic3_leds_suspend(struct platform_device *pdev, pm_message_t state)
++{
++      struct asic3_leds_machinfo *machinfo = pdev->dev.platform_data;
++      struct asic3_led *leds = machinfo->leds;
++      int i = 0;
++
++      dbg("%s:%s\n", __FILE__, __FUNCTION__);
++
++      for (i = 0; i < machinfo->num_leds; i++)
++              led_classdev_suspend(&leds[i].led_cdev);
++
++      return 0;
++}
++
++static
++int asic3_leds_resume(struct platform_device *pdev)
++{
++      struct asic3_leds_machinfo *machinfo = pdev->dev.platform_data;
++      struct asic3_led *leds = machinfo->leds;
++      int i = 0;
++
++      dbg("%s:%s\n", __FILE__, __FUNCTION__);
++
++      for (i = 0; i < machinfo->num_leds; i++)
++              led_classdev_resume(&leds[i].led_cdev);
++
++      return 0;
++}
++
++#endif
++
++static
++struct platform_driver asic3_leds_driver = {
++      .probe = asic3_leds_probe,
++      .remove = asic3_leds_remove,
++#ifdef CONFIG_PM
++      .suspend = asic3_leds_suspend,
++      .resume = asic3_leds_resume,
++#endif
++      .driver = {
++              .name = "asic3-leds",
++      },
++};
++
++int asic3_leds_register(void)
++{
++      dbg("%s:%s\n", __FILE__, __FUNCTION__);
++      return platform_driver_register(&asic3_leds_driver);
++}
++
++void asic3_leds_unregister(void)
++{
++      platform_driver_unregister(&asic3_leds_driver);
++      return;
++}
++
++EXPORT_SYMBOL_GPL(asic3_leds_register);
++EXPORT_SYMBOL_GPL(asic3_leds_unregister);
++
++MODULE_AUTHOR("Anton Vorontsov <cbou@mail.ru>");
++MODULE_DESCRIPTION("HTC ASIC3 LEDs driver");
++MODULE_LICENSE("GPL");
+Index: linux-2.6.22/drivers/mfd/Kconfig
+===================================================================
+--- linux-2.6.22.orig/drivers/mfd/Kconfig      2007-09-11 12:53:30.000000000 +0200
++++ linux-2.6.22/drivers/mfd/Kconfig   2007-09-11 12:53:37.000000000 +0200
+@@ -15,6 +15,16 @@
+         interface. The device may be connected by PCI or local bus with
+         varying functions enabled.
++config HTC_ASIC3
++        tristate "HTC ASIC3 (iPAQ h1900/h3900/h4000/hx4700/rx3000) support"
++
++config HTC_ASIC3_DS1WM
++       bool "Support HTC ASIC3 builtin DS1WM block"
++       help
++           Choose Y here if you want to include support for ASIC3's builtin
++           W1 controller. Some devices do not use it, and yet other have
++           separate DS1WM controller. For them, choose N.
++
+ endmenu
+ menu "Multimedia Capabilities Port drivers"
+Index: linux-2.6.22/drivers/mfd/Makefile
+===================================================================
+--- linux-2.6.22.orig/drivers/mfd/Makefile     2007-09-11 12:53:30.000000000 +0200
++++ linux-2.6.22/drivers/mfd/Makefile  2007-09-11 12:53:37.000000000 +0200
+@@ -2,6 +2,8 @@
+ # Makefile for multifunction miscellaneous devices
+ #
++obj-$(CONFIG_HTC_ASIC3)         += asic3_base.o soc-core.o
++
+ obj-$(CONFIG_MFD_SM501)               += sm501.o
+ obj-$(CONFIG_MCP)             += mcp-core.o
+Index: linux-2.6.22/drivers/mfd/asic3_base.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/drivers/mfd/asic3_base.c      2007-09-11 12:53:37.000000000 +0200
+@@ -0,0 +1,1208 @@
++/*
++ * Driver interface to HTC "ASIC3"
++ *
++ * Copyright 2001 Compaq Computer Corporation.
++ * Copyright 2004-2005 Phil Blundell
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * COMPAQ COMPUTER CORPORATION MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
++ * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
++ * FITNESS FOR ANY PARTICULAR PURPOSE.
++ *
++ * Author:  Andrew Christian
++ *          <Andrew.Christian@compaq.com>
++ *          October 2001
++ */
++
++#include <linux/module.h>
++#include <linux/version.h>
++#include <linux/platform_device.h>
++#include <linux/delay.h>
++#include <linux/init.h>
++#include <linux/irq.h>
++#include <linux/clk.h>
++#include <linux/ds1wm.h>
++#include <asm/arch/clock.h>
++
++#include <asm/hardware.h>
++#include <asm/irq.h>
++#include <asm/io.h>
++
++#include <asm/hardware/ipaq-asic3.h>
++#include <linux/soc/asic3_base.h>
++#include <linux/soc/tmio_mmc.h>
++#include "soc-core.h"
++
++
++struct asic3_data {
++      void *mapping;
++      unsigned int bus_shift;
++      int irq_base;
++      int irq_nr;
++
++      u16 irq_bothedge[4];
++      struct device *dev;
++
++      struct platform_device *mmc_dev;
++};
++
++static DEFINE_SPINLOCK(asic3_gpio_lock);
++
++static int asic3_remove(struct platform_device *dev);
++
++static inline unsigned long asic3_address(struct device *dev,
++                                        unsigned int reg)
++{
++      struct asic3_data *adata;
++
++      adata = (struct asic3_data *)dev->driver_data;
++
++      return (unsigned long)adata->mapping + (reg >> (2 - adata->bus_shift));
++}
++
++void asic3_write_register(struct device *dev, unsigned int reg, u32 value)
++{
++      __raw_writew(value, asic3_address(dev, reg));
++}
++EXPORT_SYMBOL(asic3_write_register);
++
++u32 asic3_read_register(struct device *dev, unsigned int reg)
++{
++      return __raw_readw(asic3_address(dev, reg));
++}
++EXPORT_SYMBOL(asic3_read_register);
++
++static inline void __asic3_write_register(struct asic3_data *asic,
++                                        unsigned int reg, u32 value)
++{
++      __raw_writew(value, (unsigned long)asic->mapping
++                          + (reg >> (2 - asic->bus_shift)));
++}
++
++static inline u32 __asic3_read_register(struct asic3_data *asic,
++                                      unsigned int reg)
++{
++      return __raw_readw((unsigned long)asic->mapping
++                         + (reg >> (2 - asic->bus_shift)));
++}
++
++#define ASIC3_GPIO_FN(get_fn_name, set_fn_name, REG)                  \
++u32 get_fn_name(struct device *dev)                                   \
++{                                                                       \
++      return asic3_read_register(dev, REG);                           \
++}                                                                       \
++EXPORT_SYMBOL(get_fn_name);                                           \
++                                                                      \
++void set_fn_name(struct device *dev, u32 bits, u32 val)                       \
++{                                                                       \
++      unsigned long flags;                                            \
++                                                                      \
++      spin_lock_irqsave(&asic3_gpio_lock, flags);                     \
++      val |= (asic3_read_register(dev, REG) & ~bits);                 \
++      asic3_write_register(dev, REG, val);                            \
++      spin_unlock_irqrestore(&asic3_gpio_lock, flags);                \
++}                                                                       \
++EXPORT_SYMBOL(set_fn_name);
++
++#define ASIC3_GPIO_REGISTER(ACTION, action, fn, FN)                   \
++      ASIC3_GPIO_FN(asic3_get_gpio_ ## action ## _ ## fn ,            \
++                     asic3_set_gpio_ ## action ## _ ## fn ,           \
++                     _IPAQ_ASIC3_GPIO_ ## FN ## _Base                 \
++                     + _IPAQ_ASIC3_GPIO_ ## ACTION )
++
++#define ASIC3_GPIO_FUNCTIONS(fn, FN)                                  \
++      ASIC3_GPIO_REGISTER(Direction, dir, fn, FN)                     \
++      ASIC3_GPIO_REGISTER(Out, out, fn, FN)                           \
++      ASIC3_GPIO_REGISTER(SleepMask, sleepmask, fn, FN)               \
++      ASIC3_GPIO_REGISTER(SleepOut, sleepout, fn, FN)         \
++      ASIC3_GPIO_REGISTER(BattFaultOut, battfaultout, fn, FN) \
++      ASIC3_GPIO_REGISTER(AltFunction, alt_fn, fn, FN)                \
++      ASIC3_GPIO_REGISTER(SleepConf, sleepconf, fn, FN)               \
++      ASIC3_GPIO_REGISTER(Status, status, fn, FN)
++
++#if 0
++      ASIC3_GPIO_REGISTER(Mask, mask, fn, FN)
++      ASIC3_GPIO_REGISTER(TriggerType, trigtype, fn, FN)
++      ASIC3_GPIO_REGISTER(EdgeTrigger, rising, fn, FN)
++      ASIC3_GPIO_REGISTER(LevelTrigger, triglevel, fn, FN)
++      ASIC3_GPIO_REGISTER(IntStatus, intstatus, fn, FN)
++#endif
++
++ASIC3_GPIO_FUNCTIONS(a, A)
++ASIC3_GPIO_FUNCTIONS(b, B)
++ASIC3_GPIO_FUNCTIONS(c, C)
++ASIC3_GPIO_FUNCTIONS(d, D)
++
++int asic3_gpio_get_value(struct device *dev, unsigned gpio)
++{
++      u32 mask = ASIC3_GPIO_bit(gpio);
++      printk("%s(%d)\n", __FUNCTION__, gpio);
++      switch (gpio >> 4) {
++      case _IPAQ_ASIC3_GPIO_BANK_A:
++              return asic3_get_gpio_status_a(dev) & mask;
++      case _IPAQ_ASIC3_GPIO_BANK_B:
++              return asic3_get_gpio_status_b(dev) & mask;
++      case _IPAQ_ASIC3_GPIO_BANK_C:
++              return asic3_get_gpio_status_c(dev) & mask;
++      case _IPAQ_ASIC3_GPIO_BANK_D:
++              return asic3_get_gpio_status_d(dev) & mask;
++      }
++
++      printk(KERN_ERR "%s: invalid GPIO value 0x%x", __FUNCTION__, gpio);
++      return 0;
++}
++EXPORT_SYMBOL(asic3_gpio_get_value);
++
++void asic3_gpio_set_value(struct device *dev, unsigned gpio, int val)
++{
++      u32 mask = ASIC3_GPIO_bit(gpio);
++      u32 bitval = 0;
++      if (val)  bitval = mask;
++      printk("%s(%d, %d)\n", __FUNCTION__, gpio, val);
++
++      switch (gpio >> 4) {
++      case _IPAQ_ASIC3_GPIO_BANK_A:
++              asic3_set_gpio_out_a(dev, mask, bitval);
++              return;
++      case _IPAQ_ASIC3_GPIO_BANK_B:
++              asic3_set_gpio_out_b(dev, mask, bitval);
++              return;
++      case _IPAQ_ASIC3_GPIO_BANK_C:
++              asic3_set_gpio_out_c(dev, mask, bitval);
++              return;
++      case _IPAQ_ASIC3_GPIO_BANK_D:
++              asic3_set_gpio_out_d(dev, mask, bitval);
++              return;
++      }
++
++      printk(KERN_ERR "%s: invalid GPIO value 0x%x", __FUNCTION__, gpio);
++}
++EXPORT_SYMBOL(asic3_gpio_set_value);
++
++int asic3_irq_base(struct device *dev)
++{
++      struct asic3_data *asic = dev->driver_data;
++
++      return asic->irq_base;
++}
++EXPORT_SYMBOL(asic3_irq_base);
++
++static int asic3_gpio_to_irq(struct device *dev, unsigned gpio)
++{
++      struct asic3_data *asic = dev->driver_data;
++      printk("%s(%d)\n", __FUNCTION__, gpio);
++
++      return asic->irq_base + gpio;
++}
++
++void asic3_set_led(struct device *dev, int led_num, int duty_time,
++                 int cycle_time, int timebase)
++{
++      struct asic3_data *asic = dev->driver_data;
++      unsigned int led_base;
++
++      /* it's a macro thing: see #define _IPAQ_ASIC_LED_0_Base for why you
++       * can't substitute led_num in the macros below...
++       */
++
++      switch (led_num) {
++      case 0:
++              led_base = _IPAQ_ASIC3_LED_0_Base;
++              break;
++      case 1:
++              led_base = _IPAQ_ASIC3_LED_1_Base;
++              break;
++      case 2:
++              led_base = _IPAQ_ASIC3_LED_2_Base;
++              break;
++      default:
++              printk(KERN_ERR "%s: invalid led number %d", __FUNCTION__,
++                     led_num);
++              return;
++      }
++
++      __asic3_write_register(asic, led_base + _IPAQ_ASIC3_LED_TimeBase,
++                             timebase | LED_EN);
++      __asic3_write_register(asic, led_base + _IPAQ_ASIC3_LED_PeriodTime,
++                             cycle_time);
++      __asic3_write_register(asic, led_base + _IPAQ_ASIC3_LED_DutyTime,
++                             0);
++      udelay(20);     /* asic voodoo - possibly need a whole duty cycle? */
++      __asic3_write_register(asic, led_base + _IPAQ_ASIC3_LED_DutyTime,
++                             duty_time);
++}
++EXPORT_SYMBOL(asic3_set_led);
++
++void asic3_set_clock_sel(struct device *dev, u32 bits, u32 val)
++{
++      struct asic3_data *asic = dev->driver_data;
++      unsigned long flags;
++      u32 v;
++
++      spin_lock_irqsave(&asic3_gpio_lock, flags);
++      v = __asic3_read_register(asic, IPAQ_ASIC3_OFFSET(CLOCK, SEL));
++      v = (v & ~bits) | val;
++      __asic3_write_register(asic, IPAQ_ASIC3_OFFSET(CLOCK, SEL), v);
++      spin_unlock_irqrestore(&asic3_gpio_lock, flags);
++}
++EXPORT_SYMBOL(asic3_set_clock_sel);
++
++void asic3_set_clock_cdex(struct device *dev, u32 bits, u32 val)
++{
++      struct asic3_data *asic = dev->driver_data;
++      unsigned long flags;
++      u32 v;
++
++      spin_lock_irqsave(&asic3_gpio_lock, flags);
++      v = __asic3_read_register(asic, IPAQ_ASIC3_OFFSET(CLOCK, CDEX));
++      v = (v & ~bits) | val;
++      __asic3_write_register(asic, IPAQ_ASIC3_OFFSET(CLOCK, CDEX), v);
++      spin_unlock_irqrestore(&asic3_gpio_lock, flags);
++}
++EXPORT_SYMBOL(asic3_set_clock_cdex);
++
++static void asic3_clock_cdex_enable(struct clk *clk)
++{
++      struct asic3_data *asic = (struct asic3_data *)clk->parent->ctrlbit;
++      unsigned long flags, val;
++
++      local_irq_save(flags);
++
++      val = __asic3_read_register(asic, IPAQ_ASIC3_OFFSET(CLOCK, CDEX));
++      val |= clk->ctrlbit;
++      __asic3_write_register(asic, IPAQ_ASIC3_OFFSET(CLOCK, CDEX), val);
++
++      local_irq_restore(flags);
++}
++
++static void asic3_clock_cdex_disable(struct clk *clk)
++{
++      struct asic3_data *asic = (struct asic3_data *)clk->parent->ctrlbit;
++      unsigned long flags, val;
++
++      local_irq_save(flags);
++
++      val = __asic3_read_register(asic, IPAQ_ASIC3_OFFSET(CLOCK, CDEX));
++      val &= ~clk->ctrlbit;
++      __asic3_write_register(asic, IPAQ_ASIC3_OFFSET(CLOCK, CDEX), val);
++
++      local_irq_restore(flags);
++}
++
++/* base clocks */
++
++static struct clk clk_g = {
++      .name           = "gclk",
++      .rate           = 0,
++      .parent         = NULL,
++};
++
++/* clock definitions */
++
++static struct clk asic3_clocks[] = {
++      {
++              .name    = "spi",
++              .id      = -1,
++              .parent  = &clk_g,
++              .enable  = asic3_clock_cdex_enable,
++              .disable = asic3_clock_cdex_disable,
++              .ctrlbit = CLOCK_CDEX_SPI,
++      },
++#ifdef CONFIG_HTC_ASIC3_DS1WM
++      {
++              .name    = "ds1wm",
++              .id      = -1,
++              .rate    = 5000000,
++              .parent  = &clk_g,
++              .enable  = asic3_clock_cdex_enable,
++              .disable = asic3_clock_cdex_disable,
++              .ctrlbit = CLOCK_CDEX_OWM,
++      },
++#endif
++      {
++              .name    = "pwm0",
++              .id      = -1,
++              .parent  = &clk_g,
++              .enable  = asic3_clock_cdex_enable,
++              .disable = asic3_clock_cdex_disable,
++              .ctrlbit = CLOCK_CDEX_PWM0,
++      },
++      {
++              .name    = "pwm1",
++              .id      = -1,
++              .parent  = &clk_g,
++              .enable  = asic3_clock_cdex_enable,
++              .disable = asic3_clock_cdex_disable,
++              .ctrlbit = CLOCK_CDEX_PWM1,
++      },
++      {
++              .name    = "led0",
++              .id      = -1,
++              .parent  = &clk_g,
++              .enable  = asic3_clock_cdex_enable,
++              .disable = asic3_clock_cdex_disable,
++              .ctrlbit = CLOCK_CDEX_LED0,
++      },
++      {
++              .name    = "led1",
++              .id      = -1,
++              .parent  = &clk_g,
++              .enable  = asic3_clock_cdex_enable,
++              .disable = asic3_clock_cdex_disable,
++              .ctrlbit = CLOCK_CDEX_LED1,
++      },
++      {
++              .name    = "led2",
++              .id      = -1,
++              .parent  = &clk_g,
++              .enable  = asic3_clock_cdex_enable,
++              .disable = asic3_clock_cdex_disable,
++              .ctrlbit = CLOCK_CDEX_LED2,
++      },
++      {
++              .name    = "smbus",
++              .id      = -1,
++              .parent  = &clk_g,
++              .enable  = asic3_clock_cdex_enable,
++              .disable = asic3_clock_cdex_disable,
++              .ctrlbit = CLOCK_CDEX_SMBUS,
++      },
++      {
++              .name    = "ex0",
++              .id      = -1,
++              .parent  = &clk_g,
++              .enable  = asic3_clock_cdex_enable,
++              .disable = asic3_clock_cdex_disable,
++              .ctrlbit = CLOCK_CDEX_EX0,
++      },
++      {
++              .name    = "ex1",
++              .id      = -1,
++              .parent  = &clk_g,
++              .enable  = asic3_clock_cdex_enable,
++              .disable = asic3_clock_cdex_disable,
++              .ctrlbit = CLOCK_CDEX_EX1,
++      },
++};
++
++void asic3_set_extcf_select(struct device *dev, u32 bits, u32 val)
++{
++      struct asic3_data *asic = dev->driver_data;
++      unsigned long flags;
++      u32 v;
++
++      spin_lock_irqsave(&asic3_gpio_lock, flags);
++      v = __asic3_read_register(asic, IPAQ_ASIC3_OFFSET(EXTCF, Select));
++      v = (v & ~bits) | val;
++      __asic3_write_register(asic, IPAQ_ASIC3_OFFSET(EXTCF, Select), v);
++      spin_unlock_irqrestore(&asic3_gpio_lock, flags);
++}
++EXPORT_SYMBOL(asic3_set_extcf_select);
++
++void asic3_set_extcf_reset(struct device *dev, u32 bits, u32 val)
++{
++      struct asic3_data *asic = dev->driver_data;
++      unsigned long flags;
++      u32 v;
++
++      spin_lock_irqsave(&asic3_gpio_lock, flags);
++      v = __asic3_read_register(asic, IPAQ_ASIC3_OFFSET(EXTCF, Reset));
++      v = (v & ~bits) | val;
++      __asic3_write_register(asic, IPAQ_ASIC3_OFFSET(EXTCF, Reset), v);
++      spin_unlock_irqrestore(&asic3_gpio_lock, flags);
++}
++EXPORT_SYMBOL(asic3_set_extcf_reset);
++
++void asic3_set_sdhwctrl(struct device *dev, u32 bits, u32 val)
++{
++      struct asic3_data *asic = dev->driver_data;
++      unsigned long flags;
++      u32 v;
++
++      spin_lock_irqsave (&asic3_gpio_lock, flags);
++      v = __asic3_read_register(asic, IPAQ_ASIC3_OFFSET(SDHWCTRL, SDConf));
++      v = (v & ~bits) | val;
++      __asic3_write_register(asic, IPAQ_ASIC3_OFFSET(SDHWCTRL, SDConf), v);
++      spin_unlock_irqrestore(&asic3_gpio_lock, flags);
++}
++EXPORT_SYMBOL(asic3_set_sdhwctrl);
++
++
++#define MAX_ASIC_ISR_LOOPS    20
++#define _IPAQ_ASIC3_GPIO_Base_INCR \
++      (_IPAQ_ASIC3_GPIO_B_Base - _IPAQ_ASIC3_GPIO_A_Base)
++
++static inline void asic3_irq_flip_edge(struct asic3_data *asic,
++                                     u32 base, int bit)
++{
++      u16 edge = __asic3_read_register(asic,
++              base + _IPAQ_ASIC3_GPIO_EdgeTrigger);
++      edge ^= bit;
++      __asic3_write_register(asic,
++              base + _IPAQ_ASIC3_GPIO_EdgeTrigger, edge);
++}
++
++static void asic3_irq_demux(unsigned int irq, struct irq_desc *desc)
++{
++      int iter;
++      struct asic3_data *asic;
++
++      /* Acknowledge the parrent (i.e. CPU's) IRQ */
++      desc->chip->ack(irq);
++
++      asic = desc->handler_data;
++
++      /* printk( KERN_NOTICE "asic3_irq_demux: irq=%d\n", irq ); */
++      for (iter = 0 ; iter < MAX_ASIC_ISR_LOOPS; iter++) {
++              u32 status;
++              int bank;
++
++              status = __asic3_read_register(asic,
++                      IPAQ_ASIC3_OFFSET(INTR, PIntStat));
++              /* Check all ten register bits */
++              if ((status & 0x3ff) == 0)
++                      break;
++
++              /* Handle GPIO IRQs */
++              for (bank = 0; bank < 4; bank++) {
++                      if (status & (1 << bank)) {
++                              unsigned long base, i, istat;
++
++                              base = _IPAQ_ASIC3_GPIO_A_Base
++                                     + bank * _IPAQ_ASIC3_GPIO_Base_INCR;
++                              istat = __asic3_read_register(asic,
++                                      base + _IPAQ_ASIC3_GPIO_IntStatus);
++                              /* IntStatus is write 0 to clear */
++                              /* XXX could miss interrupts! */
++                              __asic3_write_register(asic,
++                                      base + _IPAQ_ASIC3_GPIO_IntStatus, 0);
++
++                              for (i = 0; i < 16; i++) {
++                                      int bit = (1 << i);
++                                      unsigned int irqnr;
++                                      if (!(istat & bit))
++                                              continue;
++
++                                      irqnr = asic->irq_base
++                                              + (16 * bank) + i;
++                                      desc = irq_desc + irqnr;
++                                      desc->handle_irq(irqnr, desc);
++                                      if (asic->irq_bothedge[bank] & bit) {
++                                              asic3_irq_flip_edge(asic, base,
++                                                                  bit);
++                                      }
++                              }
++                      }
++              }
++
++              /* Handle remaining IRQs in the status register */
++              {
++                      int i;
++
++                      for (i = ASIC3_LED0_IRQ; i <= ASIC3_OWM_IRQ; i++) {
++                              /* They start at bit 4 and go up */
++                              if (status & (1 << (i - ASIC3_LED0_IRQ + 4))) {
++                                      desc = irq_desc + asic->irq_base + i;
++                                      desc->handle_irq(asic->irq_base + i,
++                                                       desc);
++                              }
++                      }
++              }
++
++      }
++
++      if (iter >= MAX_ASIC_ISR_LOOPS)
++              printk(KERN_ERR "%s: interrupt processing overrun\n",
++                     __FUNCTION__);
++}
++
++static inline int asic3_irq_to_bank(struct asic3_data *asic, int irq)
++{
++      int n;
++
++      n = (irq - asic->irq_base) >> 4;
++
++      return (n * (_IPAQ_ASIC3_GPIO_B_Base - _IPAQ_ASIC3_GPIO_A_Base));
++}
++
++static inline int asic3_irq_to_index(struct asic3_data *asic, int irq)
++{
++      return (irq - asic->irq_base) & 15;
++}
++
++static void asic3_mask_gpio_irq(unsigned int irq)
++{
++      struct asic3_data *asic = get_irq_chip_data(irq);
++      u32 val, bank, index;
++      unsigned long flags;
++
++      bank = asic3_irq_to_bank(asic, irq);
++      index = asic3_irq_to_index(asic, irq);
++
++      spin_lock_irqsave(&asic3_gpio_lock, flags);
++      val = __asic3_read_register(asic, bank + _IPAQ_ASIC3_GPIO_Mask);
++      val |= 1 << index;
++      __asic3_write_register(asic, bank + _IPAQ_ASIC3_GPIO_Mask, val);
++      spin_unlock_irqrestore(&asic3_gpio_lock, flags);
++}
++
++static void asic3_mask_irq(unsigned int irq)
++{
++      struct asic3_data *asic = get_irq_chip_data(irq);
++      int regval;
++
++      if (irq < ASIC3_NR_GPIO_IRQS) {
++              printk(KERN_ERR "asic3_base: gpio mask attempt, irq %d\n",
++                     irq);
++              return;
++      }
++
++      regval = __asic3_read_register(asic,
++              _IPAQ_ASIC3_INTR_Base + _IPAQ_ASIC3_INTR_IntMask);
++
++      switch (irq - asic->irq_base) {
++      case ASIC3_LED0_IRQ:
++              __asic3_write_register(asic,
++                      _IPAQ_ASIC3_INTR_Base + _IPAQ_ASIC3_INTR_IntMask,
++                      regval & ~ASIC3_INTMASK_MASK0);
++              break;
++      case ASIC3_LED1_IRQ:
++              __asic3_write_register(asic,
++                      _IPAQ_ASIC3_INTR_Base + _IPAQ_ASIC3_INTR_IntMask,
++                      regval & ~ASIC3_INTMASK_MASK1);
++              break;
++      case ASIC3_LED2_IRQ:
++              __asic3_write_register(asic,
++                      _IPAQ_ASIC3_INTR_Base + _IPAQ_ASIC3_INTR_IntMask,
++                      regval & ~ASIC3_INTMASK_MASK2);
++              break;
++      case ASIC3_SPI_IRQ:
++              __asic3_write_register(asic,
++                      _IPAQ_ASIC3_INTR_Base + _IPAQ_ASIC3_INTR_IntMask,
++                      regval & ~ASIC3_INTMASK_MASK3);
++              break;
++      case ASIC3_SMBUS_IRQ:
++              __asic3_write_register(asic,
++                      _IPAQ_ASIC3_INTR_Base + _IPAQ_ASIC3_INTR_IntMask,
++                      regval & ~ASIC3_INTMASK_MASK4);
++              break;
++      case ASIC3_OWM_IRQ:
++              __asic3_write_register(asic,
++                      _IPAQ_ASIC3_INTR_Base + _IPAQ_ASIC3_INTR_IntMask,
++                      regval & ~ASIC3_INTMASK_MASK5);
++              break;
++      default:
++              printk(KERN_ERR "asic3_base: bad non-gpio irq %d\n", irq);
++              break;
++      }
++}
++
++static void asic3_unmask_gpio_irq(unsigned int irq)
++{
++      struct asic3_data *asic = get_irq_chip_data(irq);
++      u32 val, bank, index;
++      unsigned long flags;
++
++      bank = asic3_irq_to_bank(asic, irq);
++      index = asic3_irq_to_index(asic, irq);
++
++      spin_lock_irqsave(&asic3_gpio_lock, flags);
++      val = __asic3_read_register(asic, bank + _IPAQ_ASIC3_GPIO_Mask);
++      val &= ~(1 << index);
++      __asic3_write_register(asic, bank + _IPAQ_ASIC3_GPIO_Mask, val);
++      spin_unlock_irqrestore(&asic3_gpio_lock, flags);
++}
++
++static void asic3_unmask_irq(unsigned int irq)
++{
++      struct asic3_data *asic = get_irq_chip_data(irq);
++      int regval;
++
++      if (irq < ASIC3_NR_GPIO_IRQS) {
++              printk(KERN_ERR "asic3_base: gpio unmask attempt, irq %d\n",
++                     irq);
++              return;
++      }
++
++      regval = __asic3_read_register(asic,
++              _IPAQ_ASIC3_INTR_Base + _IPAQ_ASIC3_INTR_IntMask);
++
++      switch (irq - asic->irq_base) {
++      case ASIC3_LED0_IRQ:
++              __asic3_write_register(asic,
++                      _IPAQ_ASIC3_INTR_Base + _IPAQ_ASIC3_INTR_IntMask,
++                      regval | ASIC3_INTMASK_MASK0);
++              break;
++      case ASIC3_LED1_IRQ:
++              __asic3_write_register(asic,
++                      _IPAQ_ASIC3_INTR_Base + _IPAQ_ASIC3_INTR_IntMask,
++                      regval | ASIC3_INTMASK_MASK1);
++              break;
++      case ASIC3_LED2_IRQ:
++              __asic3_write_register(asic,
++                      _IPAQ_ASIC3_INTR_Base + _IPAQ_ASIC3_INTR_IntMask,
++                      regval | ASIC3_INTMASK_MASK2);
++              break;
++      case ASIC3_SPI_IRQ:
++              __asic3_write_register(asic,
++                      _IPAQ_ASIC3_INTR_Base + _IPAQ_ASIC3_INTR_IntMask,
++                      regval | ASIC3_INTMASK_MASK3);
++              break;
++      case ASIC3_SMBUS_IRQ:
++              __asic3_write_register(asic,
++                      _IPAQ_ASIC3_INTR_Base + _IPAQ_ASIC3_INTR_IntMask,
++                      regval | ASIC3_INTMASK_MASK4);
++              break;
++      case ASIC3_OWM_IRQ:
++              __asic3_write_register(asic,
++                      _IPAQ_ASIC3_INTR_Base + _IPAQ_ASIC3_INTR_IntMask,
++                      regval | ASIC3_INTMASK_MASK5);
++              break;
++      default:
++              printk(KERN_ERR "asic3_base: bad non-gpio irq %d\n", irq);
++              break;
++      }
++}
++
++static int asic3_gpio_irq_type(unsigned int irq, unsigned int type)
++{
++      struct asic3_data *asic = get_irq_chip_data(irq);
++      u32 bank, index;
++      unsigned long flags;
++      u16 trigger, level, edge, bit;
++
++      bank = asic3_irq_to_bank(asic, irq);
++      index = asic3_irq_to_index(asic, irq);
++      bit = 1<<index;
++
++      spin_lock_irqsave(&asic3_gpio_lock, flags);
++      level = __asic3_read_register(asic,
++              bank + _IPAQ_ASIC3_GPIO_LevelTrigger);
++      edge = __asic3_read_register(asic,
++              bank + _IPAQ_ASIC3_GPIO_EdgeTrigger);
++      trigger = __asic3_read_register(asic,
++              bank + _IPAQ_ASIC3_GPIO_TriggerType);
++      asic->irq_bothedge[(irq - asic->irq_base) >> 4] &= ~bit;
++
++      if (type == IRQT_RISING) {
++              trigger |= bit;
++              edge |= bit;
++      } else if (type == IRQT_FALLING) {
++              trigger |= bit;
++              edge &= ~bit;
++      } else if (type == IRQT_BOTHEDGE) {
++              trigger |= bit;
++              if (asic3_gpio_get_value(asic->dev, irq - asic->irq_base))
++                      edge &= ~bit;
++              else
++                      edge |= bit;
++              asic->irq_bothedge[(irq - asic->irq_base) >> 4] |= bit;
++      } else if (type == IRQT_LOW) {
++              trigger &= ~bit;
++              level &= ~bit;
++      } else if (type == IRQT_HIGH) {
++              trigger &= ~bit;
++              level |= bit;
++      } else {
++              /*
++               * if type == IRQT_NOEDGE, we should mask interrupts, but
++               * be careful to not unmask them if mask was also called.
++               * Probably need internal state for mask.
++               */
++              printk(KERN_NOTICE "asic3: irq type not changed.\n");
++      }
++      __asic3_write_register(asic, bank + _IPAQ_ASIC3_GPIO_LevelTrigger,
++                             level);
++      __asic3_write_register(asic, bank + _IPAQ_ASIC3_GPIO_EdgeTrigger,
++                             edge);
++      __asic3_write_register(asic, bank + _IPAQ_ASIC3_GPIO_TriggerType,
++                             trigger);
++      spin_unlock_irqrestore(&asic3_gpio_lock, flags);
++      return 0;
++}
++
++static struct irq_chip asic3_gpio_irq_chip = {
++      .name           = "ASIC3-GPIO",
++      .ack            = asic3_mask_gpio_irq,
++      .mask           = asic3_mask_gpio_irq,
++      .unmask         = asic3_unmask_gpio_irq,
++      .set_type       = asic3_gpio_irq_type,
++};
++
++static struct irq_chip asic3_irq_chip = {
++      .name           = "ASIC3",
++      .ack            = asic3_mask_irq,
++      .mask           = asic3_mask_irq,
++      .unmask         = asic3_unmask_irq,
++};
++
++static void asic3_release(struct device *dev)
++{
++      struct platform_device *sdev = to_platform_device(dev);
++
++      kfree(sdev->resource);
++      kfree(sdev);
++}
++
++int asic3_register_mmc(struct device *dev)
++{
++      struct platform_device *sdev = kzalloc(sizeof(*sdev), GFP_KERNEL);
++      struct tmio_mmc_hwconfig *mmc_config = kmalloc(sizeof(*mmc_config),
++                                                     GFP_KERNEL);
++      struct platform_device *pdev = to_platform_device(dev);
++      struct asic3_data *asic = dev->driver_data;
++      struct asic3_platform_data *asic3_pdata = dev->platform_data;
++      struct resource *res;
++      int rc;
++
++      if (sdev == NULL || mmc_config == NULL)
++              return -ENOMEM;
++
++      if (asic3_pdata->tmio_mmc_hwconfig) {
++              memcpy(mmc_config, asic3_pdata->tmio_mmc_hwconfig,
++                     sizeof(*mmc_config));
++      } else {
++              memset(mmc_config, 0, sizeof(*mmc_config));
++      }
++      mmc_config->address_shift = asic->bus_shift;
++
++      sdev->id = -1;
++      sdev->name = "asic3_mmc";
++      sdev->dev.parent = dev;
++      sdev->num_resources = 2;
++      sdev->dev.platform_data = mmc_config;
++      sdev->dev.release = asic3_release;
++
++      res = kzalloc(sdev->num_resources * sizeof(struct resource),
++                    GFP_KERNEL);
++      if (res == NULL) {
++              kfree(sdev);
++              kfree(mmc_config);
++              return -ENOMEM;
++      }
++      sdev->resource = res;
++
++      res[0].start = pdev->resource[2].start;
++      res[0].end   = pdev->resource[2].end;
++      res[0].flags = IORESOURCE_MEM;
++      res[1].start = res[1].end = pdev->resource[3].start;
++      res[1].flags = IORESOURCE_IRQ;
++
++      rc = platform_device_register(sdev);
++      if (rc) {
++              printk(KERN_ERR "asic3_base: "
++                     "Could not register asic3_mmc device\n");
++              kfree(res);
++              kfree(sdev);
++              return rc;
++      }
++
++      asic->mmc_dev = sdev;
++
++      return 0;
++}
++EXPORT_SYMBOL(asic3_register_mmc);
++
++int asic3_unregister_mmc(struct device *dev)
++{
++      struct asic3_data *asic = dev->driver_data;
++      platform_device_unregister(asic->mmc_dev);
++      asic->mmc_dev = 0;
++
++      return 0;
++}
++EXPORT_SYMBOL(asic3_unregister_mmc);
++
++#ifdef CONFIG_HTC_ASIC3_DS1WM
++/*
++ *    DS1WM subdevice
++ */
++
++static void asic3_ds1wm_enable(struct platform_device *ds1wm_dev)
++{
++      struct device *dev = ds1wm_dev->dev.parent;
++
++      /* Turn on external clocks and the OWM clock */
++      asic3_set_clock_cdex(dev,
++              CLOCK_CDEX_EX0 | CLOCK_CDEX_EX1 | CLOCK_CDEX_OWM,
++              CLOCK_CDEX_EX0 | CLOCK_CDEX_EX1 | CLOCK_CDEX_OWM);
++
++      mdelay(1);
++
++      asic3_set_extcf_reset(dev, ASIC3_EXTCF_OWM_RESET,
++                            ASIC3_EXTCF_OWM_RESET);
++      mdelay(1);
++      asic3_set_extcf_reset(dev, ASIC3_EXTCF_OWM_RESET, 0);
++      mdelay(1);
++
++      /* Clear OWM_SMB, set OWM_EN */
++      asic3_set_extcf_select(dev,
++              ASIC3_EXTCF_OWM_SMB | ASIC3_EXTCF_OWM_EN,
++              0                   | ASIC3_EXTCF_OWM_EN);
++
++      mdelay(1);
++}
++
++static void asic3_ds1wm_disable(struct platform_device *ds1wm_dev)
++{
++      struct device *dev = ds1wm_dev->dev.parent;
++
++      asic3_set_extcf_select(dev,
++              ASIC3_EXTCF_OWM_SMB | ASIC3_EXTCF_OWM_EN,
++              0                   | 0);
++
++      asic3_set_clock_cdex(dev,
++              CLOCK_CDEX_EX0 | CLOCK_CDEX_EX1 | CLOCK_CDEX_OWM,
++              CLOCK_CDEX_EX0 | CLOCK_CDEX_EX1 | 0);
++}
++
++
++static struct resource asic3_ds1wm_resources[] = {
++      {
++              .start = _IPAQ_ASIC3_OWM_Base,
++              .end   = _IPAQ_ASIC3_OWM_Base + 0x14 - 1,
++              .flags = IORESOURCE_MEM,
++      },
++      {
++              .start = ASIC3_OWM_IRQ,
++              .end   = ASIC3_OWM_IRQ,
++              .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE |
++                       IORESOURCE_IRQ_SOC_SUBDEVICE,
++      },
++};
++
++static struct ds1wm_platform_data ds1wm_pd = {
++      .enable = asic3_ds1wm_enable,
++      .disable = asic3_ds1wm_disable,
++};
++#endif
++
++static struct soc_device_data asic3_blocks[] = {
++#ifdef CONFIG_HTC_ASIC3_DS1WM
++      {
++              .name = "ds1wm",
++              .res = asic3_ds1wm_resources,
++              .num_resources = ARRAY_SIZE(asic3_ds1wm_resources),
++              .hwconfig = &ds1wm_pd,
++      },
++#endif
++};
++
++static int asic3_probe(struct platform_device *pdev)
++{
++      struct asic3_platform_data *pdata = pdev->dev.platform_data;
++      struct asic3_data *asic;
++      struct device *dev = &pdev->dev;
++      unsigned long clksel;
++      int i, rc;
++
++      asic = kzalloc(sizeof(struct asic3_data), GFP_KERNEL);
++      if (!asic)
++              return -ENOMEM;
++
++      platform_set_drvdata(pdev, asic);
++      asic->dev = &pdev->dev;
++
++      asic->mapping = ioremap(pdev->resource[0].start, IPAQ_ASIC3_MAP_SIZE);
++      if (!asic->mapping) {
++              printk(KERN_ERR "asic3: couldn't ioremap ASIC3\n");
++              kfree (asic);
++              return -ENOMEM;
++      }
++
++      if (pdata && pdata->bus_shift)
++              asic->bus_shift = pdata->bus_shift;
++      else
++              asic->bus_shift = 2;
++
++      /* XXX: should get correct SD clock values from pdata struct  */
++      clksel = 0;
++      __asic3_write_register(asic, IPAQ_ASIC3_OFFSET(CLOCK, SEL), clksel);
++
++      /* Register ASIC3's clocks. */
++      clk_g.ctrlbit = (int)asic;
++
++      if (clk_register(&clk_g) < 0)
++              printk(KERN_ERR "asic3: failed to register ASIC3 gclk\n");
++
++      for (i = 0; i < ARRAY_SIZE(asic3_clocks); i++) {
++              rc = clk_register(&asic3_clocks[i]);
++              if (rc < 0)
++                      printk(KERN_ERR "asic3: "
++                             "failed to register clock %s (%d)\n",
++                             asic3_clocks[i].name, rc);
++      }
++
++      __asic3_write_register(asic, IPAQ_ASIC3_GPIO_OFFSET(A, Mask), 0xffff);
++      __asic3_write_register(asic, IPAQ_ASIC3_GPIO_OFFSET(B, Mask), 0xffff);
++      __asic3_write_register(asic, IPAQ_ASIC3_GPIO_OFFSET(C, Mask), 0xffff);
++      __asic3_write_register(asic, IPAQ_ASIC3_GPIO_OFFSET(D, Mask), 0xffff);
++
++      asic3_set_gpio_sleepmask_a(dev, 0xffff, 0xffff);
++      asic3_set_gpio_sleepmask_b(dev, 0xffff, 0xffff);
++      asic3_set_gpio_sleepmask_c(dev, 0xffff, 0xffff);
++      asic3_set_gpio_sleepmask_d(dev, 0xffff, 0xffff);
++
++      if (pdata) {
++              asic3_set_gpio_out_a(dev, 0xffff, pdata->gpio_a.init);
++              asic3_set_gpio_out_b(dev, 0xffff, pdata->gpio_b.init);
++              asic3_set_gpio_out_c(dev, 0xffff, pdata->gpio_c.init);
++              asic3_set_gpio_out_d(dev, 0xffff, pdata->gpio_d.init);
++
++              asic3_set_gpio_dir_a(dev, 0xffff, pdata->gpio_a.dir);
++              asic3_set_gpio_dir_b(dev, 0xffff, pdata->gpio_b.dir);
++              asic3_set_gpio_dir_c(dev, 0xffff, pdata->gpio_c.dir);
++              asic3_set_gpio_dir_d(dev, 0xffff, pdata->gpio_d.dir);
++
++              asic3_set_gpio_sleepmask_a(dev, 0xffff,
++                                         pdata->gpio_a.sleep_mask);
++              asic3_set_gpio_sleepmask_b(dev, 0xffff,
++                                         pdata->gpio_b.sleep_mask);
++              asic3_set_gpio_sleepmask_c(dev, 0xffff,
++                                         pdata->gpio_c.sleep_mask);
++              asic3_set_gpio_sleepmask_d(dev, 0xffff,
++                                         pdata->gpio_d.sleep_mask);
++
++              asic3_set_gpio_sleepout_a(dev, 0xffff,
++                                        pdata->gpio_a.sleep_out);
++              asic3_set_gpio_sleepout_b(dev, 0xffff,
++                                        pdata->gpio_b.sleep_out);
++              asic3_set_gpio_sleepout_c(dev, 0xffff,
++                                        pdata->gpio_c.sleep_out);
++              asic3_set_gpio_sleepout_d(dev, 0xffff,
++                                        pdata->gpio_d.sleep_out);
++
++              asic3_set_gpio_battfaultout_a(dev, 0xffff,
++                                            pdata->gpio_a.batt_fault_out);
++              asic3_set_gpio_battfaultout_b(dev, 0xffff,
++                                            pdata->gpio_b.batt_fault_out);
++              asic3_set_gpio_battfaultout_c(dev, 0xffff,
++                                            pdata->gpio_c.batt_fault_out);
++              asic3_set_gpio_battfaultout_d(dev, 0xffff,
++                                            pdata->gpio_d.batt_fault_out);
++
++              asic3_set_gpio_sleepconf_a(dev, 0xffff,
++                                         pdata->gpio_a.sleep_conf);
++              asic3_set_gpio_sleepconf_b(dev, 0xffff,
++                                         pdata->gpio_b.sleep_conf);
++              asic3_set_gpio_sleepconf_c(dev, 0xffff,
++                                         pdata->gpio_c.sleep_conf);
++              asic3_set_gpio_sleepconf_d(dev, 0xffff,
++                                         pdata->gpio_d.sleep_conf);
++
++              asic3_set_gpio_alt_fn_a(dev, 0xffff,
++                                      pdata->gpio_a.alt_function);
++              asic3_set_gpio_alt_fn_b(dev, 0xffff,
++                                      pdata->gpio_b.alt_function);
++              asic3_set_gpio_alt_fn_c(dev, 0xffff,
++                                      pdata->gpio_c.alt_function);
++              asic3_set_gpio_alt_fn_d(dev, 0xffff,
++                                      pdata->gpio_d.alt_function);
++      }
++
++      asic->irq_nr = -1;
++      asic->irq_base = -1;
++
++      if (pdev->num_resources > 1)
++              asic->irq_nr = pdev->resource[1].start;
++
++      if (asic->irq_nr != -1) {
++              unsigned int i;
++
++              if (!pdata->irq_base) {
++                      printk(KERN_ERR "asic3: IRQ base not specified\n");
++                      asic3_remove(pdev);
++                      return -EINVAL;
++              }
++
++              asic->irq_base = pdata->irq_base;
++
++              /* turn on clock to IRQ controller */
++              clksel |= CLOCK_SEL_CX;
++              __asic3_write_register(asic, IPAQ_ASIC3_OFFSET(CLOCK, SEL),
++                                     clksel);
++
++              printk(KERN_INFO "asic3: using irq %d-%d on irq %d\n",
++                     asic->irq_base, asic->irq_base + ASIC3_NR_IRQS - 1,
++                     asic->irq_nr);
++
++              for (i = 0 ; i < ASIC3_NR_IRQS ; i++) {
++                      int irq = i + asic->irq_base;
++                      if (i < ASIC3_NR_GPIO_IRQS) {
++                              set_irq_chip(irq, &asic3_gpio_irq_chip);
++                              set_irq_chip_data(irq, asic);
++                              set_irq_handler(irq, handle_level_irq);
++                              set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
++                      } else {
++                              /* The remaining IRQs are not GPIO */
++                              set_irq_chip(irq, &asic3_irq_chip);
++                              set_irq_chip_data(irq, asic);
++                              set_irq_handler(irq, handle_level_irq);
++                              set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
++                      }
++              }
++
++              __asic3_write_register(asic, IPAQ_ASIC3_OFFSET(INTR, IntMask),
++                                      ASIC3_INTMASK_GINTMASK);
++
++              set_irq_chained_handler(asic->irq_nr, asic3_irq_demux);
++              set_irq_type(asic->irq_nr, IRQT_RISING);
++              set_irq_data(asic->irq_nr, asic);
++      }
++
++#ifdef CONFIG_HTC_ASIC3_DS1WM
++      ds1wm_pd.bus_shift = asic->bus_shift;
++#endif
++
++      pdata->gpiodev_ops.get = asic3_gpio_get_value;
++      pdata->gpiodev_ops.set = asic3_gpio_set_value;
++      pdata->gpiodev_ops.to_irq = asic3_gpio_to_irq;
++
++      soc_add_devices(pdev, asic3_blocks, ARRAY_SIZE(asic3_blocks),
++                      &pdev->resource[0],
++                      asic->bus_shift - ASIC3_DEFAULT_ADDR_SHIFT,
++                      asic->irq_base);
++
++      if (pdev->num_resources > 2) {
++              int rc;
++              rc = asic3_register_mmc(dev);
++              if (rc) {
++                      asic3_remove(pdev);
++                      return rc;
++              }
++      }
++
++      if (pdata && pdata->num_child_platform_devs != 0)
++              platform_add_devices(pdata->child_platform_devs,
++                                   pdata->num_child_platform_devs);
++
++      return 0;
++}
++
++static int asic3_remove(struct platform_device *pdev)
++{
++      struct asic3_platform_data *pdata = pdev->dev.platform_data;
++      struct asic3_data *asic = platform_get_drvdata(pdev);
++      int i;
++
++      if (pdata && pdata->num_child_platform_devs != 0) {
++              for (i = 0; i < pdata->num_child_platform_devs; i++) {
++                      platform_device_unregister(
++                              pdata->child_platform_devs[i]);
++              }
++      }
++
++      if (asic->irq_nr != -1) {
++              unsigned int i;
++
++              for (i = 0 ; i < ASIC3_NR_IRQS ; i++) {
++                      int irq = i + asic->irq_base;
++                      set_irq_flags(irq, 0);
++                      set_irq_handler (irq, NULL);
++                      set_irq_chip (irq, NULL);
++                      set_irq_chip_data(irq, NULL);
++              }
++
++              set_irq_chained_handler(asic->irq_nr, NULL);
++      }
++
++      if (asic->mmc_dev)
++              asic3_unregister_mmc(&pdev->dev);
++
++      for (i = 0; i < ARRAY_SIZE(asic3_clocks); i++)
++              clk_unregister(&asic3_clocks[i]);
++      clk_unregister(&clk_g);
++
++      __asic3_write_register(asic, IPAQ_ASIC3_OFFSET(CLOCK, SEL), 0);
++      __asic3_write_register(asic, IPAQ_ASIC3_OFFSET(INTR, IntMask), 0);
++
++      iounmap(asic->mapping);
++
++      kfree(asic);
++
++      return 0;
++}
++
++static void asic3_shutdown(struct platform_device *pdev)
++{
++}
++
++#define ASIC3_SUSPEND_CDEX_MASK \
++      (CLOCK_CDEX_LED0 | CLOCK_CDEX_LED1 | CLOCK_CDEX_LED2)
++static unsigned short suspend_cdex;
++
++static int asic3_suspend(struct platform_device *pdev, pm_message_t state)
++{
++      struct asic3_data *asic = platform_get_drvdata(pdev);
++      suspend_cdex = __asic3_read_register(asic,
++              _IPAQ_ASIC3_CLOCK_Base + _IPAQ_ASIC3_CLOCK_CDEX);
++      /* The LEDs are still active during suspend */
++      __asic3_write_register(asic,
++              _IPAQ_ASIC3_CLOCK_Base + _IPAQ_ASIC3_CLOCK_CDEX,
++              suspend_cdex & ASIC3_SUSPEND_CDEX_MASK);
++      return 0;
++}
++
++static int asic3_resume(struct platform_device *pdev)
++{
++      struct asic3_data *asic = platform_get_drvdata(pdev);
++      unsigned short intmask;
++
++      __asic3_write_register(asic, IPAQ_ASIC3_OFFSET(CLOCK, CDEX),
++                             suspend_cdex);
++
++      if (asic->irq_nr != -1) {
++              /* Toggle the interrupt mask to try to get ASIC3 to show
++               * the CPU an interrupt edge. For more details see the
++               * kernel-discuss thread around 13 June 2005 with the
++               * subject "asic3 suspend / resume". */
++              intmask = __asic3_read_register(asic,
++                              IPAQ_ASIC3_OFFSET(INTR, IntMask));
++              __asic3_write_register(asic, IPAQ_ASIC3_OFFSET(INTR, IntMask),
++                                     intmask & ~ASIC3_INTMASK_GINTMASK);
++              mdelay(1);
++              __asic3_write_register(asic, IPAQ_ASIC3_OFFSET(INTR, IntMask),
++                                     intmask | ASIC3_INTMASK_GINTMASK);
++      }
++
++      return 0;
++}
++
++static struct platform_driver asic3_device_driver = {
++      .driver         = {
++              .name   = "asic3",
++      },
++      .probe          = asic3_probe,
++      .remove         = asic3_remove,
++      .suspend        = asic3_suspend,
++      .resume         = asic3_resume,
++      .shutdown       = asic3_shutdown,
++};
++
++static int __init asic3_base_init(void)
++{
++      int retval = 0;
++      retval = platform_driver_register(&asic3_device_driver);
++      return retval;
++}
++
++static void __exit asic3_base_exit(void)
++{
++      platform_driver_unregister(&asic3_device_driver);
++}
++
++#ifdef MODULE
++module_init(asic3_base_init);
++#else /* start early for dependencies */
++subsys_initcall(asic3_base_init);
++#endif
++module_exit(asic3_base_exit);
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Phil Blundell <pb@handhelds.org>");
++MODULE_DESCRIPTION("Core driver for HTC ASIC3");
++MODULE_SUPPORTED_DEVICE("asic3");
+Index: linux-2.6.22/drivers/mfd/soc-core.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/drivers/mfd/soc-core.c        2007-09-11 12:53:37.000000000 +0200
+@@ -0,0 +1,106 @@
++/*
++ * drivers/soc/soc-core.c
++ *
++ * core SoC support
++ * Copyright (c) 2006 Ian Molton
++ *
++ * This program is free software; you can 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 file contains functionality used by many SoC type devices.
++ *
++ * Created: 2006-11-28
++ *
++ */
++
++#include <linux/ioport.h>
++#include <linux/slab.h>
++#include <linux/kernel.h>
++#include <linux/platform_device.h>
++#include "soc-core.h"
++
++void soc_free_devices(struct platform_device *devices, int nr_devs)
++{
++      struct platform_device *dev = devices;
++      int i;
++
++      for (i = 0; i < nr_devs; i++) {
++              struct resource *res = dev->resource;
++              platform_device_unregister(dev++);
++              kfree(res);
++      }
++      kfree(devices);
++}
++EXPORT_SYMBOL_GPL(soc_free_devices);
++
++#define SIGNED_SHIFT(val, shift) ((shift) >= 0 ? ((val) << (shift)) : ((val) >> -(shift)))
++
++struct platform_device *soc_add_devices(struct platform_device *dev,
++                                      struct soc_device_data *soc, int nr_devs,
++                                      struct resource *mem,
++                                      int relative_addr_shift, int irq_base)
++{
++      struct platform_device *devices;
++      int i, r, base;
++
++      devices = kzalloc(nr_devs * sizeof(struct platform_device), GFP_KERNEL);
++      if (!devices)
++              return NULL;
++
++      for (i = 0; i < nr_devs; i++) {
++              struct platform_device *sdev = &devices[i];
++              struct soc_device_data *blk = &soc[i];
++              struct resource *res;
++
++              sdev->id = -1;
++              sdev->name = blk->name;
++
++              sdev->dev.parent = &dev->dev;
++              sdev->dev.platform_data = (void *)blk->hwconfig;
++              sdev->num_resources = blk->num_resources;
++
++              /* Allocate space for the subdevice resources */
++              res = kzalloc (blk->num_resources * sizeof (struct resource), GFP_KERNEL);
++              if (!res)
++                      goto fail;
++
++              for (r = 0 ; r < blk->num_resources ; r++) {
++                      res[r].name = blk->res[r].name; // Fixme - should copy
++
++                      /* Find out base to use */
++                      base = 0;
++                      if (blk->res[r].flags & IORESOURCE_MEM) {
++                              base = mem->start;
++                      } else if ((blk->res[r].flags & IORESOURCE_IRQ) &&
++                              (blk->res[r].flags & IORESOURCE_IRQ_SOC_SUBDEVICE)) {
++                              base = irq_base;
++                      }
++
++                      /* Adjust resource */
++                      if (blk->res[r].flags & IORESOURCE_MEM) {
++                              res[r].parent = mem;
++                              res[r].start = base + SIGNED_SHIFT(blk->res[r].start, relative_addr_shift);
++                              res[r].end   = base + SIGNED_SHIFT(blk->res[r].end,   relative_addr_shift);
++                      } else {
++                              res[r].start = base + blk->res[r].start;
++                              res[r].end   = base + blk->res[r].end;
++                      }
++                      res[r].flags = blk->res[r].flags;
++              }
++
++              sdev->resource = res;
++              if (platform_device_register(sdev)) {
++                      kfree(res);
++                      goto fail;
++              }
++
++              printk(KERN_INFO "SoC: registering %s\n", blk->name);
++      }
++      return devices;
++
++fail:
++      soc_free_devices(devices, i + 1);
++      return NULL;
++}
++EXPORT_SYMBOL_GPL(soc_add_devices);
+Index: linux-2.6.22/drivers/mfd/soc-core.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/drivers/mfd/soc-core.h        2007-09-11 12:53:37.000000000 +0200
+@@ -0,0 +1,30 @@
++/*
++ * drivers/soc/soc-core.h
++ *
++ * core SoC support
++ * Copyright (c) 2006 Ian Molton
++ *
++ * This program is free software; you can 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 file contains prototypes for the functions in soc-core.c
++ *
++ * Created: 2006-11-28
++ *
++ */
++
++struct soc_device_data {
++      char *name;
++      struct resource *res;
++      int num_resources;
++      void *hwconfig; /* platform_data to pass to the subdevice */
++};
++
++struct platform_device *soc_add_devices(struct platform_device *dev,
++                                      struct soc_device_data *soc, int n_devs,
++                                      struct resource *mem,
++                                      int relative_addr_shift, int irq_base);
++
++void soc_free_devices(struct platform_device *devices, int nr_devs);
++
+Index: linux-2.6.22/include/asm-arm/arch-pxa/clock.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/include/asm-arm/arch-pxa/clock.h      2007-09-11 12:53:37.000000000 +0200
+@@ -0,0 +1,27 @@
++/*
++ *  linux/include/asm-arm/arch-pxa/clock.h
++ *
++ *  Copyright (C) 2006 Erik Hovland
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++struct clk {
++      struct list_head        node;
++      struct module           *owner;
++      struct clk              *parent;
++      const char              *name;
++      int                     id;
++      unsigned int            enabled;
++      unsigned long           rate;
++      unsigned long           ctrlbit;
++
++      void                    (*enable)(struct clk *);
++      void                    (*disable)(struct clk *);
++};
++
++
++extern int clk_register(struct clk *clk);
++extern void clk_unregister(struct clk *clk);
+Index: linux-2.6.22/include/asm-arm/arch-pxa/htcuniversal-asic.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/include/asm-arm/arch-pxa/htcuniversal-asic.h  2007-09-11 12:53:37.000000000 +0200
+@@ -0,0 +1,213 @@
++/*
++ * include/asm/arm/arch-pxa/htcuniversal-asic.h
++ *
++ * Authors: Giuseppe Zompatori <giuseppe_zompatori@yahoo.it>
++ *
++ * based on previews work, see below:
++ *
++ * include/asm/arm/arch-pxa/hx4700-asic.h
++ *      Copyright (c) 2004 SDG Systems, LLC
++ *
++ */
++
++#ifndef _HTCUNIVERSAL_ASIC_H_
++#define _HTCUNIVERSAL_ASIC_H_
++
++#include <asm/hardware/ipaq-asic3.h>
++
++/* ASIC3 */
++
++#define HTCUNIVERSAL_ASIC3_GPIO_PHYS  PXA_CS4_PHYS
++#define HTCUNIVERSAL_ASIC3_MMC_PHYS   PXA_CS3_PHYS
++
++/* TODO: some information is missing here */
++
++/* ASIC3 GPIO A bank */
++
++#define GPIOA_I2C_EN                   0      /* Output */
++#define GPIOA_SPK_PWR1_ON              1      /* Output */
++#define GPIOA_AUDIO_PWR_ON             2      /* Output */
++#define GPIOA_EARPHONE_PWR_ON          3      /* Output */
++
++#define GPIOA_UNKNOWN4                         4      /* Output */
++#define GPIOA_BUTTON_BACKLIGHT_N       5      /* Input  */
++#define GPIOA_SPK_PWR2_ON              6      /* Output */
++#define GPIOA_BUTTON_RECORD_N          7      /* Input  */
++
++#define GPIOA_BUTTON_CAMERA_N          8      /* Input  */
++#define GPIOA_UNKNOWN9                         9      /* Output */
++#define GPIOA_FLASHLIGHT              10      /* Output */
++#define GPIOA_COVER_ROTATE_N          11      /* Input  */
++
++#define GPIOA_TOUCHSCREEN_N           12      /* Input  */
++#define GPIOA_VOL_UP_N                13      /* Input  */
++#define GPIOA_VOL_DOWN_N              14      /* Input  */
++#define GPIOA_LCD_PWR5_ON             15      /* Output */
++
++/* ASIC3 GPIO B bank */
++
++#define GPIOB_BB_READY                         0      /* Input */
++#define GPIOB_CODEC_PDN                        1      /* Output */
++#define GPIOB_UNKNOWN2                         2      /* Input  */
++#define GPIOB_BB_UNKNOWN3              3      /* Input  */
++
++#define GPIOB_BT_IRQ                   4      /* Input  */
++#define GPIOB_CLAMSHELL_N              5      /* Input  */
++#define GPIOB_LCD_PWR3_ON              6      /* Output */
++#define GPIOB_BB_ALERT                         7      /* Input  */
++
++#define GPIOB_BB_RESET2                        8      /* Output */
++#define GPIOB_EARPHONE_N               9      /* Input  */
++#define GPIOB_MICRECORD_N             10      /* Input  */
++#define GPIOB_NIGHT_SENSOR            11      /* Input  */
++
++#define GPIOB_UMTS_DCD                        12      /* Input  */
++#define GPIOB_UNKNOWN13                       13      /* Input  */
++#define GPIOB_CHARGE_EN               14      /* Output */
++#define GPIOB_USB_PUEN                        15      /* Output */
++
++/* ASIC3 GPIO C bank */
++
++#define GPIOC_LED_BTWIFI               0      /* Output */
++#define GPIOC_LED_RED                  1      /* Output */
++#define GPIOC_LED_GREEN                        2      /* Output */
++#define GPIOC_BOARDID3                 3      /* Input  */
++
++#define GPIOC_WIFI_IRQ_N               4      /* Input  */
++#define GPIOC_WIFI_RESET               5      /* Output */
++#define GPIOC_WIFI_PWR1_ON             6      /* Output */
++#define GPIOC_BT_RESET                 7      /* Output */
++
++#define GPIOC_UNKNOWN8                 8      /* Output */
++#define GPIOC_LCD_PWR1_ON              9      /* Output */
++#define GPIOC_LCD_PWR2_ON             10      /* Output */
++#define GPIOC_BOARDID2                11      /* Input  */
++
++#define GPIOC_BOARDID1                        12      /* Input  */
++#define GPIOC_BOARDID0                13      /* Input  */
++#define GPIOC_BT_PWR_ON                       14      /* Output */
++#define GPIOC_CHARGE_ON                       15      /* Output */
++
++/* ASIC3 GPIO D bank */
++
++#define GPIOD_KEY_OK_N                         0      /* Input  */
++#define GPIOD_KEY_RIGHT_N              1      /* Input  */
++#define GPIOD_KEY_LEFT_N               2      /* Input  */
++#define GPIOD_KEY_DOWN_N               3      /* Input  */
++
++#define GPIOD_KEY_UP_N                 4      /* Input  */
++#define GPIOD_SDIO_DET                         5      /* Input  */
++#define GPIOD_WIFI_PWR2_ON             6      /* Output */
++#define GPIOD_HW_REBOOT                        7      /* Output */
++
++#define GPIOD_BB_RESET1                        8      /* Output */
++#define GPIOD_UNKNOWN9                         9      /* Output */
++#define GPIOD_VIBRA_PWR_ON            10      /* Output */
++#define GPIOD_WIFI_PWR3_ON            11      /* Output */
++
++#define GPIOD_FL_PWR_ON               12      /* Output */
++#define GPIOD_LCD_PWR4_ON             13      /* Output */
++#define GPIOD_BL_KEYP_PWR_ON          14      /* Output */
++#define GPIOD_BL_KEYB_PWR_ON          15      /* Output */
++
++extern struct platform_device htcuniversal_asic3;
++
++/* ASIC3 GPIO A bank */
++
++#define GPIO_I2C_EN                   0*16+GPIOA_I2C_EN
++#define GPIO_SPK_PWR1_ON              0*16+GPIOA_SPK_PWR1_ON
++#define GPIO_AUDIO_PWR_ON             0*16+GPIOA_AUDIO_PWR_ON
++#define GPIO_EARPHONE_PWR_ON          0*16+GPIOA_EARPHONE_PWR_ON
++
++#define GPIO_UNKNOWNA4                        0*16+GPIOA_UNKNOWN4
++#define GPIO_BUTTON_BACKLIGHT_N               0*16+GPIOA_BUTTON_BACKLIGHT_N
++#define GPIO_SPK_PWR2_ON              0*16+GPIOA_SPK_PWR2_ON
++#define GPIO_BUTTON_RECORD_N          0*16+GPIOA_BUTTON_RECORD_N
++
++#define GPIO_BUTTON_CAMERA_N          0*16+GPIOA_BUTTON_CAMERA_N
++#define GPIO_UNKNOWNA9                        0*16+GPIOA_UNKNOWN9
++#define GPIO_FLASHLIGHT               0*16+GPIOA_FLASHLIGHT
++#define GPIO_COVER_ROTATE_N           0*16+GPIOA_COVER_ROTATE_N
++
++#define GPIO_TOUCHSCREEN_N            0*16+GPIOA_TOUCHSCREEN_N
++#define GPIO_VOL_UP_N                         0*16+GPIOA_VOL_UP_N
++#define GPIO_VOL_DOWN_N               0*16+GPIOA_VOL_DOWN_N
++#define GPIO_LCD_PWR5_ON              0*16+GPIOA_LCD_PWR5_ON
++
++/* ASIC3 GPIO B bank */
++
++#define GPIO_BB_READY                 1*16+GPIOB_BB_READY
++#define GPIO_CODEC_PDN                        1*16+GPIOB_CODEC_PDN
++#define GPIO_UNKNOWNB2                        1*16+GPIOB_UNKNOWN2
++#define GPIO_BB_UNKNOWN3              1*16+GPIOB_BB_UNKNOWN3
++
++#define GPIO_BT_IRQ                   1*16+GPIOB_BT_IRQ
++#define GPIO_CLAMSHELL_N              1*16+GPIOB_CLAMSHELL_N
++#define GPIO_LCD_PWR3_ON              1*16+GPIOB_LCD_PWR3_ON
++#define GPIO_BB_ALERT                 1*16+GPIOB_BB_ALERT
++
++#define GPIO_BB_RESET2                        1*16+GPIOB_BB_RESET2
++#define GPIO_EARPHONE_N                       1*16+GPIOB_EARPHONE_N
++#define GPIO_MICRECORD_N              1*16+GPIOB_MICRECORD_N
++#define GPIO_NIGHT_SENSOR             1*16+GPIOB_NIGHT_SENSOR
++
++#define GPIO_UMTS_DCD                 1*16+GPIOB_UMTS_DCD
++#define GPIO_UNKNOWNB13                       1*16+GPIOB_UNKNOWN13
++#define GPIO_CHARGE_EN                        1*16+GPIOB_CHARGE_EN
++#define GPIO_USB_PUEN                         1*16+GPIOB_USB_PUEN
++
++/* ASIC3 GPIO C bank */
++
++#define GPIO_LED_BTWIFI               2*16+GPIOC_LED_BTWIFI
++#define GPIO_LED_RED                  2*16+GPIOC_LED_RED
++#define GPIO_LED_GREEN                        2*16+GPIOC_LED_GREEN
++#define GPIO_BOARDID3                         2*16+GPIOC_BOARDID3
++
++#define GPIO_WIFI_IRQ_N               2*16+GPIOC_WIFI_IRQ_N
++#define GPIO_WIFI_RESET               2*16+GPIOC_WIFI_RESET
++#define GPIO_WIFI_PWR1_ON             2*16+GPIOC_WIFI_PWR1_ON
++#define GPIO_BT_RESET                         2*16+GPIOC_BT_RESET
++
++#define GPIO_UNKNOWNC8                2*16+GPIOC_UNKNOWN8
++#define GPIO_LCD_PWR1_ON              2*16+GPIOC_LCD_PWR1_ON
++#define GPIO_LCD_PWR2_ON              2*16+GPIOC_LCD_PWR2_ON
++#define GPIO_BOARDID2                         2*16+GPIOC_BOARDID2
++
++#define GPIO_BOARDID1                 2*16+GPIOC_BOARDID1
++#define GPIO_BOARDID0                         2*16+GPIOC_BOARDID0
++#define GPIO_BT_PWR_ON                        2*16+GPIOC_BT_PWR_ON
++#define GPIO_CHARGE_ON                        2*16+GPIOC_CHARGE_ON
++
++/* ASIC3 GPIO D bank */
++
++#define GPIO_KEY_OK_N                 3*16+GPIOD_KEY_OK_N
++#define GPIO_KEY_RIGHT_N              3*16+GPIOD_KEY_RIGHT_N
++#define GPIO_KEY_LEFT_N                       3*16+GPIOD_KEY_LEFT_N
++#define GPIO_KEY_DOWN_N                       3*16+GPIOD_KEY_DOWN_N
++
++#define GPIO_KEY_UP_N                         3*16+GPIOD_KEY_UP_N
++#define GPIO_SDIO_DET                 3*16+GPIOD_SDIO_DET
++#define GPIO_WIFI_PWR2_ON             3*16+GPIOD_WIFI_PWR2_ON
++#define GPIO_HW_REBOOT                        3*16+GPIOD_HW_REBOOT
++
++#define GPIO_BB_RESET1                        3*16+GPIOD_BB_RESET1
++#define GPIO_UNKNOWND9                        3*16+GPIOD_UNKNOWN9
++#define GPIO_VIBRA_PWR_ON             3*16+GPIOD_VIBRA_PWR_ON
++#define GPIO_WIFI_PWR3_ON             3*16+GPIOD_WIFI_PWR3_ON
++
++#define GPIO_FL_PWR_ON                3*16+GPIOD_FL_PWR_ON
++#define GPIO_LCD_PWR4_ON              3*16+GPIOD_LCD_PWR4_ON
++#define GPIO_BL_KEYP_PWR_ON           3*16+GPIOD_BL_KEYP_PWR_ON
++#define GPIO_BL_KEYB_PWR_ON           3*16+GPIOD_BL_KEYB_PWR_ON
++
++#define HTCUNIVERSAL_EGPIO_BASE       PXA_CS2_PHYS+0x02000000
++
++#define EGPIO4_ON                      4  /* something */
++#define EGPIO5_BT_3V3_ON               5  /* Bluetooth related */
++#define EGPIO6_WIFI_ON                         6  /* WLAN related*/
++
++extern void htcuniversal_egpio_enable( u_int16_t bits );
++extern void htcuniversal_egpio_disable( u_int16_t bits );
++
++#endif /* _HTCUNIVERSAL_ASIC_H_ */
++
+Index: linux-2.6.22/include/asm-arm/arch-pxa/htcuniversal-gpio.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/include/asm-arm/arch-pxa/htcuniversal-gpio.h  2007-09-11 12:53:37.000000000 +0200
+@@ -0,0 +1,220 @@
++/*
++ * include/asm-arm/arch-pxa/htcuniversal-gpio.h
++ * History:
++ *
++ * 2004-12-10 Michael Opdenacker. Wrote down GPIO settings as identified by Jamey Hicks.
++ *            Reused the h2200-gpio.h file as a template.
++ */
++
++#ifndef _HTCUNIVERSAL_GPIO_H_
++#define _HTCUNIVERSAL_GPIO_H_
++
++#include <asm/arch/pxa-regs.h>
++
++#define GET_HTCUNIVERSAL_GPIO(gpio) \
++      (GPLR(GPIO_NR_HTCUNIVERSAL_ ## gpio) & GPIO_bit(GPIO_NR_HTCUNIVERSAL_ ## gpio))
++
++#define SET_HTCUNIVERSAL_GPIO(gpio, setp) \
++do { \
++if (setp) \
++      GPSR(GPIO_NR_HTCUNIVERSAL_ ## gpio) = GPIO_bit(GPIO_NR_HTCUNIVERSAL_ ## gpio); \
++else \
++      GPCR(GPIO_NR_HTCUNIVERSAL_ ## gpio) = GPIO_bit(GPIO_NR_HTCUNIVERSAL_ ## gpio); \
++} while (0)
++
++#define SET_HTCUNIVERSAL_GPIO_N(gpio, setp) \
++do { \
++if (setp) \
++      GPCR(GPIO_NR_HTCUNIVERSAL_ ## gpio ## _N) = GPIO_bit(GPIO_NR_HTCUNIVERSAL_ ## gpio ## _N); \
++else \
++      GPSR(GPIO_NR_HTCUNIVERSAL_ ## gpio ## _N) = GPIO_bit(GPIO_NR_HTCUNIVERSAL_ ## gpio ## _N); \
++} while (0)
++
++#define HTCUNIVERSAL_IRQ(gpio) \
++      IRQ_GPIO(GPIO_NR_HTCUNIVERSAL_ ## gpio)
++
++#define GPIO_NR_HTCUNIVERSAL_KEY_ON_N                 0
++#define GPIO_NR_HTCUNIVERSAL_GP_RST_N                 1
++
++#define GPIO_NR_HTCUNIVERSAL_USB_DET                  9
++#define GPIO_NR_HTCUNIVERSAL_POWER_DET                        10
++
++#define GPIO_NR_HTCUNIVERSAL_CIF_DD7                  12
++#define GPIO_NR_HTCUNIVERSAL_ASIC3_SDIO_INT_N         13
++#define GPIO_NR_HTCUNIVERSAL_ASIC3_EXT_INT            14
++#define GPIO_NR_HTCUNIVERSAL_CS1_N                    15
++
++#define GPIO_NR_HTCUNIVERSAL_CIF_DD6                  17
++#define GPIO_NR_HTCUNIVERSAL_RDY                      18
++
++#define GPIO_NR_HTCUNIVERSAL_PHONE_START              19
++
++#define GPIO_NR_HTCUNIVERSAL_KP_MKOUT7                        22
++#define GPIO_NR_HTCUNIVERSAL_SPI_CLK                  23
++#define GPIO_NR_HTCUNIVERSAL_SPI_FRM                  24
++#define GPIO_NR_HTCUNIVERSAL_SPI_DO                   25
++#define GPIO_NR_HTCUNIVERSAL_SPI_DI                   26
++
++#define GPIO_NR_HTCUNIVERSAL_CODEC_ON                 27
++#define GPIO_NR_HTCUNIVERSAL_I2S_BCK                  28
++#define GPIO_NR_HTCUNIVERSAL_I2S_DIN                  29
++#define GPIO_NR_HTCUNIVERSAL_I2S_DOUT                 30
++#define GPIO_NR_HTCUNIVERSAL_I2S_SYNC                 31
++
++#define GPIO_NR_HTCUNIVERSAL_RS232_ON                 32
++#define GPIO_NR_HTCUNIVERSAL_CS5_N                    33
++
++#define GPIO_NR_HTCUNIVERSAL_PHONE_RXD                        34
++#define GPIO_NR_HTCUNIVERSAL_PHONE_UART_CTS           35
++#define GPIO_NR_HTCUNIVERSAL_KP_MKIN7                 36
++#define GPIO_NR_HTCUNIVERSAL_KP_MKIN3                 37
++#define GPIO_NR_HTCUNIVERSAL_KP_MKIN4                 38
++#define GPIO_NR_HTCUNIVERSAL_PHONE_TXD                        39
++#define GPIO_NR_HTCUNIVERSAL_KP_MKOUT6                        40
++#define GPIO_NR_HTCUNIVERSAL_PHONE_UART_RTS           41
++#define GPIO_NR_HTCUNIVERSAL_BT_RXD                   42
++#define GPIO_NR_HTCUNIVERSAL_BT_TXD                   43
++#define GPIO_NR_HTCUNIVERSAL_BT_UART_CTS              44
++#define GPIO_NR_HTCUNIVERSAL_BT_UART_RTS              45
++
++#define GPIO_NR_HTCUNIVERSAL_SIR_RXD                  42
++#define GPIO_NR_HTCUNIVERSAL_SIR_TXD                  43
++
++#define GPIO_NR_HTCUNIVERSAL_POE_N                    48
++#define GPIO_NR_HTCUNIVERSAL_PWE_N                    49
++#define GPIO_NR_HTCUNIVERSAL_CIF_DD3                  50
++#define GPIO_NR_HTCUNIVERSAL_CIF_DD2                  51
++#define GPIO_NR_HTCUNIVERSAL_CIF_DD4                  52
++
++#define GPIO_NR_HTCUNIVERSAL_CIF_MCLK                 53
++#define GPIO_NR_HTCUNIVERSAL_CIF_PCLK                 54
++#define GPIO_NR_HTCUNIVERSAL_CIF_DD1                  55
++
++#define GPIO_NR_HTCUNIVERSAL_LDD0                     58
++#define GPIO_NR_HTCUNIVERSAL_LDD1                     59
++#define GPIO_NR_HTCUNIVERSAL_LDD2                     60
++#define GPIO_NR_HTCUNIVERSAL_LDD3                     61
++#define GPIO_NR_HTCUNIVERSAL_LDD4                     62
++#define GPIO_NR_HTCUNIVERSAL_LDD5                     63
++#define GPIO_NR_HTCUNIVERSAL_LDD6                     64
++#define GPIO_NR_HTCUNIVERSAL_LDD7                     65
++#define GPIO_NR_HTCUNIVERSAL_LDD8                     66
++#define GPIO_NR_HTCUNIVERSAL_LDD9                     67
++#define GPIO_NR_HTCUNIVERSAL_LDD10                    68
++#define GPIO_NR_HTCUNIVERSAL_LDD11                    69
++#define GPIO_NR_HTCUNIVERSAL_LDD12                    70
++#define GPIO_NR_HTCUNIVERSAL_LDD13                    71
++#define GPIO_NR_HTCUNIVERSAL_LDD14                    72
++#define GPIO_NR_HTCUNIVERSAL_LDD15                    73
++
++#define GPIO_NR_HTCUNIVERSAL_LFCLK_RD                 74
++#define GPIO_NR_HTCUNIVERSAL_LFCLK_A0                 75
++#define GPIO_NR_HTCUNIVERSAL_LFCLK_WR                 76
++#define GPIO_NR_HTCUNIVERSAL_LBIAS                    77
++
++#define GPIO_NR_HTCUNIVERSAL_CS2_N                    78
++#define GPIO_NR_HTCUNIVERSAL_CS3_N                    79
++#define GPIO_NR_HTCUNIVERSAL_CS4_N                    80
++#define GPIO_NR_HTCUNIVERSAL_CIF_DD0                  81
++#define GPIO_NR_HTCUNIVERSAL_CIF_DD5                  82
++
++#define GPIO_NR_HTCUNIVERSAL_CIF_LV                   84
++#define GPIO_NR_HTCUNIVERSAL_CIF_FV                   85
++
++#define GPIO_NR_HTCUNIVERSAL_LCD1                     86
++#define GPIO_NR_HTCUNIVERSAL_LCD2                     87
++
++#define GPIO_NR_HTCUNIVERSAL_KP_MKIN5                 90
++#define GPIO_NR_HTCUNIVERSAL_KP_MKIN6                 91
++
++#define GPIO_NR_HTCUNIVERSAL_DREQ1                    97
++
++#define GPIO_NR_HTCUNIVERSAL_PHONE_RESET              98
++
++#define GPIO_NR_HTCUNIVERSAL_KP_MKIN0                 100
++#define GPIO_NR_HTCUNIVERSAL_KP_MKIN1                 101
++#define GPIO_NR_HTCUNIVERSAL_KP_MKIN2                 102
++#define GPIO_NR_HTCUNIVERSAL_KP_MKOUT0                        103
++#define GPIO_NR_HTCUNIVERSAL_KP_MKOUT1                        104
++#define GPIO_NR_HTCUNIVERSAL_KP_MKOUT2                        105
++#define GPIO_NR_HTCUNIVERSAL_KP_MKOUT3                        106
++#define GPIO_NR_HTCUNIVERSAL_KP_MKOUT4                        107
++#define GPIO_NR_HTCUNIVERSAL_KP_MKOUT5                        108
++
++#define GPIO_NR_HTCUNIVERSAL_PHONE_UNKNOWN            109
++#define GPIO_NR_HTCUNIVERSAL_PHONE_OFF                        110
++
++#define GPIO_NR_HTCUNIVERSAL_USB_PUEN                 112
++#define GPIO_NR_HTCUNIVERSAL_I2S_SYSCLK                       113
++
++#define GPIO_NR_HTCUNIVERSAL_PWM_OUT1                 115
++
++#define GPIO_NR_HTCUNIVERSAL_I2C_SCL                  117
++#define GPIO_NR_HTCUNIVERSAL_I2C_SDA                  118
++
++#if 0
++#define GPIO_NR_HTCUNIVERSAL_CPU_BATT_FAULT_N
++#define GPIO_NR_HTCUNIVERSAL_ASIC3_RESET_N
++#define GPIO_NR_HTCUNIVERSAL_CHARGE_EN_N
++#define GPIO_NR_HTCUNIVERSAL_FLASH_VPEN
++#define GPIO_NR_HTCUNIVERSAL_BATT_OFF
++#define GPIO_NR_HTCUNIVERSAL_USB_CHARGE_RATE
++#define GPIO_NR_HTCUNIVERSAL_BL_DETECT_N
++#define GPIO_NR_HTCUNIVERSAL_CPU_HW_RESET_N
++#endif
++
++
++#define GPIO_NR_HTCUNIVERSAL_TOUCHSCREEN_SPI_CLK_MD   (23 | GPIO_ALT_FN_2_OUT)
++#define GPIO_NR_HTCUNIVERSAL_TOUCHSCREEN_SPI_FRM_MD   (24 | GPIO_ALT_FN_2_OUT)
++#define GPIO_NR_HTCUNIVERSAL_TOUCHSCREEN_SPI_DO_MD    (25 | GPIO_ALT_FN_2_OUT)
++#define GPIO_NR_HTCUNIVERSAL_TOUCHSCREEN_SPI_DI_MD    (26 | GPIO_ALT_FN_1_IN)
++
++#define GPIO_NR_HTCUNIVERSAL_I2S_BCK_MD                       (28 | GPIO_ALT_FN_1_OUT)
++#define GPIO_NR_HTCUNIVERSAL_I2S_DIN_MD                       (29 | GPIO_ALT_FN_2_IN)
++#define GPIO_NR_HTCUNIVERSAL_I2S_DOUT_MD              (30 | GPIO_ALT_FN_1_OUT)
++#define GPIO_NR_HTCUNIVERSAL_I2S_SYNC_MD              (31 | GPIO_ALT_FN_1_OUT)
++
++#define GPIO_NR_HTCUNIVERSAL_PHONE_RXD_MD             (34 | GPIO_ALT_FN_1_IN)
++#define GPIO_NR_HTCUNIVERSAL_PHONE_UART_CTS_MD                (35 | GPIO_ALT_FN_1_IN)
++
++#define GPIO_NR_HTCUNIVERSAL_PHONE_TXD_MD             (39 | GPIO_ALT_FN_2_OUT)
++#define GPIO_NR_HTCUNIVERSAL_PHONE_UART_RTS_MD                (41 | GPIO_ALT_FN_2_OUT)
++
++#define GPIO_NR_HTCUNIVERSAL_BT_RXD_MD                        (42 | GPIO_ALT_FN_1_IN)
++#define GPIO_NR_HTCUNIVERSAL_BT_TXD_MD                        (43 | GPIO_ALT_FN_2_OUT)
++#define GPIO_NR_HTCUNIVERSAL_BT_UART_CTS_MD           (44 | GPIO_ALT_FN_1_IN)
++#define GPIO_NR_HTCUNIVERSAL_BT_UART_RTS_MD           (45 | GPIO_ALT_FN_2_OUT)
++
++#define GPIO_NR_HTCUNIVERSAL_SIR_RXD_MD                       (46 | GPIO_ALT_FN_2_IN)
++#define GPIO_NR_HTCUNIVERSAL_SIR_TXD_MD                       (47 | GPIO_ALT_FN_1_OUT)
++
++#define GPIO_NR_HTCUNIVERSAL_POE_N_MD                 (48 | GPIO_ALT_FN_2_OUT | GPIO_DFLT_HIGH)
++#define GPIO_NR_HTCUNIVERSAL_PWE_N_MD                 (49 | GPIO_ALT_FN_2_OUT | GPIO_DFLT_HIGH)
++
++#define GPIO_NR_HTCUNIVERSAL_KP_MKIN0_MD              (GPIO_NR_HTCUNIVERSAL_KP_MKIN0 | GPIO_ALT_FN_1_IN)
++#define GPIO_NR_HTCUNIVERSAL_KP_MKIN1_MD              (GPIO_NR_HTCUNIVERSAL_KP_MKIN1 | GPIO_ALT_FN_1_IN)
++#define GPIO_NR_HTCUNIVERSAL_KP_MKIN2_MD              (GPIO_NR_HTCUNIVERSAL_KP_MKIN2 | GPIO_ALT_FN_1_IN)
++#define GPIO_NR_HTCUNIVERSAL_KP_MKIN3_MD              (GPIO_NR_HTCUNIVERSAL_KP_MKIN3 | GPIO_ALT_FN_3_IN)
++#define GPIO_NR_HTCUNIVERSAL_KP_MKIN4_MD              (GPIO_NR_HTCUNIVERSAL_KP_MKIN4 | GPIO_ALT_FN_2_IN)
++#define GPIO_NR_HTCUNIVERSAL_KP_MKIN5_MD              (GPIO_NR_HTCUNIVERSAL_KP_MKIN5 | GPIO_ALT_FN_1_IN)
++#define GPIO_NR_HTCUNIVERSAL_KP_MKIN6_MD              (GPIO_NR_HTCUNIVERSAL_KP_MKIN6 | GPIO_ALT_FN_1_IN)
++#define GPIO_NR_HTCUNIVERSAL_KP_MKIN7_MD              (GPIO_NR_HTCUNIVERSAL_KP_MKIN7 | GPIO_ALT_FN_3_IN)
++
++#define GPIO_NR_HTCUNIVERSAL_KP_MKOUT0_MD             (GPIO_NR_HTCUNIVERSAL_KP_MKOUT0 | GPIO_ALT_FN_2_OUT)
++#define GPIO_NR_HTCUNIVERSAL_KP_MKOUT1_MD             (GPIO_NR_HTCUNIVERSAL_KP_MKOUT1 | GPIO_ALT_FN_2_OUT)
++#define GPIO_NR_HTCUNIVERSAL_KP_MKOUT2_MD             (GPIO_NR_HTCUNIVERSAL_KP_MKOUT2 | GPIO_ALT_FN_2_OUT)
++#define GPIO_NR_HTCUNIVERSAL_KP_MKOUT3_MD             (GPIO_NR_HTCUNIVERSAL_KP_MKOUT3 | GPIO_ALT_FN_2_OUT)
++#define GPIO_NR_HTCUNIVERSAL_KP_MKOUT4_MD             (GPIO_NR_HTCUNIVERSAL_KP_MKOUT4 | GPIO_ALT_FN_2_OUT)
++#define GPIO_NR_HTCUNIVERSAL_KP_MKOUT5_MD             (GPIO_NR_HTCUNIVERSAL_KP_MKOUT5 | GPIO_ALT_FN_2_OUT)
++#define GPIO_NR_HTCUNIVERSAL_KP_MKOUT6_MD             (GPIO_NR_HTCUNIVERSAL_KP_MKOUT6 | GPIO_ALT_FN_1_OUT)
++#define GPIO_NR_HTCUNIVERSAL_KP_MKOUT7_MD             (GPIO_NR_HTCUNIVERSAL_KP_MKOUT7 | GPIO_ALT_FN_1_OUT)
++
++
++#define GPIO_NR_HTCUNIVERSAL_I2S_SYSCLK_MD            (113 | GPIO_ALT_FN_1_OUT)
++
++#define GPIO_NR_HTCUNIVERSAL_PWM1OUT_MD                       (115 | GPIO_ALT_FN_3_OUT)
++
++#define GPIO_NR_HTCUNIVERSAL_I2C_SCL_MD                       (117 | GPIO_ALT_FN_1_OUT)
++#define GPIO_NR_HTCUNIVERSAL_I2C_SDA_MD                       (118 | GPIO_ALT_FN_1_OUT)
++
++#endif /* _HTCUNIVERSAL_GPIO_H */
+Index: linux-2.6.22/include/asm-arm/arch-pxa/htcuniversal-init.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/include/asm-arm/arch-pxa/htcuniversal-init.h  2007-09-11 12:53:37.000000000 +0200
+@@ -0,0 +1,14 @@
++/*
++ * include/asm/arm/arch-pxa/htcuniversal-init.h
++ *      Copyright (c) 2004 SDG Systems, LLC
++ */
++
++#ifndef _HTCUNIVERSAL_INIT_H_
++#define _HTCUNIVERSAL_INIT_H_
++
++/* htcuniversal initialization data should be found here
++ * See -init.h files from other devices for details
++ */
++
++#endif /* _HTCUNIVERSAL_INIT_H_ */
++
+Index: linux-2.6.22/include/asm-arm/arch-pxa/htcuniversal.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/include/asm-arm/arch-pxa/htcuniversal.h       2007-09-11 12:53:37.000000000 +0200
+@@ -0,0 +1,3 @@
++#include <asm/arch/irqs.h>
++
++#define HTCUNIVERSAL_ASIC3_IRQ_BASE IRQ_BOARD_START
+Index: linux-2.6.22/include/asm-arm/arch-pxa/pxa-pm_ll.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/include/asm-arm/arch-pxa/pxa-pm_ll.h  2007-09-11 12:53:37.000000000 +0200
+@@ -0,0 +1,6 @@
++struct pxa_ll_pm_ops {
++      void (*suspend)(unsigned long);
++      void (*resume)(void);
++};
++
++extern struct pxa_ll_pm_ops *pxa_pm_set_ll_ops(struct pxa_ll_pm_ops *new_ops);
+Index: linux-2.6.22/include/asm-arm/arch-pxa/sharpsl.h
+===================================================================
+--- linux-2.6.22.orig/include/asm-arm/arch-pxa/sharpsl.h       2007-07-09 01:32:17.000000000 +0200
++++ linux-2.6.22/include/asm-arm/arch-pxa/sharpsl.h    2007-09-11 12:53:37.000000000 +0200
+@@ -25,12 +25,6 @@
+ /*
+  * SharpSL Backlight
+  */
+-struct corgibl_machinfo {
+-      int max_intensity;
+-      int default_intensity;
+-      int limit_mask;
+-      void (*set_bl_intensity)(int intensity);
+-};
+ extern void corgibl_limit_intensity(int limit);
+Index: linux-2.6.22/include/asm-arm/hardware/asic3_keys.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/include/asm-arm/hardware/asic3_keys.h 2007-09-11 12:53:37.000000000 +0200
+@@ -0,0 +1,18 @@
++#include <linux/input.h>
++
++struct asic3_keys_button {
++      /* Configuration parameters */
++      int keycode;
++      int gpio;
++      int active_low;
++      char *desc;
++      int type;
++      /* Internal state vars - add below */
++};
++
++struct asic3_keys_platform_data {
++      struct asic3_keys_button *buttons;
++      int nbuttons;
++        struct input_dev *input;
++        struct device *asic3_dev;
++};
+Index: linux-2.6.22/include/asm-arm/hardware/asic3_leds.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/include/asm-arm/hardware/asic3_leds.h 2007-09-11 12:53:37.000000000 +0200
+@@ -0,0 +1,34 @@
++/*
++ * LEDs support for HTC ASIC3 devices.
++ *
++ * Copyright (c) 2006  Anton Vorontsov <cbou@mail.ru>
++ *
++ * 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/init.h>
++#include <linux/platform_device.h>
++#include <linux/leds.h>
++
++struct asic3_leds_machinfo;
++
++struct asic3_led {
++      struct led_classdev led_cdev;
++      int hw_num;     /* Number of "hardware-accelerated" led */
++      int gpio_num;   /* Number of GPIO if hw_num == -1 */
++      struct asic3_leds_machinfo *machinfo;
++};
++
++struct asic3_leds_machinfo {
++      int num_leds;
++      struct asic3_led *leds;
++      struct platform_device *asic3_pdev;
++};
++
++extern int asic3_leds_register(void);
++extern void asic3_leds_unregister(void);
++
+Index: linux-2.6.22/include/asm-arm/hardware/ipaq-asic3.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/include/asm-arm/hardware/ipaq-asic3.h 2007-09-11 12:53:37.000000000 +0200
+@@ -0,0 +1,602 @@
++/*
++ *
++ * Definitions for the HTC ASIC3 chip found in several handheld devices
++ *
++ * Copyright 2001 Compaq Computer 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.
++ *
++ * COMPAQ COMPUTER CORPORATION MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
++ * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
++ * FITNESS FOR ANY PARTICULAR PURPOSE.
++ *
++ * Author: Andrew Christian
++ *
++ */
++
++#ifndef IPAQ_ASIC3_H
++#define IPAQ_ASIC3_H
++
++/****************************************************/
++/* IPAQ, ASIC #3, replaces ASIC #1 */
++
++#define IPAQ_ASIC3_OFFSET(x,y) (_IPAQ_ASIC3_ ## x ## _Base + _IPAQ_ASIC3_ ## x ## _ ## y)
++#define IPAQ_ASIC3_GPIO_OFFSET(x,y) (_IPAQ_ASIC3_GPIO_ ## x ## _Base + _IPAQ_ASIC3_GPIO_ ## y)
++
++
++/* All offsets below are specified with the following address bus shift */
++#define ASIC3_DEFAULT_ADDR_SHIFT 2
++
++#define _IPAQ_ASIC3_GPIO_A_Base      0x0000
++#define _IPAQ_ASIC3_GPIO_B_Base      0x0100
++#define _IPAQ_ASIC3_GPIO_C_Base      0x0200
++#define _IPAQ_ASIC3_GPIO_D_Base      0x0300
++
++#define _IPAQ_ASIC3_GPIO_Mask          0x00    /* R/W 0:don't mask, 1:mask interrupt */
++#define _IPAQ_ASIC3_GPIO_Direction     0x04    /* R/W 0:input, 1:output              */
++#define _IPAQ_ASIC3_GPIO_Out           0x08    /* R/W 0:output low, 1:output high    */
++#define _IPAQ_ASIC3_GPIO_TriggerType   0x0c    /* R/W 0:level, 1:edge                */
++#define _IPAQ_ASIC3_GPIO_EdgeTrigger   0x10    /* R/W 0:falling, 1:rising            */
++#define _IPAQ_ASIC3_GPIO_LevelTrigger  0x14    /* R/W 0:low, 1:high level detect     */
++#define _IPAQ_ASIC3_GPIO_SleepMask     0x18    /* R/W 0:don't mask, 1:mask trigger in sleep mode  */
++#define _IPAQ_ASIC3_GPIO_SleepOut      0x1c    /* R/W level 0:low, 1:high in sleep mode           */
++#define _IPAQ_ASIC3_GPIO_BattFaultOut  0x20    /* R/W level 0:low, 1:high in batt_fault           */
++#define _IPAQ_ASIC3_GPIO_IntStatus     0x24    /* R/W 0:none, 1:detect               */
++#define _IPAQ_ASIC3_GPIO_AltFunction   0x28   /* R/W 0:normal control 1:LED register control */
++#define _IPAQ_ASIC3_GPIO_SleepConf     0x2c    /* R/W bit 1: autosleep 0: disable gposlpout in normal mode, enable gposlpout in sleep mode */
++#define _IPAQ_ASIC3_GPIO_Status        0x30    /* R   Pin status                                  */
++
++#define IPAQ_ASIC3_GPIO_A_MASK(_b)            IPAQ_ASIC3_GPIO( _b, u16, A, Mask )
++#define IPAQ_ASIC3_GPIO_A_DIR(_b)             IPAQ_ASIC3_GPIO( _b, u16, A, Direction )
++#define IPAQ_ASIC3_GPIO_A_OUT(_b)             IPAQ_ASIC3_GPIO( _b, u16, A, Out )
++#define IPAQ_ASIC3_GPIO_A_LEVELTRI(_b)        IPAQ_ASIC3_GPIO( _b, u16, A, TriggerType )
++#define IPAQ_ASIC3_GPIO_A_RISING(_b)          IPAQ_ASIC3_GPIO( _b, u16, A, EdgeTrigger )
++#define IPAQ_ASIC3_GPIO_A_LEVEL(_b)           IPAQ_ASIC3_GPIO( _b, u16, A, LevelTrigger )
++#define IPAQ_ASIC3_GPIO_A_SLEEP_MASK(_b)      IPAQ_ASIC3_GPIO( _b, u16, A, SleepMask )
++#define IPAQ_ASIC3_GPIO_A_SLEEP_OUT(_b)       IPAQ_ASIC3_GPIO( _b, u16, A, SleepOut )
++#define IPAQ_ASIC3_GPIO_A_BATT_FAULT_OUT(_b)  IPAQ_ASIC3_GPIO( _b, u16, A, BattFaultOut )
++#define IPAQ_ASIC3_GPIO_A_INT_STATUS(_b)      IPAQ_ASIC3_GPIO( _b, u16, A, IntStatus )
++#define IPAQ_ASIC3_GPIO_A_ALT_FUNCTION(_b)    IPAQ_ASIC3_GPIO( _b, u16, A, AltFunction )
++#define IPAQ_ASIC3_GPIO_A_SLEEP_CONF(_b)      IPAQ_ASIC3_GPIO( _b, u16, A, SleepConf )
++#define IPAQ_ASIC3_GPIO_A_STATUS(_b)          IPAQ_ASIC3_GPIO( _b, u16, A, Status )
++
++#define IPAQ_ASIC3_GPIO_B_MASK(_b)            IPAQ_ASIC3_GPIO( _b, u16, B, Mask )
++#define IPAQ_ASIC3_GPIO_B_DIR(_b)             IPAQ_ASIC3_GPIO( _b, u16, B, Direction )
++#define IPAQ_ASIC3_GPIO_B_OUT(_b)             IPAQ_ASIC3_GPIO( _b, u16, B, Out )
++#define IPAQ_ASIC3_GPIO_B_LEVELTRI(_b)        IPAQ_ASIC3_GPIO( _b, u16, B, TriggerType )
++#define IPAQ_ASIC3_GPIO_B_RISING(_b)          IPAQ_ASIC3_GPIO( _b, u16, B, EdgeTrigger )
++#define IPAQ_ASIC3_GPIO_B_LEVEL(_b)           IPAQ_ASIC3_GPIO( _b, u16, B, LevelTrigger )
++#define IPAQ_ASIC3_GPIO_B_SLEEP_MASK(_b)      IPAQ_ASIC3_GPIO( _b, u16, B, SleepMask )
++#define IPAQ_ASIC3_GPIO_B_SLEEP_OUT(_b)       IPAQ_ASIC3_GPIO( _b, u16, B, SleepOut )
++#define IPAQ_ASIC3_GPIO_B_BATT_FAULT_OUT(_b)  IPAQ_ASIC3_GPIO( _b, u16, B, BattFaultOut )
++#define IPAQ_ASIC3_GPIO_B_INT_STATUS(_b)      IPAQ_ASIC3_GPIO( _b, u16, B, IntStatus )
++#define IPAQ_ASIC3_GPIO_B_ALT_FUNCTION(_b)    IPAQ_ASIC3_GPIO( _b, u16, B, AltFunction )
++#define IPAQ_ASIC3_GPIO_B_SLEEP_CONF(_b)      IPAQ_ASIC3_GPIO( _b, u16, B, SleepConf )
++#define IPAQ_ASIC3_GPIO_B_STATUS(_b)          IPAQ_ASIC3_GPIO( _b, u16, B, Status )
++
++#define IPAQ_ASIC3_GPIO_C_MASK(_b)            IPAQ_ASIC3_GPIO( _b, u16, C, Mask )
++#define IPAQ_ASIC3_GPIO_C_DIR(_b)             IPAQ_ASIC3_GPIO( _b, u16, C, Direction )
++#define IPAQ_ASIC3_GPIO_C_OUT(_b)             IPAQ_ASIC3_GPIO( _b, u16, C, Out )
++#define IPAQ_ASIC3_GPIO_C_LEVELTRI(_b)        IPAQ_ASIC3_GPIO( _b, u16, C, TriggerType )
++#define IPAQ_ASIC3_GPIO_C_RISING(_b)          IPAQ_ASIC3_GPIO( _b, u16, C, EdgeTrigger )
++#define IPAQ_ASIC3_GPIO_C_LEVEL(_b)           IPAQ_ASIC3_GPIO( _b, u16, C, LevelTrigger )
++#define IPAQ_ASIC3_GPIO_C_SLEEP_MASK(_b)      IPAQ_ASIC3_GPIO( _b, u16, C, SleepMask )
++#define IPAQ_ASIC3_GPIO_C_SLEEP_OUT(_b)       IPAQ_ASIC3_GPIO( _b, u16, C, SleepOut )
++#define IPAQ_ASIC3_GPIO_C_BATT_FAULT_OUT(_b)  IPAQ_ASIC3_GPIO( _b, u16, C, BattFaultOut )
++#define IPAQ_ASIC3_GPIO_C_INT_STATUS(_b)      IPAQ_ASIC3_GPIO( _b, u16, C, IntStatus )
++#define IPAQ_ASIC3_GPIO_C_ALT_FUNCTION(_b)    IPAQ_ASIC3_GPIO( _b, u16, C, AltFunction )
++#define IPAQ_ASIC3_GPIO_C_SLEEP_CONF(_b)      IPAQ_ASIC3_GPIO( _b, u16, C, SleepConf )
++#define IPAQ_ASIC3_GPIO_C_STATUS(_b)          IPAQ_ASIC3_GPIO( _b, u16, C, Status )
++
++#define IPAQ_ASIC3_GPIO_D_MASK(_b)            IPAQ_ASIC3_GPIO( _b, u16, D, Mask )
++#define IPAQ_ASIC3_GPIO_D_DIR(_b)             IPAQ_ASIC3_GPIO( _b, u16, D, Direction )
++#define IPAQ_ASIC3_GPIO_D_OUT(_b)             IPAQ_ASIC3_GPIO( _b, u16, D, Out )
++#define IPAQ_ASIC3_GPIO_D_LEVELTRI(_b)        IPAQ_ASIC3_GPIO( _b, u16, D, TriggerType )
++#define IPAQ_ASIC3_GPIO_D_RISING(_b)          IPAQ_ASIC3_GPIO( _b, u16, D, EdgeTrigger )
++#define IPAQ_ASIC3_GPIO_D_LEVEL(_b)           IPAQ_ASIC3_GPIO( _b, u16, D, LevelTrigger )
++#define IPAQ_ASIC3_GPIO_D_SLEEP_MASK(_b)      IPAQ_ASIC3_GPIO( _b, u16, D, SleepMask )
++#define IPAQ_ASIC3_GPIO_D_SLEEP_OUT(_b)       IPAQ_ASIC3_GPIO( _b, u16, D, SleepOut )
++#define IPAQ_ASIC3_GPIO_D_BATT_FAULT_OUT(_b)  IPAQ_ASIC3_GPIO( _b, u16, D, BattFaultOut )
++#define IPAQ_ASIC3_GPIO_D_INT_STATUS(_b)      IPAQ_ASIC3_GPIO( _b, u16, D, IntStatus )
++#define IPAQ_ASIC3_GPIO_D_ALT_FUNCTION(_b)    IPAQ_ASIC3_GPIO( _b, u16, D, AltFunction )
++#define IPAQ_ASIC3_GPIO_D_SLEEP_CONF(_b)      IPAQ_ASIC3_GPIO( _b, u16, D, SleepConf )
++#define IPAQ_ASIC3_GPIO_D_STATUS(_b)          IPAQ_ASIC3_GPIO( _b, u16, D, Status )
++
++#define _IPAQ_ASIC3_SPI_Base                0x0400
++#define _IPAQ_ASIC3_SPI_Control               0x0000
++#define _IPAQ_ASIC3_SPI_TxData                0x0004
++#define _IPAQ_ASIC3_SPI_RxData                0x0008
++#define _IPAQ_ASIC3_SPI_Int                   0x000c
++#define _IPAQ_ASIC3_SPI_Status                0x0010
++
++#define IPAQ_ASIC3_SPI_Control(_b)            IPAQ_ASIC3( _b, u16, SPI, Control )
++#define IPAQ_ASIC3_SPI_TxData(_b)             IPAQ_ASIC3( _b, u16, SPI, TxData )
++#define IPAQ_ASIC3_SPI_RxData(_b)             IPAQ_ASIC3( _b, u16, SPI, RxData )
++#define IPAQ_ASIC3_SPI_Int(_b)                IPAQ_ASIC3( _b, u16, SPI, Int )
++#define IPAQ_ASIC3_SPI_Status(_b)             IPAQ_ASIC3( _b, u16, SPI, Status )
++
++#define SPI_CONTROL_SPR(clk)      ((clk) & 0x0f)  /* Clock rate */
++
++#define _IPAQ_ASIC3_PWM_0_Base                0x0500
++#define _IPAQ_ASIC3_PWM_1_Base                0x0600
++#define _IPAQ_ASIC3_PWM_TimeBase              0x0000
++#define _IPAQ_ASIC3_PWM_PeriodTime            0x0004
++#define _IPAQ_ASIC3_PWM_DutyTime              0x0008
++
++#define IPAQ_ASIC3_PWM_TimeBase(_b, x)        IPAQ_ASIC3_N( _b, u16, PWM, x, TimeBase )
++#define IPAQ_ASIC3_PWM_PeriodTime(_b, x)      IPAQ_ASIC3_N( _b, u16, PWM, x, PeriodTime )
++#define IPAQ_ASIC3_PWM_DutyTime(_b, x)        IPAQ_ASIC3_N( _b, u16, PWM, x, DutyTime )
++
++#define PWM_TIMEBASE_VALUE(x)    ((x)&0xf)   /* Low 4 bits sets time base */
++#define PWM_TIMEBASE_ENABLE     (1 << 4)   /* Enable clock */
++
++#define _IPAQ_ASIC3_LED_0_Base                0x0700
++#define _IPAQ_ASIC3_LED_1_Base                0x0800
++#define _IPAQ_ASIC3_LED_2_Base                      0x0900
++#define _IPAQ_ASIC3_LED_TimeBase              0x0000    /* R/W  7 bits */
++#define _IPAQ_ASIC3_LED_PeriodTime            0x0004    /* R/W 12 bits */
++#define _IPAQ_ASIC3_LED_DutyTime              0x0008    /* R/W 12 bits */
++#define _IPAQ_ASIC3_LED_AutoStopCount         0x000c    /* R/W 16 bits */
++
++#define IPAQ_ASIC3_LED_TimeBase(_b, x)         IPAQ_ASIC3_N( _b,  u8, LED, x, TimeBase )
++#define IPAQ_ASIC3_LED_PeriodTime(_b, x)       IPAQ_ASIC3_N( _b, u16, LED, x, PeriodTime )
++#define IPAQ_ASIC3_LED_DutyTime(_b, x)         IPAQ_ASIC3_N( _b, u16, LED, x, DutyTime )
++#define IPAQ_ASIC3_LED_AutoStopCount(_b, x)    IPAQ_ASIC3_N( _b, u16, LED, x, AutoStopCount )
++
++/* LED TimeBase bits - match ASIC2 */
++#define LED_TBS               0x0f            /* Low 4 bits sets time base, max = 13          */
++                                      /* Note: max = 5 on hx4700                      */
++                                      /* 0: maximum time base                         */
++                                      /* 1: maximum time base / 2                     */
++                                      /* n: maximum time base / 2^n                   */
++
++#define LED_EN                (1 << 4)        /* LED ON/OFF 0:off, 1:on                       */
++#define LED_AUTOSTOP  (1 << 5)        /* LED ON/OFF auto stop set 0:disable, 1:enable */
++#define LED_ALWAYS    (1 << 6)        /* LED Interrupt Mask 0:No mask, 1:mask         */
++
++#define _IPAQ_ASIC3_CLOCK_Base                0x0A00
++#define _IPAQ_ASIC3_CLOCK_CDEX           0x00
++#define _IPAQ_ASIC3_CLOCK_SEL            0x04
++
++#define IPAQ_ASIC3_CLOCK_CDEX(_b)         IPAQ_ASIC3( _b, u16, CLOCK, CDEX )
++#define IPAQ_ASIC3_CLOCK_SEL(_b)          IPAQ_ASIC3( _b, u16, CLOCK, SEL )
++
++#define CLOCK_CDEX_SOURCE       (1 << 0)  /* 2 bits */
++#define CLOCK_CDEX_SOURCE0      (1 << 0)
++#define CLOCK_CDEX_SOURCE1      (1 << 1)
++#define CLOCK_CDEX_SPI          (1 << 2)
++#define CLOCK_CDEX_OWM          (1 << 3)
++#define CLOCK_CDEX_PWM0         (1 << 4)
++#define CLOCK_CDEX_PWM1         (1 << 5)
++#define CLOCK_CDEX_LED0         (1 << 6)
++#define CLOCK_CDEX_LED1         (1 << 7)
++#define CLOCK_CDEX_LED2         (1 << 8)
++
++#define CLOCK_CDEX_SD_HOST      (1 << 9)   /* R/W: SD host clock source 24.576M/12.288M */
++#define CLOCK_CDEX_SD_BUS       (1 << 10)  /* R/W: SD bus clock source control 24.576M/12.288M */
++#define CLOCK_CDEX_SMBUS        (1 << 11)
++#define CLOCK_CDEX_CONTROL_CX   (1 << 12)
++
++#define CLOCK_CDEX_EX0          (1 << 13)  /* R/W: 32.768 kHz crystal */
++#define CLOCK_CDEX_EX1          (1 << 14)  /* R/W: 24.576 MHz crystal */
++
++#define CLOCK_SEL_SD_HCLK_SEL   (1 << 0)   /* R/W: SDIO host clock select  -  1: 24.576 Mhz, 0: 12.288 MHz */
++#define CLOCK_SEL_SD_BCLK_SEL   (1 << 1)   /* R/W: SDIO bus clock select -  1: 24.576 MHz, 0: 12.288 MHz */
++#define CLOCK_SEL_CX            (1 << 2)   /* R/W: INT clock source control (32.768 kHz) */
++
++
++#define _IPAQ_ASIC3_INTR_Base         0x0B00
++
++#define _IPAQ_ASIC3_INTR_IntMask       0x00  /* Interrupt mask control */
++#define _IPAQ_ASIC3_INTR_PIntStat      0x04  /* Peripheral interrupt status */
++#define _IPAQ_ASIC3_INTR_IntCPS        0x08  /* Interrupt timer clock pre-scale */
++#define _IPAQ_ASIC3_INTR_IntTBS        0x0c  /* Interrupt timer set */
++
++#define IPAQ_ASIC3_INTR_IntMask(_b)       IPAQ_ASIC3( _b, u8, INTR, IntMask )
++#define IPAQ_ASIC3_INTR_PIntStat(_b)      IPAQ_ASIC3( _b, u8, INTR, PIntStat )
++#define IPAQ_ASIC3_INTR_IntCPS(_b)        IPAQ_ASIC3( _b, u8, INTR, IntCPS )
++#define IPAQ_ASIC3_INTR_IntTBS(_b)        IPAQ_ASIC3( _b, u16, INTR, IntTBS )
++
++#define ASIC3_INTMASK_GINTMASK    (1 << 0)  /* Global interrupt mask 1:enable */
++#define ASIC3_INTMASK_GINTEL      (1 << 1)  /* 1: rising edge, 0: hi level */
++#define ASIC3_INTMASK_MASK0       (1 << 2)
++#define ASIC3_INTMASK_MASK1       (1 << 3)
++#define ASIC3_INTMASK_MASK2       (1 << 4)
++#define ASIC3_INTMASK_MASK3       (1 << 5)
++#define ASIC3_INTMASK_MASK4       (1 << 6)
++#define ASIC3_INTMASK_MASK5       (1 << 7)
++
++#define ASIC3_INTR_PERIPHERAL_A   (1 << 0)
++#define ASIC3_INTR_PERIPHERAL_B   (1 << 1)
++#define ASIC3_INTR_PERIPHERAL_C   (1 << 2)
++#define ASIC3_INTR_PERIPHERAL_D   (1 << 3)
++#define ASIC3_INTR_LED0           (1 << 4)
++#define ASIC3_INTR_LED1           (1 << 5)
++#define ASIC3_INTR_LED2           (1 << 6)
++#define ASIC3_INTR_SPI            (1 << 7)
++#define ASIC3_INTR_SMBUS          (1 << 8)
++#define ASIC3_INTR_OWM            (1 << 9)
++
++#define ASIC3_INTR_CPS(x)         ((x)&0x0f)    /* 4 bits, max 14 */
++#define ASIC3_INTR_CPS_SET        ( 1 << 4 )    /* Time base enable */
++
++
++/* Basic control of the SD ASIC */
++#define _IPAQ_ASIC3_SDHWCTRL_Base     0x0E00
++
++#define _IPAQ_ASIC3_SDHWCTRL_SDConf    0x00
++#define IPAQ_ASIC3_SDHWCTRL_SDConf(_b)    IPAQ_ASIC3( _b, u8, SDHWCTRL, SDConf )
++
++#define ASIC3_SDHWCTRL_SUSPEND    (1 << 0)  /* 1=suspend all SD operations */
++#define ASIC3_SDHWCTRL_CLKSEL     (1 << 1)  /* 1=SDICK, 0=HCLK */
++#define ASIC3_SDHWCTRL_PCLR       (1 << 2)  /* All registers of SDIO cleared */
++#define ASIC3_SDHWCTRL_LEVCD      (1 << 3)  /* Level of SD card detection: 1:high, 0:low */
++#define ASIC3_SDHWCTRL_LEVWP      (1 << 4)  /* Level of SD card write protection: 1=low, 0=high */
++#define ASIC3_SDHWCTRL_SDLED      (1 << 5)  /* SD card LED signal 1=enable, 0=disable */
++#define ASIC3_SDHWCTRL_SDPWR      (1 << 6)  /* SD card power supply control 1=enable */
++
++
++/* This is a pointer to an array of 12 u32 values - but only the lower 2 bytes matter */
++/* Use it as "IPAQ_ASIC3_HWPROTECT_ARRAY[x]" */
++
++#define _IPAQ_ASIC3_HWPROTECT_Base    0x1000
++#define IPAQ_ASIC3_HWPROTECT_ARRAY  ((volatile u32*)(_IPAQ_ASIC3_Base + _IPAQ_ASIC3_HWPROTECT_Base))
++#define HWPROTECT_ARRAY_LEN 12
++#define HWPROTECT_ARRAY_VALUES {0x4854,0x432d,0x5344,0x494f,0x2050,0x2f4e,0x3a33,0x3048,0x3830,0x3032,0x382d,0x3030}
++
++
++#define _IPAQ_ASIC3_EXTCF_Base                0x1100
++
++#define _IPAQ_ASIC3_EXTCF_Select         0x00
++#define _IPAQ_ASIC3_EXTCF_Reset          0x04
++
++#define IPAQ_ASIC3_EXTCF_Select(_b)    IPAQ_ASIC3( _b, u16, EXTCF, Select )
++#define IPAQ_ASIC3_EXTCF_Reset(_b)     IPAQ_ASIC3( _b, u16, EXTCF, Reset )
++
++#define ASIC3_EXTCF_SMOD0              (1 << 0)  /* slot number of mode 0 */
++#define ASIC3_EXTCF_SMOD1              (1 << 1)  /* slot number of mode 1 */
++#define ASIC3_EXTCF_SMOD2              (1 << 2)  /* slot number of mode 2 */
++#define ASIC3_EXTCF_OWM_EN             (1 << 4)  /* enable onewire module */
++#define ASIC3_EXTCF_OWM_SMB            (1 << 5)  /* OWM bus selection */
++#define ASIC3_EXTCF_OWM_RESET            (1 << 6)  /* undocumented, used by OWM and CF */
++#define ASIC3_EXTCF_CF0_SLEEP_MODE       (1 << 7)  /* CF0 sleep state control */
++#define ASIC3_EXTCF_CF1_SLEEP_MODE       (1 << 8)  /* CF1 sleep state control */
++#define ASIC3_EXTCF_CF0_PWAIT_EN         (1 << 10)  /* CF0 PWAIT_n control */
++#define ASIC3_EXTCF_CF1_PWAIT_EN         (1 << 11)  /* CF1 PWAIT_n control */
++#define ASIC3_EXTCF_CF0_BUF_EN           (1 << 12)  /* CF0 buffer control */
++#define ASIC3_EXTCF_CF1_BUF_EN           (1 << 13)  /* CF1 buffer control */
++#define ASIC3_EXTCF_SD_MEM_ENABLE        (1 << 14)
++#define ASIC3_EXTCF_CF_SLEEP             (1 << 15)  /* CF sleep mode control */
++
++/*****************************************************************************
++ *  The Onewire interface registers
++ *
++ *  OWM_CMD
++ *  OWM_DAT
++ *  OWM_INTR
++ *  OWM_INTEN
++ *  OWM_CLKDIV
++ *
++ *****************************************************************************/
++
++#define _IPAQ_ASIC3_OWM_Base          0xC00
++
++#define _IPAQ_ASIC3_OWM_CMD         0x00
++#define _IPAQ_ASIC3_OWM_DAT         0x04
++#define _IPAQ_ASIC3_OWM_INTR        0x08
++#define _IPAQ_ASIC3_OWM_INTEN       0x0C
++#define _IPAQ_ASIC3_OWM_CLKDIV      0x10
++
++#define ASIC3_OWM_CMD_ONEWR         (1 << 0)
++#define ASIC3_OWM_CMD_SRA           (1 << 1)
++#define ASIC3_OWM_CMD_DQO           (1 << 2)
++#define ASIC3_OWM_CMD_DQI           (1 << 3)
++
++#define ASIC3_OWM_INTR_PD          (1 << 0)
++#define ASIC3_OWM_INTR_PDR         (1 << 1)
++#define ASIC3_OWM_INTR_TBE         (1 << 2)
++#define ASIC3_OWM_INTR_TEMP        (1 << 3)
++#define ASIC3_OWM_INTR_RBF         (1 << 4)
++
++#define ASIC3_OWM_INTEN_EPD        (1 << 0)
++#define ASIC3_OWM_INTEN_IAS        (1 << 1)
++#define ASIC3_OWM_INTEN_ETBE       (1 << 2)
++#define ASIC3_OWM_INTEN_ETMT       (1 << 3)
++#define ASIC3_OWM_INTEN_ERBF       (1 << 4)
++
++#define ASIC3_OWM_CLKDIV_PRE       (3 << 0) /* two bits wide at bit position 0 */
++#define ASIC3_OWM_CLKDIV_DIV       (7 << 2) /* 3 bits wide at bit position 2 */
++
++
++/*****************************************************************************
++ *  The SD configuration registers are at a completely different location
++ *  in memory.  They are divided into three sets of registers:
++ *
++ *  SD_CONFIG         Core configuration register
++ *  SD_CTRL           Control registers for SD operations
++ *  SDIO_CTRL         Control registers for SDIO operations
++ *
++ *****************************************************************************/
++
++#define IPAQ_ASIC3_SD_CONFIG(_b, s,x)   \
++     (*((volatile s *) ((_b) + _IPAQ_ASIC3_SD_CONFIG_Base + (_IPAQ_ASIC3_SD_CONFIG_ ## x))))
++
++#define _IPAQ_ASIC3_SD_CONFIG_Base            0x0400    // Assumes 32 bit addressing
++
++#define _IPAQ_ASIC3_SD_CONFIG_Command           0x08   /* R/W: Command */
++#define _IPAQ_ASIC3_SD_CONFIG_Addr0             0x20   /* [9:31] SD Control Register Base Address */
++#define _IPAQ_ASIC3_SD_CONFIG_Addr1             0x24   /* [9:31] SD Control Register Base Address */
++#define _IPAQ_ASIC3_SD_CONFIG_IntPin            0x78   /* R/O: interrupt assigned to pin */
++#define _IPAQ_ASIC3_SD_CONFIG_ClkStop           0x80   /* Set to 0x1f to clock SD controller, 0 otherwise. */
++                                                      /* at 0x82 - Gated Clock Control */
++#define _IPAQ_ASIC3_SD_CONFIG_ClockMode         0x84   /* Control clock of SD controller */
++#define _IPAQ_ASIC3_SD_CONFIG_SDHC_PinStatus    0x88   /* R/0: read status of SD pins */
++#define _IPAQ_ASIC3_SD_CONFIG_SDHC_Power1       0x90   /* Power1 - manual power control */
++                                                      /* Power2 is at 0x92 - auto power up after card inserted */
++#define _IPAQ_ASIC3_SD_CONFIG_SDHC_Power3       0x94   /* auto power down when card removed */
++#define _IPAQ_ASIC3_SD_CONFIG_SDHC_CardDetect   0x98   /* */
++#define _IPAQ_ASIC3_SD_CONFIG_SDHC_Slot         0xA0   /* R/O: define support slot number */
++#define _IPAQ_ASIC3_SD_CONFIG_SDHC_ExtGateClk1  0x1E0  /* Could be used for gated clock (don't use) */
++#define _IPAQ_ASIC3_SD_CONFIG_SDHC_ExtGateClk2  0x1E2  /* Could be used for gated clock (don't use) */
++#define _IPAQ_ASIC3_SD_CONFIG_SDHC_GPIO_OutAndEnable  0x1E8  /* GPIO Output Reg. , at 0x1EA - GPIO Output Enable Reg. */
++#define _IPAQ_ASIC3_SD_CONFIG_SDHC_GPIO_Status  0x1EC  /* GPIO Status Reg. */
++#define _IPAQ_ASIC3_SD_CONFIG_SDHC_ExtGateClk3  0x1F0  /* Bit 1: double buffer/single buffer */
++
++#define IPAQ_ASIC3_SD_CONFIG_Command(_b)           IPAQ_ASIC3_SD_CONFIG(_b, u16, Command )
++#define IPAQ_ASIC3_SD_CONFIG_Addr0(_b)             IPAQ_ASIC3_SD_CONFIG(_b, u16, Addr0 )
++#define IPAQ_ASIC3_SD_CONFIG_Addr1(_b)             IPAQ_ASIC3_SD_CONFIG(_b, u16, Addr1 )
++#define IPAQ_ASIC3_SD_CONFIG_IntPin(_b)            IPAQ_ASIC3_SD_CONFIG(_b, u8, IntPin )
++#define IPAQ_ASIC3_SD_CONFIG_ClkStop(_b)           IPAQ_ASIC3_SD_CONFIG(_b, u8, ClkStop )
++#define IPAQ_ASIC3_SD_CONFIG_ClockMode(_b)         IPAQ_ASIC3_SD_CONFIG(_b, u8, ClockMode )
++#define IPAQ_ASIC3_SD_CONFIG_SDHC_PinStatus(_b)    IPAQ_ASIC3_SD_CONFIG(_b, u16, SDHC_PinStatus )
++#define IPAQ_ASIC3_SD_CONFIG_SDHC_Power1(_b)       IPAQ_ASIC3_SD_CONFIG(_b, u16, SDHC_Power1 )
++#define IPAQ_ASIC3_SD_CONFIG_SDHC_Power3(_b)       IPAQ_ASIC3_SD_CONFIG(_b, u16, SDHC_Power3 )
++#define IPAQ_ASIC3_SD_CONFIG_SDHC_CardDetect(_b)   IPAQ_ASIC3_SD_CONFIG(_b, u16, SDHC_CardDetect )
++#define IPAQ_ASIC3_SD_CONFIG_SDHC_Slot(_b)         IPAQ_ASIC3_SD_CONFIG(_b, u16, SDHC_Slot )
++#define IPAQ_ASIC3_SD_CONFIG_SDHC_ExtGateClk1(_b)  IPAQ_ASIC3_SD_CONFIG(_b, u16, SDHC_ExtGateClk1 )
++#define IPAQ_ASIC3_SD_CONFIG_SDHC_ExtGateClk3(_b)  IPAQ_ASIC3_SD_CONFIG(_b, u16, SDHC_ExtGateClk3 )
++
++#define SD_CONFIG_
++
++#define SD_CONFIG_COMMAND_MAE                (1<<1)    /* Memory access enable (set to 1 to access SD Controller) */
++
++#define SD_CONFIG_CLK_ENABLE_ALL             0x1f
++
++#define SD_CONFIG_POWER1_PC_33V              0x0200    /* Set for 3.3 volts */
++#define SD_CONFIG_POWER1_PC_OFF              0x0000    /* Turn off power */
++
++#define SD_CONFIG_CARDDETECTMODE_CLK           ((x)&0x3) /* two bits - number of cycles for card detection */
++
++
++#define _IPAQ_ASIC3_SD_CTRL_Base            0x1000
++
++#define IPAQ_ASIC3_SD(_b, s,x)   \
++     (*((volatile s *) ((_b) + _IPAQ_ASIC3_SD_CTRL_Base + (_IPAQ_ASIC3_SD_CTRL_ ## x))))
++
++#define _IPAQ_ASIC3_SD_CTRL_Cmd                  0x00
++#define _IPAQ_ASIC3_SD_CTRL_Arg0                 0x08
++#define _IPAQ_ASIC3_SD_CTRL_Arg1                 0x0C
++#define _IPAQ_ASIC3_SD_CTRL_StopInternal         0x10
++#define _IPAQ_ASIC3_SD_CTRL_TransferSectorCount  0x14
++#define _IPAQ_ASIC3_SD_CTRL_Response0            0x18
++#define _IPAQ_ASIC3_SD_CTRL_Response1            0x1C
++#define _IPAQ_ASIC3_SD_CTRL_Response2            0x20
++#define _IPAQ_ASIC3_SD_CTRL_Response3            0x24
++#define _IPAQ_ASIC3_SD_CTRL_Response4            0x28
++#define _IPAQ_ASIC3_SD_CTRL_Response5            0x2C
++#define _IPAQ_ASIC3_SD_CTRL_Response6            0x30
++#define _IPAQ_ASIC3_SD_CTRL_Response7            0x34
++#define _IPAQ_ASIC3_SD_CTRL_CardStatus           0x38
++#define _IPAQ_ASIC3_SD_CTRL_BufferCtrl           0x3C
++#define _IPAQ_ASIC3_SD_CTRL_IntMaskCard          0x40
++#define _IPAQ_ASIC3_SD_CTRL_IntMaskBuffer        0x44
++#define _IPAQ_ASIC3_SD_CTRL_CardClockCtrl        0x48
++#define _IPAQ_ASIC3_SD_CTRL_MemCardXferDataLen   0x4C
++#define _IPAQ_ASIC3_SD_CTRL_MemCardOptionSetup   0x50
++#define _IPAQ_ASIC3_SD_CTRL_ErrorStatus0         0x58
++#define _IPAQ_ASIC3_SD_CTRL_ErrorStatus1         0x5C
++#define _IPAQ_ASIC3_SD_CTRL_DataPort             0x60
++#define _IPAQ_ASIC3_SD_CTRL_TransactionCtrl      0x68
++#define _IPAQ_ASIC3_SD_CTRL_SoftwareReset        0x1C0
++
++#define IPAQ_ASIC3_SD_CTRL_Cmd(_b)                  IPAQ_ASIC3_SD( _b, u16, Cmd )   /* */
++#define IPAQ_ASIC3_SD_CTRL_Arg0(_b)                 IPAQ_ASIC3_SD( _b, u16, Arg0 )   /* */
++#define IPAQ_ASIC3_SD_CTRL_Arg1(_b)                 IPAQ_ASIC3_SD( _b, u16, Arg1 )   /* */
++#define IPAQ_ASIC3_SD_CTRL_StopInternal(_b)         IPAQ_ASIC3_SD( _b, u16, StopInternal )   /* */
++#define IPAQ_ASIC3_SD_CTRL_TransferSectorCount(_b)  IPAQ_ASIC3_SD( _b, u16, TransferSectorCount )   /* */
++#define IPAQ_ASIC3_SD_CTRL_Response0(_b)            IPAQ_ASIC3_SD( _b, u16, Response0 )   /* */
++#define IPAQ_ASIC3_SD_CTRL_Response1(_b)            IPAQ_ASIC3_SD( _b, u16, Response1 )   /* */
++#define IPAQ_ASIC3_SD_CTRL_Response2(_b)            IPAQ_ASIC3_SD( _b, u16, Response2 )   /* */
++#define IPAQ_ASIC3_SD_CTRL_Response3(_b)            IPAQ_ASIC3_SD( _b, u16, Response3 )   /* */
++#define IPAQ_ASIC3_SD_CTRL_Response4(_b)            IPAQ_ASIC3_SD( _b, u16, Response4 )   /* */
++#define IPAQ_ASIC3_SD_CTRL_Response5(_b)            IPAQ_ASIC3_SD( _b, u16, Response5 )   /* */
++#define IPAQ_ASIC3_SD_CTRL_Response6(_b)            IPAQ_ASIC3_SD( _b, u16, Response6 )   /* */
++#define IPAQ_ASIC3_SD_CTRL_Response7(_b)            IPAQ_ASIC3_SD( _b, u16, Response7 )   /* */
++#define IPAQ_ASIC3_SD_CTRL_CardStatus(_b)           IPAQ_ASIC3_SD( _b, u16, CardStatus )   /* */
++#define IPAQ_ASIC3_SD_CTRL_BufferCtrl(_b)           IPAQ_ASIC3_SD( _b, u16, BufferCtrl )   /* and error status*/
++#define IPAQ_ASIC3_SD_CTRL_IntMaskCard(_b)          IPAQ_ASIC3_SD( _b, u16, IntMaskCard )   /* */
++#define IPAQ_ASIC3_SD_CTRL_IntMaskBuffer(_b)        IPAQ_ASIC3_SD( _b, u16, IntMaskBuffer )   /* */
++#define IPAQ_ASIC3_SD_CTRL_CardClockCtrl(_b)        IPAQ_ASIC3_SD( _b, u16, CardClockCtrl )   /* */
++#define IPAQ_ASIC3_SD_CTRL_MemCardXferDataLen(_b)   IPAQ_ASIC3_SD( _b, u16, MemCardXferDataLen )   /* */
++#define IPAQ_ASIC3_SD_CTRL_MemCardOptionSetup(_b)   IPAQ_ASIC3_SD( _b, u16, MemCardOptionSetup )   /* */
++#define IPAQ_ASIC3_SD_CTRL_ErrorStatus0(_b)         IPAQ_ASIC3_SD( _b, u16, ErrorStatus0 )   /* */
++#define IPAQ_ASIC3_SD_CTRL_ErrorStatus1(_b)         IPAQ_ASIC3_SD( _b, u16, ErrorStatus1 )   /* */
++#define IPAQ_ASIC3_SD_CTRL_DataPort(_b)             IPAQ_ASIC3_SD( _b, u16, DataPort )   /* */
++#define IPAQ_ASIC3_SD_CTRL_TransactionCtrl(_b)      IPAQ_ASIC3_SD( _b, u16, TransactionCtrl )   /* */
++#define IPAQ_ASIC3_SD_CTRL_SoftwareReset(_b)        IPAQ_ASIC3_SD( _b, u16, SoftwareReset )   /* */
++
++#define SD_CTRL_SOFTWARE_RESET_CLEAR            (1<<0)
++
++#define SD_CTRL_TRANSACTIONCONTROL_SET          (1<<8) // 0x0100
++
++#define SD_CTRL_CARDCLOCKCONTROL_FOR_SD_CARD    (1<<15)// 0x8000
++#define SD_CTRL_CARDCLOCKCONTROL_ENABLE_CLOCK   (1<<8) // 0x0100
++#define SD_CTRL_CARDCLOCKCONTROL_CLK_DIV_512    (1<<7) // 0x0080
++#define SD_CTRL_CARDCLOCKCONTROL_CLK_DIV_256    (1<<6) // 0x0040
++#define SD_CTRL_CARDCLOCKCONTROL_CLK_DIV_128    (1<<5) // 0x0020
++#define SD_CTRL_CARDCLOCKCONTROL_CLK_DIV_64     (1<<4) // 0x0010
++#define SD_CTRL_CARDCLOCKCONTROL_CLK_DIV_32     (1<<3) // 0x0008
++#define SD_CTRL_CARDCLOCKCONTROL_CLK_DIV_16     (1<<2) // 0x0004
++#define SD_CTRL_CARDCLOCKCONTROL_CLK_DIV_8      (1<<1) // 0x0002
++#define SD_CTRL_CARDCLOCKCONTROL_CLK_DIV_4      (1<<0) // 0x0001
++#define SD_CTRL_CARDCLOCKCONTROL_CLK_DIV_2      (0<<0) // 0x0000
++
++#define MEM_CARD_OPTION_REQUIRED                   0x000e
++#define MEM_CARD_OPTION_DATA_RESPONSE_TIMEOUT(x)   (((x)&0x0f)<<4)      /* Four bits */
++#define MEM_CARD_OPTION_C2_MODULE_NOT_PRESENT      (1<<14) // 0x4000
++#define MEM_CARD_OPTION_DATA_XFR_WIDTH_1           (1<<15) // 0x8000
++#define MEM_CARD_OPTION_DATA_XFR_WIDTH_4           (0<<15) //~0x8000
++
++#define SD_CTRL_COMMAND_INDEX(x)                   ((x)&0x3f)           /* 0=CMD0, 1=CMD1, ..., 63=CMD63 */
++#define SD_CTRL_COMMAND_TYPE_CMD                   (0 << 6)
++#define SD_CTRL_COMMAND_TYPE_ACMD                  (1 << 6)
++#define SD_CTRL_COMMAND_TYPE_AUTHENTICATION        (2 << 6)
++#define SD_CTRL_COMMAND_RESPONSE_TYPE_NORMAL       (0 << 8)
++#define SD_CTRL_COMMAND_RESPONSE_TYPE_EXT_R1       (4 << 8)
++#define SD_CTRL_COMMAND_RESPONSE_TYPE_EXT_R1B      (5 << 8)
++#define SD_CTRL_COMMAND_RESPONSE_TYPE_EXT_R2       (6 << 8)
++#define SD_CTRL_COMMAND_RESPONSE_TYPE_EXT_R3       (7 << 8)
++#define SD_CTRL_COMMAND_DATA_PRESENT               (1 << 11)
++#define SD_CTRL_COMMAND_TRANSFER_READ              (1 << 12)
++#define SD_CTRL_COMMAND_TRANSFER_WRITE             (0 << 12)
++#define SD_CTRL_COMMAND_MULTI_BLOCK                (1 << 13)
++#define SD_CTRL_COMMAND_SECURITY_CMD               (1 << 14)
++
++#define SD_CTRL_STOP_INTERNAL_ISSSUE_CMD12         (1 << 0)
++#define SD_CTRL_STOP_INTERNAL_AUTO_ISSUE_CMD12     (1 << 8)
++
++#define SD_CTRL_CARDSTATUS_RESPONSE_END            (1 << 0)
++#define SD_CTRL_CARDSTATUS_RW_END                  (1 << 2)
++#define SD_CTRL_CARDSTATUS_CARD_REMOVED_0          (1 << 3)
++#define SD_CTRL_CARDSTATUS_CARD_INSERTED_0         (1 << 4)
++#define SD_CTRL_CARDSTATUS_SIGNAL_STATE_PRESENT_0  (1 << 5)
++#define SD_CTRL_CARDSTATUS_WRITE_PROTECT           (1 << 7)
++#define SD_CTRL_CARDSTATUS_CARD_REMOVED_3          (1 << 8)
++#define SD_CTRL_CARDSTATUS_CARD_INSERTED_3         (1 << 9)
++#define SD_CTRL_CARDSTATUS_SIGNAL_STATE_PRESENT_3  (1 << 10)
++
++#define SD_CTRL_BUFFERSTATUS_CMD_INDEX_ERROR       (1 << 0) // 0x0001
++#define SD_CTRL_BUFFERSTATUS_CRC_ERROR             (1 << 1) // 0x0002
++#define SD_CTRL_BUFFERSTATUS_STOP_BIT_END_ERROR    (1 << 2) // 0x0004
++#define SD_CTRL_BUFFERSTATUS_DATA_TIMEOUT          (1 << 3) // 0x0008
++#define SD_CTRL_BUFFERSTATUS_BUFFER_OVERFLOW       (1 << 4) // 0x0010
++#define SD_CTRL_BUFFERSTATUS_BUFFER_UNDERFLOW      (1 << 5) // 0x0020
++#define SD_CTRL_BUFFERSTATUS_CMD_TIMEOUT           (1 << 6) // 0x0040
++#define SD_CTRL_BUFFERSTATUS_UNK7                  (1 << 7) // 0x0080
++#define SD_CTRL_BUFFERSTATUS_BUFFER_READ_ENABLE    (1 << 8) // 0x0100
++#define SD_CTRL_BUFFERSTATUS_BUFFER_WRITE_ENABLE   (1 << 9) // 0x0200
++#define SD_CTRL_BUFFERSTATUS_ILLEGAL_FUNCTION      (1 << 13)// 0x2000
++#define SD_CTRL_BUFFERSTATUS_CMD_BUSY              (1 << 14)// 0x4000
++#define SD_CTRL_BUFFERSTATUS_ILLEGAL_ACCESS        (1 << 15)// 0x8000
++
++#define SD_CTRL_INTMASKCARD_RESPONSE_END           (1 << 0) // 0x0001
++#define SD_CTRL_INTMASKCARD_RW_END                 (1 << 2) // 0x0004
++#define SD_CTRL_INTMASKCARD_CARD_REMOVED_0         (1 << 3) // 0x0008
++#define SD_CTRL_INTMASKCARD_CARD_INSERTED_0        (1 << 4) // 0x0010
++#define SD_CTRL_INTMASKCARD_SIGNAL_STATE_PRESENT_0 (1 << 5) // 0x0020
++#define SD_CTRL_INTMASKCARD_UNK6                   (1 << 6) // 0x0040
++#define SD_CTRL_INTMASKCARD_WRITE_PROTECT          (1 << 7) // 0x0080
++#define SD_CTRL_INTMASKCARD_CARD_REMOVED_3         (1 << 8) // 0x0100
++#define SD_CTRL_INTMASKCARD_CARD_INSERTED_3        (1 << 9) // 0x0200
++#define SD_CTRL_INTMASKCARD_SIGNAL_STATE_PRESENT_3 (1 << 10)// 0x0400
++
++#define SD_CTRL_INTMASKBUFFER_CMD_INDEX_ERROR      (1 << 0) // 0x0001
++#define SD_CTRL_INTMASKBUFFER_CRC_ERROR            (1 << 1) // 0x0002
++#define SD_CTRL_INTMASKBUFFER_STOP_BIT_END_ERROR   (1 << 2) // 0x0004
++#define SD_CTRL_INTMASKBUFFER_DATA_TIMEOUT         (1 << 3) // 0x0008
++#define SD_CTRL_INTMASKBUFFER_BUFFER_OVERFLOW      (1 << 4) // 0x0010
++#define SD_CTRL_INTMASKBUFFER_BUFFER_UNDERFLOW     (1 << 5) // 0x0020
++#define SD_CTRL_INTMASKBUFFER_CMD_TIMEOUT          (1 << 6) // 0x0040
++#define SD_CTRL_INTMASKBUFFER_UNK7                 (1 << 7) // 0x0080
++#define SD_CTRL_INTMASKBUFFER_BUFFER_READ_ENABLE   (1 << 8) // 0x0100
++#define SD_CTRL_INTMASKBUFFER_BUFFER_WRITE_ENABLE  (1 << 9) // 0x0200
++#define SD_CTRL_INTMASKBUFFER_ILLEGAL_FUNCTION     (1 << 13)// 0x2000
++#define SD_CTRL_INTMASKBUFFER_CMD_BUSY             (1 << 14)// 0x4000
++#define SD_CTRL_INTMASKBUFFER_ILLEGAL_ACCESS       (1 << 15)// 0x8000
++
++#define SD_CTRL_DETAIL0_RESPONSE_CMD_ERROR                   (1 << 0) // 0x0001
++#define SD_CTRL_DETAIL0_END_BIT_ERROR_FOR_RESPONSE_NON_CMD12 (1 << 2) // 0x0004
++#define SD_CTRL_DETAIL0_END_BIT_ERROR_FOR_RESPONSE_CMD12     (1 << 3) // 0x0008
++#define SD_CTRL_DETAIL0_END_BIT_ERROR_FOR_READ_DATA          (1 << 4) // 0x0010
++#define SD_CTRL_DETAIL0_END_BIT_ERROR_FOR_WRITE_CRC_STATUS   (1 << 5) // 0x0020
++#define SD_CTRL_DETAIL0_CRC_ERROR_FOR_RESPONSE_NON_CMD12     (1 << 8) // 0x0100
++#define SD_CTRL_DETAIL0_CRC_ERROR_FOR_RESPONSE_CMD12         (1 << 9) // 0x0200
++#define SD_CTRL_DETAIL0_CRC_ERROR_FOR_READ_DATA              (1 << 10)// 0x0400
++#define SD_CTRL_DETAIL0_CRC_ERROR_FOR_WRITE_CMD              (1 << 11)// 0x0800
++
++#define SD_CTRL_DETAIL1_NO_CMD_RESPONSE                      (1 << 0) // 0x0001
++#define SD_CTRL_DETAIL1_TIMEOUT_READ_DATA                    (1 << 4) // 0x0010
++#define SD_CTRL_DETAIL1_TIMEOUT_CRS_STATUS                   (1 << 5) // 0x0020
++#define SD_CTRL_DETAIL1_TIMEOUT_CRC_BUSY                     (1 << 6) // 0x0040
++
++#define _IPAQ_ASIC3_SDIO_CTRL_Base          0x1200
++
++#define IPAQ_ASIC3_SDIO(_b, s,x)   \
++     (*((volatile s *) ((_b) + _IPAQ_ASIC3_SDIO_CTRL_Base + (_IPAQ_ASIC3_SDIO_CTRL_ ## x))))
++
++#define _IPAQ_ASIC3_SDIO_CTRL_Cmd                  0x00
++#define _IPAQ_ASIC3_SDIO_CTRL_CardPortSel          0x04
++#define _IPAQ_ASIC3_SDIO_CTRL_Arg0                 0x08
++#define _IPAQ_ASIC3_SDIO_CTRL_Arg1                 0x0C
++#define _IPAQ_ASIC3_SDIO_CTRL_TransferBlockCount   0x14
++#define _IPAQ_ASIC3_SDIO_CTRL_Response0            0x18
++#define _IPAQ_ASIC3_SDIO_CTRL_Response1            0x1C
++#define _IPAQ_ASIC3_SDIO_CTRL_Response2            0x20
++#define _IPAQ_ASIC3_SDIO_CTRL_Response3            0x24
++#define _IPAQ_ASIC3_SDIO_CTRL_Response4            0x28
++#define _IPAQ_ASIC3_SDIO_CTRL_Response5            0x2C
++#define _IPAQ_ASIC3_SDIO_CTRL_Response6            0x30
++#define _IPAQ_ASIC3_SDIO_CTRL_Response7            0x34
++#define _IPAQ_ASIC3_SDIO_CTRL_CardStatus           0x38
++#define _IPAQ_ASIC3_SDIO_CTRL_BufferCtrl           0x3C
++#define _IPAQ_ASIC3_SDIO_CTRL_IntMaskCard          0x40
++#define _IPAQ_ASIC3_SDIO_CTRL_IntMaskBuffer        0x44
++#define _IPAQ_ASIC3_SDIO_CTRL_CardXferDataLen      0x4C
++#define _IPAQ_ASIC3_SDIO_CTRL_CardOptionSetup      0x50
++#define _IPAQ_ASIC3_SDIO_CTRL_ErrorStatus0         0x54
++#define _IPAQ_ASIC3_SDIO_CTRL_ErrorStatus1         0x58
++#define _IPAQ_ASIC3_SDIO_CTRL_DataPort             0x60
++#define _IPAQ_ASIC3_SDIO_CTRL_TransactionCtrl      0x68
++#define _IPAQ_ASIC3_SDIO_CTRL_CardIntCtrl          0x6C
++#define _IPAQ_ASIC3_SDIO_CTRL_ClocknWaitCtrl       0x70
++#define _IPAQ_ASIC3_SDIO_CTRL_HostInformation      0x74
++#define _IPAQ_ASIC3_SDIO_CTRL_ErrorCtrl            0x78
++#define _IPAQ_ASIC3_SDIO_CTRL_LEDCtrl              0x7C
++#define _IPAQ_ASIC3_SDIO_CTRL_SoftwareReset        0x1C0
++
++#define IPAQ_ASIC3_SDIO_CTRL_Cmd(_b)                  IPAQ_ASIC3_SDIO( _b, u16, Cmd )   /* */
++#define IPAQ_ASIC3_SDIO_CTRL_CardPortSel(_b)          IPAQ_ASIC3_SDIO( _b, u16, CardPortSel )   /* */
++#define IPAQ_ASIC3_SDIO_CTRL_Arg0(_b)                 IPAQ_ASIC3_SDIO( _b, u16, Arg0 )   /* */
++#define IPAQ_ASIC3_SDIO_CTRL_Arg1(_b)                 IPAQ_ASIC3_SDIO( _b, u16, Arg1 )   /* */
++#define IPAQ_ASIC3_SDIO_CTRL_TransferBlockCount(_b)   IPAQ_ASIC3_SDIO( _b, u16, TransferBlockCount )   /* */
++#define IPAQ_ASIC3_SDIO_CTRL_Response0(_b)            IPAQ_ASIC3_SDIO( _b, u16, Response0 )   /* */
++#define IPAQ_ASIC3_SDIO_CTRL_Response1(_b)            IPAQ_ASIC3_SDIO( _b, u16, Response1 )   /* */
++#define IPAQ_ASIC3_SDIO_CTRL_Response2(_b)            IPAQ_ASIC3_SDIO( _b, u16, Response2 )   /* */
++#define IPAQ_ASIC3_SDIO_CTRL_Response3(_b)            IPAQ_ASIC3_SDIO( _b, u16, Response3 )   /* */
++#define IPAQ_ASIC3_SDIO_CTRL_Response4(_b)            IPAQ_ASIC3_SDIO( _b, u16, Response4 )   /* */
++#define IPAQ_ASIC3_SDIO_CTRL_Response5(_b)            IPAQ_ASIC3_SDIO( _b, u16, Response5 )   /* */
++#define IPAQ_ASIC3_SDIO_CTRL_Response6(_b)            IPAQ_ASIC3_SDIO( _b, u16, Response6 )   /* */
++#define IPAQ_ASIC3_SDIO_CTRL_Response7(_b)            IPAQ_ASIC3_SDIO( _b, u16, Response7 )   /* */
++#define IPAQ_ASIC3_SDIO_CTRL_CardStatus(_b)           IPAQ_ASIC3_SDIO( _b, u16, CardStatus )   /* */
++#define IPAQ_ASIC3_SDIO_CTRL_BufferCtrl(_b)           IPAQ_ASIC3_SDIO( _b, u16, BufferCtrl )   /* and error status*/
++#define IPAQ_ASIC3_SDIO_CTRL_IntMaskCard(_b)          IPAQ_ASIC3_SDIO( _b, u16, IntMaskCard )   /* */
++#define IPAQ_ASIC3_SDIO_CTRL_IntMaskBuffer(_b)        IPAQ_ASIC3_SDIO( _b, u16, IntMaskBuffer )   /* */
++#define IPAQ_ASIC3_SDIO_CTRL_CardXferDataLen(_b)      IPAQ_ASIC3_SDIO( _b, u16, CardXferDataLen )   /* */
++#define IPAQ_ASIC3_SDIO_CTRL_CardOptionSetup(_b)      IPAQ_ASIC3_SDIO( _b, u16, CardOptionSetup )   /* */
++#define IPAQ_ASIC3_SDIO_CTRL_ErrorStatus0(_b)         IPAQ_ASIC3_SDIO( _b, u16, ErrorStatus0 )   /* */
++#define IPAQ_ASIC3_SDIO_CTRL_ErrorStatus1(_b)         IPAQ_ASIC3_SDIO( _b, u16, ErrorStatus1 )   /* */
++#define IPAQ_ASIC3_SDIO_CTRL_DataPort(_b)             IPAQ_ASIC3_SDIO( _b, u16, DataPort )   /* */
++#define IPAQ_ASIC3_SDIO_CTRL_TransactionCtrl(_b)      IPAQ_ASIC3_SDIO( _b, u16, TransactionCtrl )   /* */
++#define IPAQ_ASIC3_SDIO_CTRL_CardIntCtrl(_b)          IPAQ_ASIC3_SDIO( _b, u16, CardIntCtrl )   /* */
++#define IPAQ_ASIC3_SDIO_CTRL_ClocknWaitCtrl(_b)       IPAQ_ASIC3_SDIO( _b, u16, ClocknWaitCtrl )   /* */
++#define IPAQ_ASIC3_SDIO_CTRL_HostInformation(_b)      IPAQ_ASIC3_SDIO( _b, u16, HostInformation )   /* */
++#define IPAQ_ASIC3_SDIO_CTRL_ErrorCtrl(_b)            IPAQ_ASIC3_SDIO( _b, u16, ErrorCtrl )   /* */
++#define IPAQ_ASIC3_SDIO_CTRL_LEDCtrl(_b)              IPAQ_ASIC3_SDIO( _b, u16, LEDCtrl )   /* */
++#define IPAQ_ASIC3_SDIO_CTRL_SoftwareReset(_b)        IPAQ_ASIC3_SDIO( _b, u16, SoftwareReset )   /* */
++
++#define IPAQ_ASIC3_MAP_SIZE        0x2000
++
++#endif
+Index: linux-2.6.22/include/linux/backlight.h
+===================================================================
+--- linux-2.6.22.orig/include/linux/backlight.h        2007-09-11 12:53:26.000000000 +0200
++++ linux-2.6.22/include/linux/backlight.h     2007-09-11 12:53:37.000000000 +0200
+@@ -92,4 +92,11 @@
+       return dev_get_drvdata(&bl_dev->dev);
+ }
++struct generic_bl_info {
++      int max_intensity;
++      int default_intensity;
++      int limit_mask;
++      void (*set_bl_intensity)(int intensity);
++};
++
+ #endif
+Index: linux-2.6.22/include/linux/gpiodev.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/include/linux/gpiodev.h       2007-09-11 12:53:37.000000000 +0200
+@@ -0,0 +1,44 @@
++#ifndef __GPIODEV_H
++#define __GPIODEV_H
++
++#include <linux/device.h>
++#include <linux/platform_device.h>
++#include <asm/gpio.h>
++
++/* Interface */
++
++/* This structure must be first member of device platform_data structure
++   of a device which provides gpiodev interface. All method pointers
++   must be non-NULL, so stubs must be used for non-implemented ones. */
++struct gpiodev_ops {
++        int (*get)(struct device *this, unsigned gpio_no);
++        void (*set)(struct device *this, unsigned gpio_no, int val);
++        int (*to_irq)(struct device *this, unsigned gpio_no);
++};
++
++/* Generalized GPIO structure */
++
++struct gpio {
++      struct device *gpio_dev;
++      unsigned gpio_no;
++};
++
++/* API functions */
++
++static inline int gpiodev_get_value(struct gpio *gpio)
++{
++      struct gpiodev_ops *ops = gpio->gpio_dev->platform_data;
++      return ops->get(gpio->gpio_dev, gpio->gpio_no);
++}
++static inline void gpiodev_set_value(struct gpio *gpio, int val)
++{
++      struct gpiodev_ops *ops = gpio->gpio_dev->platform_data;
++      ops->set(gpio->gpio_dev, gpio->gpio_no, val);
++}
++static inline int gpiodev_to_irq(struct gpio *gpio)
++{
++      struct gpiodev_ops *ops = gpio->gpio_dev->platform_data;
++      return ops->to_irq(gpio->gpio_dev, gpio->gpio_no);
++}
++
++#endif /* __GPIODEV_H */
+Index: linux-2.6.22/include/linux/input_pda.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/include/linux/input_pda.h     2007-09-11 12:53:37.000000000 +0200
+@@ -0,0 +1,47 @@
++#ifndef _INPUT_PDA_H
++#define _INPUT_PDA_H
++
++/*
++ * This is temporary virtual button key codes map
++ * for keyboardless handheld computers.
++ * Its purpose is to provide map common to all devices
++ * and known to work with current software and its bugs
++ * and misfeatures. Once issues with the software are
++ * solved, codes from input.h will be used directly
++ * (missing key definitions will be added).
++ */
++
++/* Some directly usable keycodes:
++KEY_POWER - Power/suspend button
++KEY_ENTER - Enter/Action/Central button on joypad
++KEY_UP
++KEY_DOWN
++KEY_LEFT
++KEY_RIGHT
++*/
++
++/* XXX Instead of using any values in include/linux/input.h, we have to use
++       use values < 128 due to some munging that kdrive does to get keystrokes.
++       When kdrive gets its key events from evdev instead of the console,
++       we should be able to switch to using input.h values and get rid of
++       xmodmap. */
++
++#define _KEY_APP1     KEY_F9          // xmodmap sees 67 + 8 = 75
++#define _KEY_APP2     KEY_F10         // xmodmap 76
++#define _KEY_APP3     KEY_F11         // xmodmap 95
++#define _KEY_APP4     KEY_F12         // xmodmap 96
++
++#define _KEY_RECORD   KEY_RO
++
++/* It is highly recommended to use exactly 4 codes above for
++   4 buttons the device has. This will ensure that console and
++   framebuffer applications (e.g. games) will work ok on all
++   devices. If you'd like more distinguishable names, following
++   convenience defines are provided, suiting many devices. */
++
++#define _KEY_CALENDAR _KEY_APP1
++#define _KEY_CONTACTS _KEY_APP2
++#define _KEY_MAIL     _KEY_APP3
++#define _KEY_HOMEPAGE _KEY_APP4
++
++#endif
+Index: linux-2.6.22/include/linux/soc/asic3_base.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/include/linux/soc/asic3_base.h        2007-09-11 12:53:37.000000000 +0200
+@@ -0,0 +1,104 @@
++#include <asm/types.h>
++#include <linux/gpiodev.h>
++
++/* Private API - for ASIC3 devices internal use only */
++#define HDR_IPAQ_ASIC3_ACTION(ACTION,action,fn,FN)                  \
++u32  asic3_get_gpio_ ## action ## _ ## fn (struct device *dev);      \
++void asic3_set_gpio_ ## action ## _ ## fn (struct device *dev, u32 bits, u32 val);
++
++#define HDR_IPAQ_ASIC3_FN(fn,FN)                                      \
++      HDR_IPAQ_ASIC3_ACTION ( MASK,mask,fn,FN)                        \
++      HDR_IPAQ_ASIC3_ACTION ( DIR, dir, fn, FN)                       \
++      HDR_IPAQ_ASIC3_ACTION ( OUT, out, fn, FN)                       \
++      HDR_IPAQ_ASIC3_ACTION ( LEVELTRI, trigtype, fn, FN)             \
++      HDR_IPAQ_ASIC3_ACTION ( RISING, rising, fn, FN)                 \
++      HDR_IPAQ_ASIC3_ACTION ( LEVEL, triglevel, fn, FN)               \
++      HDR_IPAQ_ASIC3_ACTION ( SLEEP_MASK, sleepmask, fn, FN)          \
++      HDR_IPAQ_ASIC3_ACTION ( SLEEP_OUT, sleepout, fn, FN)            \
++      HDR_IPAQ_ASIC3_ACTION ( BATT_FAULT_OUT, battfaultout, fn, FN)   \
++      HDR_IPAQ_ASIC3_ACTION ( INT_STATUS, intstatus, fn, FN)          \
++      HDR_IPAQ_ASIC3_ACTION ( ALT_FUNCTION, alt_fn, fn, FN)           \
++      HDR_IPAQ_ASIC3_ACTION ( SLEEP_CONF, sleepconf, fn, FN)          \
++      HDR_IPAQ_ASIC3_ACTION ( STATUS, status, fn, FN)
++
++/* Public API */
++
++#define ASIC3_GPIOA_IRQ_BASE  0
++#define ASIC3_GPIOB_IRQ_BASE  16
++#define ASIC3_GPIOC_IRQ_BASE  32
++#define ASIC3_GPIOD_IRQ_BASE  48
++#define ASIC3_LED0_IRQ                64
++#define ASIC3_LED1_IRQ                65
++#define ASIC3_LED2_IRQ                66
++#define ASIC3_SPI_IRQ         67
++#define ASIC3_SMBUS_IRQ               68
++#define ASIC3_OWM_IRQ         69
++
++#define ASIC3_NR_GPIO_IRQS    64      /* 16 bits each GPIO A...D banks */
++#define ASIC3_NR_IRQS         (ASIC3_OWM_IRQ + 1)
++
++extern int asic3_irq_base(struct device *dev);
++
++extern void asic3_write_register(struct device *dev, unsigned int reg,
++                                 u32 value);
++extern u32  asic3_read_register(struct device *dev, unsigned int reg);
++
++/* old clock api */
++extern void asic3_set_clock_sel(struct device *dev, u32 bits, u32 val);
++extern u32  asic3_get_clock_cdex(struct device *dev);
++extern void asic3_set_clock_cdex(struct device *dev, u32 bits, u32 val);
++
++extern void asic3_set_extcf_select(struct device *dev, u32 bits, u32 val);
++extern void asic3_set_extcf_reset(struct device *dev, u32 bits, u32 val);
++extern void asic3_set_sdhwctrl(struct device *dev, u32 bits, u32 val);
++
++extern void asic3_set_led(struct device *dev, int led_num, int duty_time,
++                          int cycle_time, int timebase);
++
++extern int asic3_register_mmc(struct device *dev);
++extern int asic3_unregister_mmc(struct device *dev);
++
++/* Accessors for GPIO banks */
++HDR_IPAQ_ASIC3_FN(a, A)
++HDR_IPAQ_ASIC3_FN(b, B)
++HDR_IPAQ_ASIC3_FN(c, C)
++HDR_IPAQ_ASIC3_FN(d, D)
++
++#define _IPAQ_ASIC3_GPIO_BANK_A      0
++#define _IPAQ_ASIC3_GPIO_BANK_B      1
++#define _IPAQ_ASIC3_GPIO_BANK_C      2
++#define _IPAQ_ASIC3_GPIO_BANK_D      3
++
++#define ASIC3_GPIO_bit(gpio) (1 << (gpio & 0xf))
++
++extern int asic3_get_gpio_bit(struct device *dev, int gpio);
++extern void asic3_set_gpio_bit(struct device *dev, int gpio, int val);
++extern int asic3_gpio_get_value(struct device *dev, unsigned gpio);
++extern void asic3_gpio_set_value(struct device *dev, unsigned gpio, int val);
++
++
++struct tmio_mmc_hwconfig;
++
++struct asic3_platform_data
++{
++      // Must be first member
++      struct gpiodev_ops gpiodev_ops;
++
++      struct {
++              u32 dir;
++              u32 init;
++              u32 sleep_mask;
++              u32 sleep_out;
++              u32 batt_fault_out;
++              u32 sleep_conf;
++              u32 alt_function;
++      } gpio_a, gpio_b, gpio_c, gpio_d;
++
++      int irq_base;
++      unsigned int bus_shift;
++
++      struct platform_device **child_platform_devs;
++      int num_child_platform_devs;
++
++      struct tmio_mmc_hwconfig *tmio_mmc_hwconfig;
++};
+Index: linux-2.6.22/include/linux/soc/tmio_mmc.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/include/linux/soc/tmio_mmc.h  2007-09-11 12:53:37.000000000 +0200
+@@ -0,0 +1,17 @@
++#include <linux/platform_device.h>
++
++#define MMC_CLOCK_DISABLED 0
++#define MMC_CLOCK_ENABLED  1
++
++#define TMIO_WP_ALWAYS_RW ((void*)-1)
++
++struct tmio_mmc_hwconfig {
++      void (*hwinit)(struct platform_device *sdev);
++      void (*set_mmc_clock)(struct platform_device *sdev, int state);
++
++      /* NULL - use ASIC3 signal,
++         TMIO_WP_ALWAYS_RW - assume always R/W (e.g. miniSD)
++         otherwise - machine-specific handler */
++      int (*mmc_get_ro)(struct platform_device *pdev);
++      short address_shift;
++};
+Index: linux-2.6.22/include/asm-arm/arch-pxa/pxa-regs.h
+===================================================================
+--- linux-2.6.22.orig/include/asm-arm/arch-pxa/pxa-regs.h      2007-09-11 12:53:34.000000000 +0200
++++ linux-2.6.22/include/asm-arm/arch-pxa/pxa-regs.h   2007-09-11 12:53:37.000000000 +0200
+@@ -2043,6 +2043,8 @@
+ #define LDCMD_SOFINT  (1 << 22)
+ #define LDCMD_EOFINT  (1 << 21)
++#define LCCR4_13M_PCD_EN        (1<<25)          /* 13M PCD enable */
++#define LCCR4_PCDDIV            (1<<31)          /* PCD selection */
+ #define LCCR5_SOFM1   (1<<0)          /* Start Of Frame Mask for Overlay 1 (channel 1) */
+ #define LCCR5_SOFM2   (1<<1)          /* Start Of Frame Mask for Overlay 2 (channel 2) */
+Index: linux-2.6.22/drivers/mmc/host/Kconfig
+===================================================================
+--- linux-2.6.22.orig/drivers/mmc/host/Kconfig 2007-07-09 01:32:17.000000000 +0200
++++ linux-2.6.22/drivers/mmc/host/Kconfig      2007-09-11 12:53:37.000000000 +0200
+@@ -100,3 +100,9 @@
+           To compile this driver as a module, choose M here: the
+         module will be called tifm_sd.
++config MMC_ASIC3
++      tristate "HTC ASIC3 SD/MMC support"
++      depends on MMC && HTC_ASIC3
++      help
++        This provides support for the ASIC3 SD/MMC controller, used
++        in the iPAQ hx4700 and others.
+Index: linux-2.6.22/drivers/mmc/host/Makefile
+===================================================================
+--- linux-2.6.22.orig/drivers/mmc/host/Makefile        2007-07-09 01:32:17.000000000 +0200
++++ linux-2.6.22/drivers/mmc/host/Makefile     2007-09-11 12:53:37.000000000 +0200
+@@ -15,4 +15,4 @@
+ obj-$(CONFIG_MMC_OMAP)                += omap.o
+ obj-$(CONFIG_MMC_AT91)                += at91_mci.o
+ obj-$(CONFIG_MMC_TIFM_SD)     += tifm_sd.o
+-
++obj-$(CONFIG_MMC_ASIC3)         += asic3_mmc.o
+Index: linux-2.6.22/drivers/mmc/host/asic3_mmc.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/drivers/mmc/host/asic3_mmc.c  2007-09-11 12:53:37.000000000 +0200
+@@ -0,0 +1,900 @@
++/* Note that this driver can likely be merged into the tmio driver, so
++ * consider this code temporary.  It works, though.
++ */
++/*
++ *  linux/drivers/mmc/asic3_mmc.c
++ *
++ *  Copyright (c) 2005 SDG Systems, LLC
++ *
++ *  based on tmio_mmc.c
++ *      Copyright (C) 2004 Ian Molton
++ *
++ *  Refactored to support all ASIC3 devices, 2006 Paul Sokolovsky
++ *
++ * This program is free software; you can 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 SD / SDIO cell found in:
++ *
++ * TC6393XB
++ *
++ * This driver draws mainly on scattered spec sheets, Reverse engineering
++ * of the toshiba e800  SD driver and some parts of the 2.4 ASIC3 driver (4 bit
++ * support).
++ *
++ * Supports MMC 1 bit transfers and SD 1 and 4 bit modes.
++ *
++ * TODO:
++ *   Eliminate FIXMEs
++ *   SDIO support
++ *   Power management
++ *   Handle MMC errors (at all)
++ *
++ */
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/init.h>
++#include <linux/ioport.h>
++#include <linux/platform_device.h>
++#include <linux/interrupt.h>
++#include <linux/blkdev.h>
++#include <linux/delay.h>
++#include <linux/err.h>
++#include <linux/mmc/mmc.h>
++#include <linux/mmc/host.h>
++#include <linux/mmc/card.h>
++//#include <linux/mmc/protocol.h>
++#include <linux/mmc/sd.h>
++#include <linux/scatterlist.h>
++//#include <linux/soc-old.h>
++#include <linux/soc/asic3_base.h>
++#include <linux/soc/tmio_mmc.h>
++
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/mach/irq.h>
++#include <linux/clk.h>
++#include <asm/mach-types.h>
++
++#include <asm/hardware/ipaq-asic3.h>
++#include "asic3_mmc.h"
++
++struct asic3_mmc_host {
++    void                    *ctl_base;
++    struct device           *asic3_dev;       /* asic3 device */
++    struct tmio_mmc_hwconfig *hwconfig;       /* HW config data/handlers, guaranteed != NULL */
++    unsigned long           bus_shift;
++    struct mmc_command      *cmd;
++    struct mmc_request      *mrq;
++    struct mmc_data         *data;
++    struct mmc_host         *mmc;
++    int                     irq;
++    unsigned short          clock_for_sd;
++
++    /* I/O related stuff */
++    struct scatterlist      *sg_ptr;
++    unsigned int            sg_len;
++    unsigned int            sg_off;
++};
++
++static void
++mmc_finish_request(struct asic3_mmc_host *host)
++{
++    struct mmc_request *mrq = host->mrq;
++
++    /* Write something to end the command */
++    host->mrq  = NULL;
++    host->cmd  = NULL;
++    host->data = NULL;
++
++    mmc_request_done(host->mmc, mrq);
++}
++
++
++#define ASIC3_MMC_REG(host, block, reg) (*((volatile u16 *) ((host->ctl_base) + ((_IPAQ_ASIC3_## block ## _Base + _IPAQ_ASIC3_ ## block ## _ ## reg) >> (2 - host->bus_shift))) ))
++
++static void
++mmc_start_command(struct asic3_mmc_host *host, struct mmc_command *cmd)
++{
++    struct mmc_data *data = host->data;
++    int c                 = cmd->opcode;
++
++    DBG("\e[1;33mOpcode: %d\e[0m, base: %p\n", cmd->opcode, host->ctl_base);
++
++    if(cmd->opcode == MMC_STOP_TRANSMISSION) {
++        ASIC3_MMC_REG(host, SD_CTRL, StopInternal) = SD_CTRL_STOP_INTERNAL_ISSSUE_CMD12;
++        cmd->resp[0] = cmd->opcode;
++        cmd->resp[1] = 0;
++        cmd->resp[2] = 0;
++        cmd->resp[3] = 0;
++        cmd->resp[4] = 0;
++        return;
++    }
++
++    switch(cmd->flags & 0x1f) {
++        case MMC_RSP_NONE: c |= SD_CTRL_COMMAND_RESPONSE_TYPE_NORMAL; break;
++        case MMC_RSP_R1:   c |= SD_CTRL_COMMAND_RESPONSE_TYPE_EXT_R1;   break;
++        case MMC_RSP_R1B:  c |= SD_CTRL_COMMAND_RESPONSE_TYPE_EXT_R1B;  break;
++        case MMC_RSP_R2:   c |= SD_CTRL_COMMAND_RESPONSE_TYPE_EXT_R2;   break;
++        case MMC_RSP_R3:   c |= SD_CTRL_COMMAND_RESPONSE_TYPE_EXT_R3;   break;
++        default:
++            DBG("Unknown response type %d\n", cmd->flags & 0x1f);
++            break;
++    }
++
++    host->cmd = cmd;
++
++    if(cmd->opcode == MMC_APP_CMD) {
++        c |= APP_CMD;
++    }
++    if (cmd->opcode == MMC_GO_IDLE_STATE) {
++        c |= (3 << 8); /* This was removed from ipaq-asic3.h for some reason */
++    }
++    if(data) {
++        c |= SD_CTRL_COMMAND_DATA_PRESENT;
++        if(data->blocks > 1) {
++            ASIC3_MMC_REG(host, SD_CTRL, StopInternal) = SD_CTRL_STOP_INTERNAL_AUTO_ISSUE_CMD12;
++            c |= SD_CTRL_COMMAND_MULTI_BLOCK;
++        }
++        if(data->flags & MMC_DATA_READ) {
++            c |= SD_CTRL_COMMAND_TRANSFER_READ;
++        }
++        /* MMC_DATA_WRITE does not require a bit to be set */
++    }
++
++    /* Enable the command and data interrupts */
++    ASIC3_MMC_REG(host, SD_CTRL, IntMaskCard) = ~(
++          SD_CTRL_INTMASKCARD_RESPONSE_END
++        | SD_CTRL_INTMASKCARD_RW_END
++        | SD_CTRL_INTMASKCARD_CARD_REMOVED_0
++        | SD_CTRL_INTMASKCARD_CARD_INSERTED_0
++#if 0
++        | SD_CTRL_INTMASKCARD_CARD_REMOVED_3
++        | SD_CTRL_INTMASKCARD_CARD_INSERTED_3
++#endif
++    );
++
++    ASIC3_MMC_REG(host, SD_CTRL, IntMaskBuffer) = ~(
++          SD_CTRL_INTMASKBUFFER_UNK7
++        | SD_CTRL_INTMASKBUFFER_CMD_BUSY
++#if 0
++        | SD_CTRL_INTMASKBUFFER_CMD_INDEX_ERROR
++        | SD_CTRL_INTMASKBUFFER_CRC_ERROR
++        | SD_CTRL_INTMASKBUFFER_STOP_BIT_END_ERROR
++        | SD_CTRL_INTMASKBUFFER_DATA_TIMEOUT
++        | SD_CTRL_INTMASKBUFFER_BUFFER_OVERFLOW
++        | SD_CTRL_INTMASKBUFFER_BUFFER_UNDERFLOW
++        | SD_CTRL_INTMASKBUFFER_CMD_TIMEOUT
++        | SD_CTRL_INTMASKBUFFER_BUFFER_READ_ENABLE
++        | SD_CTRL_INTMASKBUFFER_BUFFER_WRITE_ENABLE
++        | SD_CTRL_INTMASKBUFFER_ILLEGAL_ACCESS
++#endif
++    );
++
++    /* Send the command */
++    ASIC3_MMC_REG(host, SD_CTRL, Arg1) = cmd->arg >> 16;
++    ASIC3_MMC_REG(host, SD_CTRL, Arg0) = cmd->arg & 0xffff;
++    ASIC3_MMC_REG(host, SD_CTRL, Cmd) = c;
++}
++
++/* This chip always returns (at least?) as much data as you ask for.  I'm
++ * unsure what happens if you ask for less than a block. This should be looked
++ * into to ensure that a funny length read doesnt mess up the controller data
++ * state machine.
++ *
++ * Aric: Statement above may not apply to ASIC3.
++ *
++ * FIXME - this chip cannot do 1 and 2 byte data requests in 4 bit mode
++ *
++ * Aric: Statement above may not apply to ASIC3.
++ */
++
++static struct tasklet_struct mmc_data_read_tasklet;
++
++static void
++mmc_data_transfer(unsigned long h)
++{
++    struct asic3_mmc_host *host = (struct asic3_mmc_host *)h;
++    struct mmc_data *data = host->data;
++    unsigned short *buf;
++    int count;
++    /* unsigned long flags; */
++
++    if(!data){
++        printk(KERN_WARNING DRIVER_NAME ": Spurious Data IRQ\n");
++        return;
++    }
++
++    /* local_irq_save(flags); */
++    /* buf = kmap_atomic(host->sg_ptr->page, KM_BIO_SRC_IRQ); */
++    buf = kmap(host->sg_ptr->page);
++    buf += host->sg_ptr->offset/2 + host->sg_off/2;
++
++    /*
++     * Ensure we dont read more than one block. The chip will interrupt us
++     * When the next block is available.
++     */
++    count = host->sg_ptr->length - host->sg_off;
++    if(count > data->blksz) {
++        count = data->blksz;
++    }
++
++    DBG("count: %08x, page: %p, offset: %08x flags %08x\n",
++        count, host->sg_ptr->page, host->sg_off, data->flags);
++
++    host->sg_off += count;
++
++    /* Transfer the data */
++    if(data->flags & MMC_DATA_READ) {
++        while(count > 0) {
++            /* Read two bytes from SD/MMC controller. */
++            *buf = ASIC3_MMC_REG(host, SD_CTRL, DataPort);
++            buf++;
++            count -= 2;
++        }
++      //flush_dcache_page(host->sg_ptr->page);
++    } else {
++        while(count > 0) {
++            /* Write two bytes to SD/MMC controller. */
++            ASIC3_MMC_REG(host, SD_CTRL, DataPort) = *buf;
++            buf++;
++            count -= 2;
++        }
++    }
++
++    /* kunmap_atomic(host->sg_ptr->page, KM_BIO_SRC_IRQ); */
++    kunmap(host->sg_ptr->page);
++    /* local_irq_restore(flags); */
++    if(host->sg_off == host->sg_ptr->length) {
++        host->sg_ptr++;
++        host->sg_off = 0;
++        --host->sg_len;
++    }
++
++    return;
++}
++
++static void
++mmc_data_end_irq(struct asic3_mmc_host *host)
++{
++    struct mmc_data *data = host->data;
++
++    host->data = NULL;
++
++    if(!data){
++        printk(KERN_WARNING DRIVER_NAME ": Spurious data end IRQ\n");
++        return;
++    }
++
++    if (data->error == MMC_ERR_NONE) {
++        data->bytes_xfered = data->blocks * data->blksz;
++    } else {
++        data->bytes_xfered = 0;
++    }
++
++    DBG("Completed data request\n");
++
++    ASIC3_MMC_REG(host, SD_CTRL, StopInternal) = 0;
++
++    /* Make sure read enable interrupt and write enable interrupt are disabled */
++    if(data->flags & MMC_DATA_READ) {
++        ASIC3_MMC_REG(host, SD_CTRL, IntMaskBuffer) |= SD_CTRL_INTMASKBUFFER_BUFFER_READ_ENABLE;
++    } else {
++        ASIC3_MMC_REG(host, SD_CTRL, IntMaskBuffer) |= SD_CTRL_INTMASKBUFFER_BUFFER_WRITE_ENABLE;
++    }
++
++    mmc_finish_request(host);
++}
++
++static void
++mmc_cmd_irq(struct asic3_mmc_host *host, unsigned int buffer_stat)
++{
++    struct mmc_command *cmd = host->cmd;
++    u8 *buf = (u8 *)cmd->resp;
++    u16 data;
++
++    if(!host->cmd) {
++        printk(KERN_WARNING DRIVER_NAME ": Spurious CMD irq\n");
++        return;
++    }
++
++    host->cmd = NULL;
++    if(cmd->flags & MMC_RSP_PRESENT && cmd->flags & MMC_RSP_136) {
++        /* R2 */
++        buf[12] = 0xff;
++        data = ASIC3_MMC_REG(host, SD_CTRL, Response0);
++        buf[13] = data & 0xff;
++        buf[14] = data >> 8;
++        data = ASIC3_MMC_REG(host, SD_CTRL, Response1);
++        buf[15] = data & 0xff;
++        buf[8] = data >> 8;
++        data = ASIC3_MMC_REG(host, SD_CTRL, Response2);
++        buf[9] = data & 0xff;
++        buf[10] = data >> 8;
++        data = ASIC3_MMC_REG(host, SD_CTRL, Response3);
++        buf[11] = data & 0xff;
++        buf[4] = data >> 8;
++        data = ASIC3_MMC_REG(host, SD_CTRL, Response4);
++        buf[5] = data & 0xff;
++        buf[6] = data >> 8;
++        data = ASIC3_MMC_REG(host, SD_CTRL, Response5);
++        buf[7] = data & 0xff;
++        buf[0] = data >> 8;
++        data = ASIC3_MMC_REG(host, SD_CTRL, Response6);
++        buf[1] = data & 0xff;
++        buf[2] = data >> 8;
++        data = ASIC3_MMC_REG(host, SD_CTRL, Response7);
++        buf[3] = data & 0xff;
++    } else if(cmd->flags & MMC_RSP_PRESENT) {
++        /* R1, R1B, R3 */
++        data = ASIC3_MMC_REG(host, SD_CTRL, Response0);
++        buf[0] = data & 0xff;
++        buf[1] = data >> 8;
++        data = ASIC3_MMC_REG(host, SD_CTRL, Response1);
++        buf[2] = data & 0xff;
++        buf[3] = data >> 8;
++    }
++    DBG("Response: %08x %08x %08x %08x\n", cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]);
++
++    if(buffer_stat & SD_CTRL_BUFFERSTATUS_CMD_TIMEOUT) {
++        cmd->error = MMC_ERR_TIMEOUT;
++    } else if((buffer_stat & SD_CTRL_BUFFERSTATUS_CRC_ERROR) && (cmd->flags & MMC_RSP_CRC)) {
++        cmd->error = MMC_ERR_BADCRC;
++    } else if(buffer_stat &
++                (
++                      SD_CTRL_BUFFERSTATUS_ILLEGAL_ACCESS
++                    | SD_CTRL_BUFFERSTATUS_CMD_INDEX_ERROR
++                    | SD_CTRL_BUFFERSTATUS_STOP_BIT_END_ERROR
++                    | SD_CTRL_BUFFERSTATUS_BUFFER_OVERFLOW
++                    | SD_CTRL_BUFFERSTATUS_BUFFER_UNDERFLOW
++                    | SD_CTRL_BUFFERSTATUS_DATA_TIMEOUT
++                )
++    ) {
++        DBG("Buffer status ERROR 0x%04x - inside check buffer\n", buffer_stat);
++        DBG("detail0 error status 0x%04x\n", ASIC3_MMC_REG(host, SD_CTRL, ErrorStatus0));
++        DBG("detail1 error status 0x%04x\n", ASIC3_MMC_REG(host, SD_CTRL, ErrorStatus1));
++        cmd->error = MMC_ERR_FAILED;
++    }
++
++    if(cmd->error == MMC_ERR_NONE) {
++        switch (cmd->opcode) {
++            case SD_APP_SET_BUS_WIDTH:
++                if(cmd->arg == SD_BUS_WIDTH_4) {
++                    host->clock_for_sd = SD_CTRL_CARDCLOCKCONTROL_FOR_SD_CARD;
++                    ASIC3_MMC_REG(host, SD_CTRL, MemCardOptionSetup) =
++                              MEM_CARD_OPTION_REQUIRED
++                            | MEM_CARD_OPTION_DATA_RESPONSE_TIMEOUT(14)
++                            | MEM_CARD_OPTION_C2_MODULE_NOT_PRESENT
++                            | MEM_CARD_OPTION_DATA_XFR_WIDTH_4;
++                } else {
++                    host->clock_for_sd = 0;
++                    ASIC3_MMC_REG(host, SD_CTRL, MemCardOptionSetup) =
++                              MEM_CARD_OPTION_REQUIRED
++                            | MEM_CARD_OPTION_DATA_RESPONSE_TIMEOUT(14)
++                            | MEM_CARD_OPTION_C2_MODULE_NOT_PRESENT
++                            | MEM_CARD_OPTION_DATA_XFR_WIDTH_1;
++                }
++                break;
++            case MMC_SELECT_CARD:
++                if((cmd->arg >> 16) == 0) {
++                    /* We have been deselected. */
++                    ASIC3_MMC_REG(host, SD_CTRL, MemCardOptionSetup) =
++                          MEM_CARD_OPTION_REQUIRED
++                        | MEM_CARD_OPTION_DATA_RESPONSE_TIMEOUT(14)
++                        | MEM_CARD_OPTION_C2_MODULE_NOT_PRESENT
++                        | MEM_CARD_OPTION_DATA_XFR_WIDTH_1;
++                }
++        }
++    }
++
++    /*
++     * If there is data to handle we enable data IRQs here, and we will
++     * ultimatley finish the request in the mmc_data_end_irq handler.
++     */
++    if(host->data && (cmd->error == MMC_ERR_NONE)){
++        if(host->data->flags & MMC_DATA_READ) {
++            /* Enable the read enable interrupt */
++            ASIC3_MMC_REG(host, SD_CTRL, IntMaskBuffer) &=
++                ~SD_CTRL_INTMASKBUFFER_BUFFER_READ_ENABLE;
++        } else {
++            /* Enable the write enable interrupt */
++            ASIC3_MMC_REG(host, SD_CTRL, IntMaskBuffer) &=
++                ~SD_CTRL_INTMASKBUFFER_BUFFER_WRITE_ENABLE;
++        }
++    } else {
++        /* There's no data, or we encountered an error, so finish now. */
++        mmc_finish_request(host);
++    }
++
++    return;
++}
++
++static void hwinit2_irqsafe(struct asic3_mmc_host *host);
++
++static irqreturn_t
++mmc_irq(int irq, void *irq_desc)
++{
++    struct asic3_mmc_host *host;
++    unsigned int breg, bmask, bstatus, creg, cmask, cstatus;
++
++    host = irq_desc;
++
++    /* asic3 bstatus has errors */
++    bstatus = ASIC3_MMC_REG(host, SD_CTRL, BufferCtrl);
++    bmask   = ASIC3_MMC_REG(host, SD_CTRL, IntMaskBuffer);
++    cstatus = ASIC3_MMC_REG(host, SD_CTRL, CardStatus);
++    cmask   = ASIC3_MMC_REG(host, SD_CTRL, IntMaskCard);
++    breg    = bstatus & ~bmask & ~DONT_CARE_BUFFER_BITS;
++    creg    = cstatus & ~cmask & ~DONT_CARE_CARD_BITS;
++
++    if (!breg && !creg) {
++        /* This occurs sometimes for no known reason.  It doesn't hurt
++         * anything, so I don't print it.  */
++        ASIC3_MMC_REG(host, SD_CTRL, IntMaskBuffer) &= ~breg;
++        ASIC3_MMC_REG(host, SD_CTRL, IntMaskCard) &= ~creg;
++        goto out;
++    }
++
++    while (breg || creg) {
++
++        /* XXX TODO: Need to handle errors in breg here. */
++
++        /*
++         * Card insert/remove.  The mmc controlling code is stateless.  That
++         * is, it doesn't care if it was an insert or a remove.  It treats
++         * both the same.
++         */
++        /* XXX Asic3 has _3 versions of these status bits, too, for a second slot, perhaps? */
++        if (creg & (SD_CTRL_CARDSTATUS_CARD_INSERTED_0 | SD_CTRL_CARDSTATUS_CARD_REMOVED_0)) {
++            ASIC3_MMC_REG(host, SD_CTRL, CardStatus) &=
++                ~(SD_CTRL_CARDSTATUS_CARD_REMOVED_0 | SD_CTRL_CARDSTATUS_CARD_INSERTED_0);
++            if(creg & SD_CTRL_CARDSTATUS_CARD_INSERTED_0) {
++                hwinit2_irqsafe(host);
++            }
++            mmc_detect_change(host->mmc,1);
++        }
++
++        /* Command completion */
++        if (creg & SD_CTRL_CARDSTATUS_RESPONSE_END) {
++            ASIC3_MMC_REG(host, SD_CTRL, CardStatus) &=
++                ~(SD_CTRL_CARDSTATUS_RESPONSE_END);
++            mmc_cmd_irq(host, bstatus);
++        }
++
++        /* Data transfer */
++        if (breg & (SD_CTRL_BUFFERSTATUS_BUFFER_READ_ENABLE | SD_CTRL_BUFFERSTATUS_BUFFER_WRITE_ENABLE)) {
++            ASIC3_MMC_REG(host, SD_CTRL, BufferCtrl) &=
++                ~(SD_CTRL_BUFFERSTATUS_BUFFER_WRITE_ENABLE | SD_CTRL_BUFFERSTATUS_BUFFER_READ_ENABLE);
++          tasklet_schedule(&mmc_data_read_tasklet);
++        }
++
++        /* Data transfer completion */
++        if (creg & SD_CTRL_CARDSTATUS_RW_END) {
++            ASIC3_MMC_REG(host, SD_CTRL, CardStatus) &= ~(SD_CTRL_CARDSTATUS_RW_END);
++            mmc_data_end_irq(host);
++        }
++
++        /* Check status - keep going until we've handled it all */
++        bstatus = ASIC3_MMC_REG(host, SD_CTRL, BufferCtrl);
++        bmask   = ASIC3_MMC_REG(host, SD_CTRL, IntMaskBuffer);
++        cstatus = ASIC3_MMC_REG(host, SD_CTRL, CardStatus);
++        cmask   = ASIC3_MMC_REG(host, SD_CTRL, IntMaskCard);
++        breg    = bstatus & ~bmask & ~DONT_CARE_BUFFER_BITS;
++        creg    = cstatus & ~cmask & ~DONT_CARE_CARD_BITS;
++    }
++
++out:
++    /* Ensure all interrupt sources are cleared */
++    ASIC3_MMC_REG(host, SD_CTRL, BufferCtrl) = 0;
++    ASIC3_MMC_REG(host, SD_CTRL, CardStatus) = 0;
++    return IRQ_HANDLED;
++}
++
++static void
++mmc_start_data(struct asic3_mmc_host *host, struct mmc_data *data)
++{
++    DBG("setup data transfer: blocksize %08x  nr_blocks %d, page: %08x, offset: %08x\n", data->blksz,
++        data->blocks, (int)data->sg->page, data->sg->offset);
++
++    host->sg_len = data->sg_len;
++    host->sg_ptr = data->sg;
++    host->sg_off = 0;
++    host->data   = data;
++
++    /* Set transfer length and blocksize */
++    ASIC3_MMC_REG(host, SD_CTRL, TransferSectorCount) = data->blocks;
++    ASIC3_MMC_REG(host, SD_CTRL, MemCardXferDataLen)  = data->blksz;
++}
++
++/* Process requests from the MMC layer */
++static void
++mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
++{
++    struct asic3_mmc_host *host = mmc_priv(mmc);
++
++    WARN_ON(host->mrq != NULL);
++
++    host->mrq = mrq;
++
++    /* If we're performing a data request we need to setup some
++       extra information */
++    if(mrq->data) {
++        mmc_start_data(host, mrq->data);
++    }
++
++    mmc_start_command(host, mrq->cmd);
++}
++
++/* Set MMC clock / power.
++ * Note: This controller uses a simple divider scheme therefore it cannot run
++ * a MMC card at full speed (20MHz). The max clock is 24MHz on SD, but as MMC
++ * wont run that fast, it has to be clocked at 12MHz which is the next slowest
++ * setting.  This is likely not an issue because we are doing single 16-bit
++ * writes for data I/O.
++ */
++static void
++mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
++{
++    struct asic3_mmc_host *host = mmc_priv(mmc);
++    u32 clk = 0;
++
++    DBG("clock %uHz busmode %u powermode %u Vdd %u\n",
++        ios->clock, ios->bus_mode, ios->power_mode, ios->vdd);
++
++    if (ios->clock) {
++        clk = 0x80; /* slowest by default */
++        if(ios->clock >= 24000000 / 256) clk >>= 1;
++        if(ios->clock >= 24000000 / 128) clk >>= 1;
++        if(ios->clock >= 24000000 / 64)  clk >>= 1;
++        if(ios->clock >= 24000000 / 32)  clk >>= 1;
++        if(ios->clock >= 24000000 / 16)  clk >>= 1;
++        if(ios->clock >= 24000000 / 8)   clk >>= 1;
++        if(ios->clock >= 24000000 / 4)   clk >>= 1;
++        if(ios->clock >= 24000000 / 2)   clk >>= 1;
++        if(ios->clock >= 24000000 / 1)   clk >>= 1;
++        if(clk == 0) { /* For fastest speed we disable the divider. */
++            ASIC3_MMC_REG(host, SD_CONFIG, ClockMode) = 0;
++        } else {
++            ASIC3_MMC_REG(host, SD_CONFIG, ClockMode) = 1;
++        }
++        ASIC3_MMC_REG(host, SD_CTRL, CardClockCtrl) = 0;
++        ASIC3_MMC_REG(host, SD_CTRL, CardClockCtrl) =
++              host->clock_for_sd
++            | SD_CTRL_CARDCLOCKCONTROL_ENABLE_CLOCK
++            | clk;
++        msleep(10);
++    } else {
++        ASIC3_MMC_REG(host, SD_CTRL, CardClockCtrl) = 0;
++    }
++
++    switch (ios->power_mode) {
++        case MMC_POWER_OFF:
++            ASIC3_MMC_REG(host, SD_CONFIG, SDHC_Power1) = 0;
++            msleep(1);
++            break;
++        case MMC_POWER_UP:
++            break;
++        case MMC_POWER_ON:
++            ASIC3_MMC_REG(host, SD_CONFIG, SDHC_Power1) = SD_CONFIG_POWER1_PC_33V;
++            msleep(20);
++            break;
++    }
++}
++
++static int
++mmc_get_ro(struct mmc_host *mmc)
++{
++    struct asic3_mmc_host *host = mmc_priv(mmc);
++
++    /* Call custom handler for RO status */
++    if(host->hwconfig->mmc_get_ro) {
++            /* Special case for cards w/o WP lock (like miniSD) */
++            if (host->hwconfig->mmc_get_ro == (void*)-1) {
++                  return 0;
++            } else {
++                  struct platform_device *pdev = to_platform_device(mmc_dev(mmc));
++                  return host->hwconfig->mmc_get_ro(pdev);
++            }
++    }
++
++    /* WRITE_PROTECT is active low */
++    return (ASIC3_MMC_REG(host, SD_CTRL, CardStatus) & SD_CTRL_CARDSTATUS_WRITE_PROTECT)?0:1;
++}
++
++static struct mmc_host_ops mmc_ops = {
++    .request        = mmc_request,
++    .set_ios        = mmc_set_ios,
++    .get_ro         = mmc_get_ro,
++};
++
++static void
++hwinit2_irqsafe(struct asic3_mmc_host *host)
++{
++    ASIC3_MMC_REG(host, SD_CONFIG, Addr1) = 0x0000;
++    ASIC3_MMC_REG(host, SD_CONFIG, Addr0) = 0x0800;
++
++    ASIC3_MMC_REG(host, SD_CONFIG, ClkStop) = SD_CONFIG_CLKSTOP_ENABLE_ALL;
++    ASIC3_MMC_REG(host, SD_CONFIG, SDHC_CardDetect) = 2;
++    ASIC3_MMC_REG(host, SD_CONFIG, Command) = SD_CONFIG_COMMAND_MAE;
++
++    ASIC3_MMC_REG(host, SD_CTRL, SoftwareReset) = 0; /* reset on */
++    mdelay(2);
++
++    ASIC3_MMC_REG(host, SD_CTRL, SoftwareReset) = 1; /* reset off */
++    mdelay(2);
++
++    ASIC3_MMC_REG(host, SD_CTRL, MemCardOptionSetup) =
++          MEM_CARD_OPTION_REQUIRED
++        | MEM_CARD_OPTION_DATA_RESPONSE_TIMEOUT(14)
++        | MEM_CARD_OPTION_C2_MODULE_NOT_PRESENT
++        | MEM_CARD_OPTION_DATA_XFR_WIDTH_1
++        ;
++    host->clock_for_sd = 0;
++
++    ASIC3_MMC_REG(host, SD_CTRL, CardClockCtrl) = 0;
++    ASIC3_MMC_REG(host, SD_CTRL, CardStatus) = 0;
++    ASIC3_MMC_REG(host, SD_CTRL, BufferCtrl) = 0;
++    ASIC3_MMC_REG(host, SD_CTRL, ErrorStatus0) = 0;
++    ASIC3_MMC_REG(host, SD_CTRL, ErrorStatus1) = 0;
++    ASIC3_MMC_REG(host, SD_CTRL, StopInternal) = 0;
++
++    ASIC3_MMC_REG(host, SDIO_CTRL, ClocknWaitCtrl) = 0x100;
++    /* *((unsigned short *)(((char *)host->ctl_base) + 0x938)) = 0x100; */
++
++    ASIC3_MMC_REG(host, SD_CONFIG, ClockMode) = 0;
++    ASIC3_MMC_REG(host, SD_CTRL, CardClockCtrl) = 0;
++
++    mdelay(1);
++
++
++    ASIC3_MMC_REG(host, SD_CTRL, IntMaskCard) = ~(
++          SD_CTRL_INTMASKCARD_RESPONSE_END
++        | SD_CTRL_INTMASKCARD_RW_END
++        | SD_CTRL_INTMASKCARD_CARD_REMOVED_0
++        | SD_CTRL_INTMASKCARD_CARD_INSERTED_0
++#if 0
++        | SD_CTRL_INTMASKCARD_CARD_REMOVED_3
++        | SD_CTRL_INTMASKCARD_CARD_INSERTED_3
++#endif
++        )
++        ; /* check */
++    ASIC3_MMC_REG(host, SD_CTRL, IntMaskBuffer) = 0xffff;  /* IRQs off */
++
++    /*
++     * ASIC3_MMC_REG(host, SD_CTRL, TransactionCtrl) = SD_CTRL_TRANSACTIONCONTROL_SET;
++     *   Wince has 0x1000
++     */
++    /* ASIC3_MMC_REG(host, SD_CTRL, TransactionCtrl) = 0x1000; */
++
++
++    asic3_set_sdhwctrl(host->asic3_dev, ASIC3_SDHWCTRL_SDPWR, ASIC3_SDHWCTRL_SDPWR); /* turn on power at controller(?) */
++
++}
++
++static void
++hwinit(struct asic3_mmc_host *host, struct platform_device *pdev)
++{
++    /* Call custom handler for enabling clock (if needed) */
++    if(host->hwconfig->set_mmc_clock)
++            host->hwconfig->set_mmc_clock(pdev, MMC_CLOCK_ENABLED);
++
++    /* Not sure if it must be done bit by bit, but leaving as-is */
++    asic3_set_sdhwctrl(host->asic3_dev, ASIC3_SDHWCTRL_LEVCD, ASIC3_SDHWCTRL_LEVCD);
++    asic3_set_sdhwctrl(host->asic3_dev, ASIC3_SDHWCTRL_LEVWP, ASIC3_SDHWCTRL_LEVWP);
++    asic3_set_sdhwctrl(host->asic3_dev, ASIC3_SDHWCTRL_SUSPEND, 0);
++    asic3_set_sdhwctrl(host->asic3_dev, ASIC3_SDHWCTRL_PCLR, 0);
++
++    asic3_set_clock_cdex (host->asic3_dev,
++        CLOCK_CDEX_EX1 | CLOCK_CDEX_EX0, CLOCK_CDEX_EX1 | CLOCK_CDEX_EX0);
++    msleep(1);
++
++    asic3_set_clock_sel (host->asic3_dev,
++        CLOCK_SEL_SD_HCLK_SEL | CLOCK_SEL_SD_BCLK_SEL,
++      CLOCK_SEL_SD_HCLK_SEL | 0);     /* ? */
++
++    asic3_set_clock_cdex (host->asic3_dev,
++        CLOCK_CDEX_SD_HOST | CLOCK_CDEX_SD_BUS,
++      CLOCK_CDEX_SD_HOST | CLOCK_CDEX_SD_BUS);
++    msleep(1);
++
++    asic3_set_extcf_select(host->asic3_dev, ASIC3_EXTCF_SD_MEM_ENABLE, ASIC3_EXTCF_SD_MEM_ENABLE);
++
++    /* Long Delay */
++    if( !machine_is_h4700())
++        msleep(500);
++
++    hwinit2_irqsafe(host);
++}
++
++#ifdef CONFIG_PM
++static int
++mmc_suspend(struct platform_device *pdev, pm_message_t state)
++{
++    struct mmc_host *mmc = platform_get_drvdata(pdev);
++    struct asic3_mmc_host *host = mmc_priv(mmc);
++    int ret;
++
++    ret = mmc_suspend_host(mmc, state);
++
++    if (ret) {
++      printk(KERN_ERR DRIVER_NAME ": Could not suspend MMC host, hardware not suspended");
++      return ret;
++    }
++
++    /* disable the card insert / remove interrupt while sleeping */
++    ASIC3_MMC_REG(host, SD_CTRL, IntMaskCard) = ~(
++          SD_CTRL_INTMASKCARD_RESPONSE_END
++        | SD_CTRL_INTMASKCARD_RW_END);
++
++    /* disable clock */
++    ASIC3_MMC_REG(host, SD_CTRL, CardClockCtrl) = 0;
++    ASIC3_MMC_REG(host, SD_CONFIG, ClkStop) = 0;
++
++    /* power down */
++    ASIC3_MMC_REG(host, SD_CONFIG, SDHC_Power1) = 0;
++
++    asic3_set_clock_cdex (host->asic3_dev,
++        CLOCK_CDEX_SD_HOST | CLOCK_CDEX_SD_BUS, 0);
++
++    /* disable core clock */
++    if(host->hwconfig->set_mmc_clock)
++        host->hwconfig->set_mmc_clock(pdev, MMC_CLOCK_DISABLED);
++
++    /* Put in suspend mode */
++    asic3_set_sdhwctrl(host->asic3_dev, ASIC3_SDHWCTRL_SUSPEND, ASIC3_SDHWCTRL_SUSPEND);
++    return 0;
++}
++
++static int
++mmc_resume(struct platform_device *pdev)
++{
++    struct mmc_host *mmc = platform_get_drvdata(pdev);
++    struct asic3_mmc_host *host = mmc_priv(mmc);
++
++    printk(KERN_INFO "%s: starting resume\n", DRIVER_NAME);
++
++    asic3_set_sdhwctrl(host->asic3_dev, ASIC3_SDHWCTRL_SUSPEND, 0);
++    hwinit(host, pdev);
++
++    /* re-enable card remove / insert interrupt */
++    ASIC3_MMC_REG(host, SD_CTRL, IntMaskCard) = ~(
++          SD_CTRL_INTMASKCARD_RESPONSE_END
++        | SD_CTRL_INTMASKCARD_RW_END
++        | SD_CTRL_INTMASKCARD_CARD_REMOVED_0
++        | SD_CTRL_INTMASKCARD_CARD_INSERTED_0 );
++
++    mmc_resume_host(mmc);
++
++    printk(KERN_INFO "%s: finished resume\n", DRIVER_NAME);
++    return 0;
++}
++#endif
++
++static int
++mmc_probe(struct platform_device *pdev)
++{
++    struct mmc_host *mmc;
++    struct asic3_mmc_host *host = NULL;
++    int retval = 0;
++    struct tmio_mmc_hwconfig *mmc_config = (struct tmio_mmc_hwconfig *)pdev->dev.platform_data;
++
++    /* bus_shift is mandatory */
++    if (!mmc_config) {
++        printk(KERN_ERR DRIVER_NAME ": Invalid configuration\n");
++      return -EINVAL;
++    }
++
++    mmc = mmc_alloc_host(sizeof(struct asic3_mmc_host) + 128, &pdev->dev);
++    if (!mmc) {
++        retval = -ENOMEM;
++        goto exceptional_return;
++    }
++
++    host = mmc_priv(mmc);
++    host->mmc = mmc;
++    platform_set_drvdata(pdev, mmc);
++
++    host->ctl_base = 0;
++    host->hwconfig = mmc_config;
++    host->bus_shift = mmc_config->address_shift;
++    host->asic3_dev = pdev->dev.parent;
++    host->clock_for_sd = 0;
++
++    tasklet_init(&mmc_data_read_tasklet, mmc_data_transfer, (unsigned long)host);
++
++    host->ctl_base = ioremap_nocache ((unsigned long)pdev->resource[0].start, pdev->resource[0].end - pdev->resource[0].start);
++    if(!host->ctl_base){
++      printk(KERN_ERR DRIVER_NAME ": Could not map ASIC3 SD controller\n");
++        retval = -ENODEV;
++        goto exceptional_return;
++    }
++
++    printk(DRIVER_NAME ": ASIC3 MMC/SD Driver, controller at 0x%lx\n", (unsigned long)pdev->resource[0].start);
++
++    mmc->ops = &mmc_ops;
++    mmc->caps = MMC_CAP_4_BIT_DATA;
++    mmc->f_min = 46875; /* ARIC: not sure what these should be */
++    mmc->f_max = 24000000; /* ARIC: not sure what these should be */
++    mmc->ocr_avail = MMC_VDD_32_33;
++
++    hwinit(host, pdev);
++
++
++    host->irq = pdev->resource[1].start;
++
++    retval = request_irq(host->irq, mmc_irq, 0, DRIVER_NAME, host);
++    if(retval) {
++        printk(KERN_ERR DRIVER_NAME ": Unable to get interrupt\n");
++        retval = -ENODEV;
++        goto exceptional_return;
++    }
++    set_irq_type(host->irq, IRQT_FALLING);
++
++    mmc_add_host(mmc);
++
++#ifdef CONFIG_PM
++    // resume_timer.function = resume_timer_callback;
++    // resume_timer.data = 0;
++    // init_timer(&resume_timer);
++#endif
++
++    return 0;
++
++exceptional_return:
++    if (mmc) {
++        mmc_free_host(mmc);
++    }
++    if(host && host->ctl_base) iounmap(host->ctl_base);
++    return retval;
++}
++
++static int
++mmc_remove(struct platform_device *pdev)
++{
++    struct mmc_host *mmc = platform_get_drvdata(pdev);
++
++    platform_set_drvdata(pdev, NULL);
++
++    if (mmc) {
++        struct asic3_mmc_host *host = mmc_priv(mmc);
++        mmc_remove_host(mmc);
++        free_irq(host->irq, host);
++        /* FIXME - we might want to consider stopping the chip here... */
++        iounmap(host->ctl_base);
++        mmc_free_host(mmc); /* FIXME - why does this call hang? */
++    }
++    return 0;
++}
++
++/* ------------------- device registration ----------------------- */
++
++static struct platform_driver mmc_asic3_driver = {
++    .driver = {
++      .name    = DRIVER_NAME,
++    },
++    .probe   = mmc_probe,
++    .remove  = mmc_remove,
++#ifdef CONFIG_PM
++    .suspend = mmc_suspend,
++    .resume  = mmc_resume,
++#endif
++};
++
++static int __init mmc_init(void)
++{
++    return platform_driver_register(&mmc_asic3_driver);
++}
++
++static void __exit mmc_exit(void)
++{
++    platform_driver_unregister(&mmc_asic3_driver);
++}
++
++late_initcall(mmc_init);
++module_exit(mmc_exit);
++
++MODULE_DESCRIPTION("HTC ASIC3 SD/MMC driver");
++MODULE_AUTHOR("Aric Blumer, SDG Systems, LLC");
++MODULE_LICENSE("GPL");
++
+Index: linux-2.6.22/drivers/mmc/host/asic3_mmc.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/drivers/mmc/host/asic3_mmc.h  2007-09-11 12:53:37.000000000 +0200
+@@ -0,0 +1,25 @@
++#ifndef __ASIC3_MMC_H
++#define __ASIC3_MMC_H
++
++#define DRIVER_NAME   "asic3_mmc"
++
++#ifdef CONFIG_MMC_DEBUG
++#define DBG(x...)       printk(DRIVER_NAME ": " x)
++#else
++#define DBG(x...)       do { } while (0)
++#endif
++
++/* Response types */
++#define APP_CMD        0x0040
++
++#define SD_CONFIG_CLKSTOP_ENABLE_ALL 0x1f
++
++#define DONT_CARE_CARD_BITS ( \
++      SD_CTRL_INTMASKCARD_SIGNAL_STATE_PRESENT_3 \
++    | SD_CTRL_INTMASKCARD_WRITE_PROTECT \
++    | SD_CTRL_INTMASKCARD_UNK6 \
++    | SD_CTRL_INTMASKCARD_SIGNAL_STATE_PRESENT_0 \
++  )
++#define DONT_CARE_BUFFER_BITS ( SD_CTRL_INTMASKBUFFER_UNK7 | SD_CTRL_INTMASKBUFFER_CMD_BUSY )
++
++#endif // __ASIC3_MMC_H
+Index: linux-2.6.22/drivers/input/keyboard/Makefile
+===================================================================
+--- linux-2.6.22.orig/drivers/input/keyboard/Makefile  2007-07-09 01:32:17.000000000 +0200
++++ linux-2.6.22/drivers/input/keyboard/Makefile       2007-09-11 12:53:37.000000000 +0200
+@@ -21,4 +21,4 @@
+ obj-$(CONFIG_KEYBOARD_PXA27x)         += pxa27x_keyboard.o
+ obj-$(CONFIG_KEYBOARD_AAED2000)               += aaed2000_kbd.o
+ obj-$(CONFIG_KEYBOARD_GPIO)           += gpio_keys.o
+-
++obj-$(CONFIG_KEYBOARD_ASIC3)          += asic3_keys.o
+Index: linux-2.6.22/drivers/input/keyboard/asic3_keys.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/drivers/input/keyboard/asic3_keys.c   2007-09-11 12:53:37.000000000 +0200
+@@ -0,0 +1,131 @@
++/*
++ * Generic buttons driver for ASIC3 SoC.
++ *
++ * 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 Joshua Wise
++ * Copyright (C) 2005 Pawel Kolodziejski
++ * Copyright (C) 2006 Paul Sokolovsky
++ *
++ */
++
++#include <linux/input.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <linux/platform_device.h>
++#include <linux/irq.h>
++#include <linux/soc/asic3_base.h>
++#include <asm/mach/arch.h>
++#include <asm/mach/map.h>
++#include <asm/arch/irqs.h>
++#include <asm/hardware.h>
++#include <asm/hardware/ipaq-asic3.h>
++#include <asm/hardware/asic3_keys.h>
++
++static irqreturn_t asic3_keys_asic_handle(int irq, void *data)
++{
++      struct asic3_keys_platform_data *pdata = data;
++      int i, base_irq;
++
++      base_irq = asic3_irq_base(pdata->asic3_dev);
++      for (i = 0; i < pdata->nbuttons; i++) {
++              struct asic3_keys_button *b = &pdata->buttons[i];
++              if ((base_irq + b->gpio) == irq) {
++                      int state = !!asic3_gpio_get_value(pdata->asic3_dev, b->gpio);
++
++                      if (pdata->buttons[i].type == EV_SW)
++                              input_report_switch(pdata->input, pdata->buttons[i].keycode, state ^ b->active_low);
++                      else
++                              input_report_key(pdata->input, b->keycode, state ^ b->active_low);
++                      input_sync(pdata->input);
++              }
++      }
++
++      return IRQ_HANDLED;
++}
++
++static int __devinit asic3_keys_probe(struct platform_device *pdev)
++{
++      struct asic3_keys_platform_data *pdata = pdev->dev.platform_data;
++      int i, base_irq;
++      int j, ret;
++
++      pdata->input = input_allocate_device();
++
++      base_irq = asic3_irq_base(pdata->asic3_dev);
++
++      for (i = 0; i < pdata->nbuttons; i++) {
++              struct asic3_keys_button *b = &pdata->buttons[i];
++              set_bit(b->keycode, pdata->input->keybit);
++                ret=request_irq(base_irq + b->gpio, asic3_keys_asic_handle, SA_SAMPLE_RANDOM, b->desc, pdata);
++                if (ret)
++                {
++                 printk(KERN_NOTICE "Failed to allocate asic3_keys irq=%d.\n",b->gpio);
++
++                 for(j=0; j<i ; j++)
++                  free_irq(base_irq + pdata->buttons[i].gpio, NULL);
++
++                 input_unregister_device (pdata->input);
++
++                 return -ENODEV;
++                }
++
++              set_irq_type(base_irq + b->gpio, IRQT_BOTHEDGE);
++              if (pdata->buttons[i].type == EV_SW) {
++                      pdata->input->evbit[0] |= BIT(EV_SW);
++                      set_bit(b->keycode, pdata->input->swbit);
++              } else {
++                      pdata->input->evbit[0] |= BIT(EV_KEY);
++                      set_bit(b->keycode, pdata->input->keybit);
++              }
++      }
++
++      pdata->input->name = pdev->name;
++      input_register_device(pdata->input);
++
++      return 0;
++}
++
++static int __devexit asic3_keys_remove(struct platform_device *pdev)
++{
++      struct asic3_keys_platform_data *pdata = pdev->dev.platform_data;
++      int i, base_irq;
++
++      base_irq = asic3_irq_base(pdata->asic3_dev);
++      for (i = 0; i < pdata->nbuttons; i++) {
++              free_irq(base_irq + pdata->buttons[i].gpio, NULL);
++      }
++
++      input_unregister_device(pdata->input);
++
++      return 0;
++}
++
++
++static struct platform_driver asic3_keys_driver = {
++      .probe          = asic3_keys_probe,
++        .remove         = __devexit_p(asic3_keys_remove),
++      .driver         = {
++          .name       = "asic3-keys",
++      },
++};
++
++static int __init asic3_keys_init(void)
++{
++      return platform_driver_register(&asic3_keys_driver);
++}
++
++static void __exit asic3_keys_exit(void)
++{
++      platform_driver_unregister(&asic3_keys_driver);
++}
++
++module_init(asic3_keys_init);
++module_exit(asic3_keys_exit);
++
++MODULE_AUTHOR("Joshua Wise, Pawel Kolodziejski, Paul Sokolovsky");
++MODULE_DESCRIPTION("Buttons driver for HTC ASIC3 SoC");
++MODULE_LICENSE("GPL");
+Index: linux-2.6.22/include/asm-arm/arch-pxa/irqs.h
+===================================================================
+--- linux-2.6.22.orig/include/asm-arm/arch-pxa/irqs.h  2007-09-11 12:53:24.000000000 +0200
++++ linux-2.6.22/include/asm-arm/arch-pxa/irqs.h       2007-09-11 12:53:37.000000000 +0200
+@@ -172,6 +172,8 @@
+       defined(CONFIG_MACH_LOGICPD_PXA270) || \
+       defined(CONFIG_MACH_MAINSTONE)
+ #define NR_IRQS                       (IRQ_BOARD_END)
++#elif defined(CONFIG_MACH_HTCUNIVERSAL)
++#define NR_IRQS                       (IRQ_BOARD_START + 96)
+ #else
+ #define NR_IRQS                       (IRQ_BOARD_START)
+ #endif
+Index: linux-2.6.22/include/linux/ioport.h
+===================================================================
+--- linux-2.6.22.orig/include/linux/ioport.h   2007-07-09 01:32:17.000000000 +0200
++++ linux-2.6.22/include/linux/ioport.h        2007-09-11 12:53:37.000000000 +0200
+@@ -56,6 +56,7 @@
+ #define IORESOURCE_IRQ_HIGHLEVEL      (1<<2)
+ #define IORESOURCE_IRQ_LOWLEVEL               (1<<3)
+ #define IORESOURCE_IRQ_SHAREABLE      (1<<4)
++#define IORESOURCE_IRQ_SOC_SUBDEVICE    (1<<5)
+ /* ISA PnP DMA specific bits (IORESOURCE_BITS) */
+ #define IORESOURCE_DMA_TYPE_MASK      (3<<0)
+Index: linux-2.6.22/drivers/video/backlight/Kconfig
+===================================================================
+--- linux-2.6.22.orig/drivers/video/backlight/Kconfig  2007-09-11 12:53:30.000000000 +0200
++++ linux-2.6.22/drivers/video/backlight/Kconfig       2007-09-11 12:53:37.000000000 +0200
+@@ -40,7 +40,7 @@
+ config BACKLIGHT_CORGI
+       tristate "Sharp Corgi Backlight Driver (SL Series)"
+-      depends on BACKLIGHT_CLASS_DEVICE && PXA_SHARPSL
++      depends on BACKLIGHT_CLASS_DEVICE
+       default y
+       help
+         If you have a Sharp Zaurus SL-C7xx, SL-Cxx00 or SL-6000x say y to enable the
+Index: linux-2.6.22/drivers/video/backlight/corgi_bl.c
+===================================================================
+--- linux-2.6.22.orig/drivers/video/backlight/corgi_bl.c       2007-07-09 01:32:17.000000000 +0200
++++ linux-2.6.22/drivers/video/backlight/corgi_bl.c    2007-09-11 12:53:37.000000000 +0200
+@@ -24,7 +24,7 @@
+ static int corgibl_intensity;
+ static struct backlight_properties corgibl_data;
+ static struct backlight_device *corgi_backlight_device;
+-static struct corgibl_machinfo *bl_machinfo;
++static struct generic_bl_info *bl_machinfo;
+ static unsigned long corgibl_flags;
+ #define CORGIBL_SUSPENDED     0x01
+@@ -107,7 +107,7 @@
+ static int corgibl_probe(struct platform_device *pdev)
+ {
+-      struct corgibl_machinfo *machinfo = pdev->dev.platform_data;
++      struct generic_bl_info *machinfo = pdev->dev.platform_data;
+       bl_machinfo = machinfo;
+       if (!machinfo->limit_mask)
+Index: linux-2.6.22/arch/arm/mach-pxa/corgi.c
+===================================================================
+--- linux-2.6.22.orig/arch/arm/mach-pxa/corgi.c        2007-09-11 12:53:32.000000000 +0200
++++ linux-2.6.22/arch/arm/mach-pxa/corgi.c     2007-09-11 12:53:37.000000000 +0200
+@@ -20,6 +20,7 @@
+ #include <linux/interrupt.h>
+ #include <linux/mmc/host.h>
+ #include <linux/pm.h>
++#include <linux/backlight.h>
+ #include <asm/setup.h>
+ #include <asm/memory.h>
+@@ -143,7 +144,7 @@
+ /*
+  * Corgi Backlight Device
+  */
+-static struct corgibl_machinfo corgi_bl_machinfo = {
++static struct generic_bl_info corgi_bl_machinfo = {
+       .max_intensity = 0x2f,
+       .default_intensity = 0x1f,
+       .limit_mask = 0x0b,
+Index: linux-2.6.22/arch/arm/mach-pxa/spitz.c
+===================================================================
+--- linux-2.6.22.orig/arch/arm/mach-pxa/spitz.c        2007-09-11 12:53:33.000000000 +0200
++++ linux-2.6.22/arch/arm/mach-pxa/spitz.c     2007-09-11 12:53:37.000000000 +0200
+@@ -222,7 +222,7 @@
+ /*
+  * Spitz Backlight Device
+  */
+-static struct corgibl_machinfo spitz_bl_machinfo = {
++static struct generic_bl_info spitz_bl_machinfo = {
+       .default_intensity = 0x1f,
+       .limit_mask = 0x0b,
+       .max_intensity = 0x2f,
+Index: linux-2.6.22/include/asm-arm/arch-pxa/serial.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/include/asm-arm/arch-pxa/serial.h     2007-09-11 12:53:37.000000000 +0200
+@@ -0,0 +1,78 @@
++/*
++ *  linux/include/asm-arm/arch-pxa/serial.h
++ *
++ * Author:    Nicolas Pitre
++ * Copyright: (C) 2001 MontaVista Software Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <asm/arch/pxa-regs.h>
++
++#define BAUD_BASE     921600
++
++/* Standard COM flags */
++#define STD_COM_FLAGS (ASYNC_SKIP_TEST)
++
++#define STD_SERIAL_PORT_DEFNS \
++      {       \
++              type:                   PORT_PXA,       \
++              xmit_fifo_size:         64,             \
++              baud_base:              BAUD_BASE,      \
++              iomem_base:             &FFUART,        \
++              iomem_reg_shift:        2,              \
++              io_type:                SERIAL_IO_MEM,  \
++              irq:                    IRQ_FFUART,     \
++              flags:                  STD_COM_FLAGS,  \
++      }, {    \
++              type:                   PORT_PXA,       \
++              xmit_fifo_size:         64,             \
++              baud_base:              BAUD_BASE,      \
++              iomem_base:             &STUART,        \
++              iomem_reg_shift:        2,              \
++              io_type:                SERIAL_IO_MEM,  \
++              irq:                    IRQ_STUART,     \
++              flags:                  STD_COM_FLAGS,  \
++      }, {    \
++              type:                   PORT_PXA,       \
++              xmit_fifo_size:         64,             \
++              baud_base:              BAUD_BASE,      \
++              iomem_base:             &BTUART,        \
++              iomem_reg_shift:        2,              \
++              io_type:                SERIAL_IO_MEM,  \
++              irq:                    IRQ_BTUART,     \
++              flags:                  STD_COM_FLAGS,  \
++      }
++
++#define EXTRA_SERIAL_PORT_DEFNS
++
++struct platform_pxa_serial_funcs {
++
++      /* Initialize whatever is connected to this serial port. */
++      void (*configure)(int state);
++#define PXA_UART_CFG_PRE_STARTUP   0
++#define PXA_UART_CFG_POST_STARTUP  1
++#define PXA_UART_CFG_PRE_SHUTDOWN  2
++#define PXA_UART_CFG_POST_SHUTDOWN 3
++
++      /* Enable or disable the individual transmitter/receiver submodules.
++       * On transceivers without echo cancellation (e.g. SIR)
++       * transmitter always has priority; e.g. if both bits are set,
++       * only the transmitter is enabled. */
++        void (*set_txrx)(int txrx);
++#define PXA_SERIAL_TX 1
++#define PXA_SERIAL_RX 2
++
++      /* Get the current state of tx/rx. */
++      int (*get_txrx)(void);
++
++      int (*suspend)(struct platform_device *dev, pm_message_t state);
++      int (*resume)(struct platform_device *dev);
++};
++
++void pxa_set_ffuart_info(struct platform_pxa_serial_funcs *ffuart_funcs);
++void pxa_set_btuart_info(struct platform_pxa_serial_funcs *btuart_funcs);
++void pxa_set_stuart_info(struct platform_pxa_serial_funcs *stuart_funcs);
++void pxa_set_hwuart_info(struct platform_pxa_serial_funcs *hwuart_funcs);
+Index: linux-2.6.22/drivers/serial/pxa.c
+===================================================================
+--- linux-2.6.22.orig/drivers/serial/pxa.c     2007-07-09 01:32:17.000000000 +0200
++++ linux-2.6.22/drivers/serial/pxa.c  2007-09-11 12:53:37.000000000 +0200
+@@ -46,6 +46,7 @@
+ #include <asm/io.h>
+ #include <asm/hardware.h>
+ #include <asm/irq.h>
++#include <asm/arch/serial.h>
+ #include <asm/arch/pxa-regs.h>
+@@ -59,6 +60,14 @@
+       char                    *name;
+ };
++
++#define IS_METHOD(dev, method) (dev && (dev)->platform_data && ((struct platform_pxa_serial_funcs *)(dev)->platform_data)->method)
++#define METHOD_CALL(dev, method) \
++              ((struct platform_pxa_serial_funcs *)(dev)->platform_data)->method()
++#define SAFE_METHOD_CALL(dev, method, args...) \
++      if (IS_METHOD(dev, method)) \
++              ((struct platform_pxa_serial_funcs *)(dev)->platform_data)->method(args)
++
+ static inline unsigned int serial_in(struct uart_pxa_port *up, int offset)
+ {
+       offset <<= 2;
+@@ -346,6 +355,9 @@
+       unsigned long flags;
+       int retval;
++      /* Perform platform-specific port initialization, if needed. */
++      SAFE_METHOD_CALL(port->dev, configure, PXA_UART_CFG_PRE_STARTUP);
++
+       if (port->line == 3) /* HWUART */
+               up->mcr |= UART_MCR_AFE;
+       else
+@@ -401,6 +413,12 @@
+       (void) serial_in(up, UART_IIR);
+       (void) serial_in(up, UART_MSR);
++      /*
++       * Perform platform-specific port initialization if needed
++       */
++      SAFE_METHOD_CALL(port->dev, configure, PXA_UART_CFG_POST_STARTUP);
++      SAFE_METHOD_CALL(port->dev, set_txrx, PXA_SERIAL_RX);
++
+       return 0;
+ }
+@@ -409,6 +427,8 @@
+       struct uart_pxa_port *up = (struct uart_pxa_port *)port;
+       unsigned long flags;
++      SAFE_METHOD_CALL(port->dev, configure, PXA_UART_CFG_PRE_SHUTDOWN);
++
+       free_irq(up->port.irq, up);
+       /*
+@@ -430,6 +450,8 @@
+                                 UART_FCR_CLEAR_RCVR |
+                                 UART_FCR_CLEAR_XMIT);
+       serial_out(up, UART_FCR, 0);
++
++      SAFE_METHOD_CALL(port->dev, configure, PXA_UART_CFG_POST_SHUTDOWN);
+ }
+ static void
+Index: linux-2.6.22/arch/arm/mach-pxa/generic.c
+===================================================================
+--- linux-2.6.22.orig/arch/arm/mach-pxa/generic.c      2007-09-11 12:53:11.000000000 +0200
++++ linux-2.6.22/arch/arm/mach-pxa/generic.c   2007-09-11 12:53:37.000000000 +0200
+@@ -42,6 +42,7 @@
+ #include <asm/arch/mmc.h>
+ #include <asm/arch/irda.h>
+ #include <asm/arch/i2c.h>
++#include <asm/arch/serial.h>
+ #include "devices.h"
+ #include "generic.h"
+@@ -346,6 +347,18 @@
+       .id             = 3,
+ };
++void __init pxa_set_ffuart_info(struct platform_pxa_serial_funcs *info)
++{
++      pxa_device_ffuart.dev.platform_data = info;
++}
++EXPORT_SYMBOL(pxa_set_ffuart_info);
++
++void __init pxa_set_btuart_info(struct platform_pxa_serial_funcs *info)
++{
++      pxa_device_btuart.dev.platform_data = info;
++}
++EXPORT_SYMBOL(pxa_set_btuart_info);
++
+ static struct resource pxai2c_resources[] = {
+       {
+               .start  = 0x40301680,
+Index: linux-2.6.22/drivers/leds/Makefile
+===================================================================
+--- linux-2.6.22.orig/drivers/leds/Makefile    2007-09-11 12:53:14.000000000 +0200
++++ linux-2.6.22/drivers/leds/Makefile 2007-09-11 12:53:37.000000000 +0200
+@@ -16,6 +16,7 @@
+ obj-$(CONFIG_LEDS_WRAP)                       += leds-wrap.o
+ obj-$(CONFIG_LEDS_H1940)              += leds-h1940.o
+ obj-$(CONFIG_LEDS_COBALT)             += leds-cobalt.o
++obj-$(CONFIG_LEDS_ASIC3)                += leds-asic3.o
+ obj-$(CONFIG_LEDS_GPIO)                       += leds-gpio.o
+ # LED Triggers
+Index: linux-2.6.22/arch/arm/Kconfig
+===================================================================
+--- linux-2.6.22.orig/arch/arm/Kconfig 2007-09-11 12:53:32.000000000 +0200
++++ linux-2.6.22/arch/arm/Kconfig      2007-09-11 12:53:37.000000000 +0200
+@@ -1032,6 +1032,8 @@
+ source "drivers/w1/Kconfig"
++source "drivers/power/Kconfig"
++
+ source "drivers/hwmon/Kconfig"
+ #source "drivers/l3/Kconfig"
+Index: linux-2.6.22/drivers/input/keyboard/Kconfig
+===================================================================
+--- linux-2.6.22.orig/drivers/input/keyboard/Kconfig   2007-09-11 14:28:45.000000000 +0200
++++ linux-2.6.22/drivers/input/keyboard/Kconfig        2007-09-11 14:29:05.000000000 +0200
+@@ -253,4 +253,11 @@
+         To compile this driver as a module, choose M here: the
+         module will be called gpio-keys.
++config KEYBOARD_ASIC3
++        tristate "Buttons on ASIC3 SoC GPIOs (iPaqs, etc.)"
++        depends on HTC_ASIC3
++        help
++          This enables support for the buttons attached to GPIOs of
++          HTC ASIC3 peripheral controller.
++
+ endif
diff --git a/packages/kexecboot/linux-kexecboot-2.6.23/htcuniversal/defconfig b/packages/kexecboot/linux-kexecboot-2.6.23/htcuniversal/defconfig
new file mode 100644 (file)
index 0000000..3f33b14
--- /dev/null
@@ -0,0 +1,1313 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.23-rc4
+# Wed Sep 26 17:55:32 2007
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_MMU=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ZONE_DMA=y
+CONFIG_ARCH_MTD_XIP=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_AUDIT is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+# CONFIG_UID16 is not set
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+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_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_IOSCHED_CFQ 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 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_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_MXC 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_DAVINCI is not set
+# CONFIG_ARCH_OMAP 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 is not set
+# CONFIG_MACH_EM_X270 is not set
+# CONFIG_MACH_HX2750 is not set
+CONFIG_MACH_HTCUNIVERSAL=y
+
+#
+# HTC Universal support
+#
+CONFIG_HTCUNIVERSAL_CORE=y
+CONFIG_HTCUNIVERSAL_UDC=y
+CONFIG_HTCUNIVERSAL_POWER=y
+CONFIG_HTCUNIVERSAL_BACKLIGHT=y
+CONFIG_HTCUNIVERSAL_LCD=y
+CONFIG_HTCUNIVERSAL_TS2=y
+CONFIG_HTCUNIVERSAL_BUTTONS=y
+CONFIG_HTCUNIVERSAL_BLUETOOTH=m
+CONFIG_HTCUNIVERSAL_ASIC3_LEDS=y
+CONFIG_HTCUNIVERSAL_PHONE=m
+# CONFIG_HTCUNIVERSAL_AK4641 is not set
+CONFIG_PXA27x=y
+# CONFIG_PXA_KEYS is not set
+
+#
+# Boot options
+#
+
+#
+# Power management
+#
+
+#
+# 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
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_OUTER_CACHE is not set
+CONFIG_IWMMXT=y
+CONFIG_XSCALE_PMU=y
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_TICK_ONESHOT is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_PREEMPT=y
+CONFIG_HZ=100
+CONFIG_AEABI=y
+CONFIG_OABI_COMPAT=y
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=ttyS0,115200n8 console=tty1 noinitrd root=/dev/mtdblock2 rootfstype=jffs2   dyntick=enable debug"
+# CONFIG_XIP_KERNEL is not set
+CONFIG_KEXEC=y
+CONFIG_ATAGS_PROC=y
+
+#
+# CPU Frequency scaling
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+CONFIG_CPU_FREQ_DEBUG=y
+CONFIG_CPU_FREQ_STAT=y
+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 is not set
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+# CONFIG_SUSPEND is not set
+CONFIG_APM_EMULATION=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=m
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK is not set
+# CONFIG_NF_CONNTRACK_ENABLED is not set
+# CONFIG_NF_CONNTRACK is not set
+CONFIG_NETFILTER_XTABLES=m
+# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
+# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
+# CONFIG_NETFILTER_XT_TARGET_MARK is not set
+# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
+# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
+# CONFIG_NETFILTER_XT_TARGET_TRACE is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
+# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
+# CONFIG_NETFILTER_XT_MATCH_ESP is not set
+# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
+# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_MAC is not set
+# CONFIG_NETFILTER_XT_MATCH_MARK is not set
+# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
+# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
+# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
+# CONFIG_NETFILTER_XT_MATCH_REALM is not set
+# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
+# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
+# CONFIG_NETFILTER_XT_MATCH_STRING is not set
+# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_U32 is not set
+# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=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_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# 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=y
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=y
+# CONFIG_IRNET is not set
+CONFIG_IRCOMM=y
+CONFIG_IRDA_ULTRA=y
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+CONFIG_IRDA_DEBUG=y
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=y
+
+#
+# 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_PXA_FICP=y
+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_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+# CONFIG_BT_HCIVHCI is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+CONFIG_WIRELESS_EXT=y
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+CONFIG_MTD_DEBUG=y
+CONFIG_MTD_DEBUG_VERBOSE=0
+# 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 is not set
+# CONFIG_MTD_BLKDEVS is not set
+# CONFIG_MTD_BLOCK is not set
+# CONFIG_MTD_BLOCK_RO is not set
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_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=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 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_NET_ETHERNET is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+CONFIG_NET_RADIO=y
+# CONFIG_NET_WIRELESS_RTNETLINK is not set
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+CONFIG_ACX=m
+CONFIG_ACX_MEM=y
+# CONFIG_ACX_CS is not set
+CONFIG_ACX_HTCUNIVERSAL=m
+# CONFIG_WAN is not set
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_MPPE=m
+# CONFIG_PPPOE is not set
+# CONFIG_PPPOL2TP is not set
+# CONFIG_SLIP is not set
+CONFIG_SLHC=m
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+# CONFIG_INPUT_POWER is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+CONFIG_KEYBOARD_PXA27x=y
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_KEYBOARD_ASIC3=y
+CONFIG_INPUT_MOUSE=y
+# CONFIG_MOUSE_PS2 is not set
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_MOUSE_GPIO is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_UCB1400 is not set
+# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_ATI_REMOTE is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
+CONFIG_INPUT_UINPUT=m
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_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=32
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_WATCHDOG is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_NVRAM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=m
+CONFIG_I2C_BOARDINFO=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_GPIO is not set
+CONFIG_I2C_PXA=m
+# CONFIG_I2C_PXA_SLAVE is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_DS1682 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_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+CONFIG_W1=y
+
+#
+# 1-wire Bus Masters
+#
+# CONFIG_W1_MASTER_DS2482 is not set
+CONFIG_W1_MASTER_DS1WM=y
+
+#
+# 1-wire Slaves
+#
+# CONFIG_W1_SLAVE_THERM is not set
+# CONFIG_W1_SLAVE_SMEM is not set
+# CONFIG_W1_SLAVE_DS2433 is not set
+CONFIG_W1_SLAVE_DS2760=y
+CONFIG_POWER_SUPPLY=y
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+CONFIG_PDA_POWER=y
+CONFIG_APM_POWER=y
+CONFIG_BATTERY_DS2760=y
+# CONFIG_HWMON is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_EEPROM_93CX6 is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+CONFIG_HTC_ASIC3=y
+CONFIG_HTC_ASIC3_DS1WM=y
+
+#
+# Multi-Function Devices
+#
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+# CONFIG_LEDS_GPIO is not set
+CONFIG_LEDS_ASIC3=y
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+# CONFIG_LEDS_TRIGGER_HEARTBEAT is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
+
+#
+# Graphics support
+#
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_CORGI=y
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=m
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_SYS_FOPS is not set
+CONFIG_FB_DEFERRED_IO=y
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_PXA=y
+CONFIG_FB_PXA_LCD_QVGA=y
+# CONFIG_FB_PXA_LCD_VGA is not set
+# CONFIG_FB_PXA_OVERLAY is not set
+# CONFIG_FB_PXA_PARAMETERS is not set
+# CONFIG_FB_MBX 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_DETECT_PRIMARY is not set
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+# CONFIG_FONT_8x16 is not set
+# 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
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+CONFIG_LOGO_OHAND_CLUT224=y
+# CONFIG_LOGO_OZ240_CLUT224 is not set
+# CONFIG_LOGO_OZ480_CLUT224 is not set
+# CONFIG_LOGO_OZ640_CLUT224 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_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_PCM_OSS_PLUGINS=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# ALSA ARM devices
+#
+# CONFIG_SND_PXA2XX_AC97 is not set
+
+#
+# System on Chip audio support
+#
+# CONFIG_SND_SOC is not set
+
+#
+# SoC Audio support for SuperH
+#
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=m
+# CONFIG_HID_DEBUG is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+# CONFIG_USB is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG is not set
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_PXA2XX is not set
+# CONFIG_USB_GADGET_M66592 is not set
+CONFIG_USB_GADGET_PXA27X=y
+CONFIG_USB_PXA27X=y
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+# CONFIG_USB_GADGET_DUALSPEED is not set
+# 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
+# CONFIG_USB_MIDI_GADGET is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_UNSAFE_RESUME=y
+
+#
+# MMC/SD Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+
+#
+# MMC/SD Host Controller Drivers
+#
+# CONFIG_MMC_PXA is not set
+CONFIG_MMC_ASIC3=y
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+CONFIG_RTC_DEBUG=y
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_SA1100=y
+
+#
+# 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 is not set
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS 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_SUNRPC_BIND34 is not set
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+CONFIG_NLS_CODEPAGE_1250=y
+CONFIG_NLS_CODEPAGE_1251=y
+# 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=y
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+CONFIG_PRINTK_TIME=y
+CONFIG_ENABLE_MUST_CHECK=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_DEBUG_PREEMPT=y
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
+CONFIG_DEBUG_VM=y
+# CONFIG_DEBUG_LIST is not set
+CONFIG_FRAME_POINTER=y
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+CONFIG_DEBUG_USER=y
+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
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=y
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_ECB=m
+# CONFIG_CRYPTO_CBC is not set
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+CONFIG_CRYPTO_ARC4=m
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_DEFLATE=y
+# CONFIG_CRYPTO_LZO is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_TEST is not set
+CONFIG_CRYPTO_HW=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/packages/kexecboot/linux-kexecboot-2.6.23/hx2000/defconfig b/packages/kexecboot/linux-kexecboot-2.6.23/hx2000/defconfig
new file mode 100644 (file)
index 0000000..447d26d
--- /dev/null
@@ -0,0 +1,1231 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.20-rc2
+# Mon Jan  1 01:49:04 2007
+#
+CONFIG_ARM=y
+# CONFIG_GENERIC_TIME is not set
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_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_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_IPC_NS is not set
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_KMOD is not set
+
+#
+# Block layer
+#
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=m
+CONFIG_IOSCHED_CFQ=m
+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_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_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 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 is not set
+CONFIG_MACH_HX2750=y
+CONFIG_PXA27x=y
+CONFIG_PXA_SSP=y
+CONFIG_PXA_KEYS=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
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_DCACHE_DISABLE is not set
+CONFIG_IWMMXT=y
+CONFIG_XSCALE_PMU=y
+
+#
+# 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_PCMCIA_PXA2XX=y
+
+#
+# Kernel Features
+#
+CONFIG_PREEMPT=y
+CONFIG_NO_IDLE_HZ=y
+CONFIG_HZ=100
+CONFIG_AEABI=y
+CONFIG_OABI_COMPAT=y
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=ttyS0,115200n8 console=tty1 noinitrd root=/dev/mtdblock2 rootfstype=jffs2   dyntick=enable debug"
+# CONFIG_XIP_KERNEL is not set
+CONFIG_KEXEC=y
+CONFIG_ATAGS_PROC=y
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+CONFIG_PM_DEBUG=y
+# CONFIG_DISABLE_CONSOLE_SUSPEND is not set
+# CONFIG_PM_SYSFS_DEPRECATED is not set
+CONFIG_APM=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=m
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK is not set
+# CONFIG_NF_CONNTRACK_ENABLED is not set
+# CONFIG_NF_CONNTRACK is not set
+CONFIG_NETFILTER_XTABLES=m
+# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
+# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
+# CONFIG_NETFILTER_XT_TARGET_MARK is not set
+# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
+# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
+# CONFIG_NETFILTER_XT_TARGET_TRACE is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
+# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
+# CONFIG_NETFILTER_XT_MATCH_ESP is not set
+# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
+# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_MAC is not set
+# CONFIG_NETFILTER_XT_MATCH_MARK is not set
+# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
+# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
+# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
+# CONFIG_NETFILTER_XT_MATCH_REALM is not set
+# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
+# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
+# CONFIG_NETFILTER_XT_MATCH_STRING is not set
+# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_U32 is not set
+# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=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_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+# CONFIG_IEEE80211_CRYPT_CCMP is not set
+# CONFIG_IEEE80211_CRYPT_TKIP is not set
+# CONFIG_IEEE80211_SOFTMAC is not set
+CONFIG_WIRELESS_EXT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+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 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
+# CONFIG_SSFDC is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_NOSWAP=y
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+CONFIG_MTD_CFI_GEOMETRY=y
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_OTP is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# 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=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# 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 is not set
+CONFIG_BLK_DEV_IDECS=y
+# 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_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
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=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
+# CONFIG_SMC911X 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=m
+# CONFIG_ATMEL is not set
+
+#
+# Wireless 802.11b Pcmcia/Cardbus cards support
+#
+CONFIG_PCMCIA_HERMES=m
+CONFIG_PCMCIA_SPECTRUM=m
+# CONFIG_AIRO_CS is not set
+# CONFIG_PCMCIA_WL3501 is not set
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+# CONFIG_HOSTAP_FIRMWARE_NVRAM is not set
+CONFIG_HOSTAP_CS=m
+CONFIG_NET_WIRELESS=y
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+# CONFIG_PCMCIA_3C589 is not set
+# CONFIG_PCMCIA_3C574 is not set
+# CONFIG_PCMCIA_FMVJ18X is not set
+CONFIG_PCMCIA_PCNET=m
+# CONFIG_PCMCIA_NMCLAN is not set
+# CONFIG_PCMCIA_SMC91C92 is not set
+# CONFIG_PCMCIA_XIRC2PS is not set
+# CONFIG_PCMCIA_AXNET is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+# CONFIG_PPP_MPPE is not set
+# CONFIG_PPPOE is not set
+# CONFIG_SLIP is not set
+CONFIG_SLHC=m
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=m
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=240
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=320
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+CONFIG_INPUT_POWER=y
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+# 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_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_UCB1400 is not set
+CONFIG_TOUCHSCREEN_TSC2101=y
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_PXA=y
+CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+CONFIG_HW_RANDOM=m
+# CONFIG_NVRAM is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_CARDMAN_4000 is not set
+# CONFIG_CARDMAN_4040 is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
+# Misc devices
+#
+# CONFIG_TIFM_CORE is not set
+
+#
+# Multi-Function Devices
+#
+CONFIG_MFD_TSC2101=y
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_VIDEO_V4L2=y
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB 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 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_LCD_QVGA=y
+# CONFIG_FB_PXA_LCD_VGA is not set
+# CONFIG_FB_PXA_OVERLAY is not set
+# CONFIG_FB_PXA_PARAMETERS is not set
+# CONFIG_FB_MBX 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 is not set
+CONFIG_LOGO_OHAND_CLUT224=y
+# CONFIG_LOGO_OZ240_CLUT224 is not set
+# CONFIG_LOGO_OZ480_CLUT224 is not set
+# CONFIG_LOGO_OZ640_CLUT224 is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_LCD_DEVICE=y
+CONFIG_BACKLIGHT_HX2750=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# HID Devices
+#
+CONFIG_HID=m
+
+#
+# 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=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_PXA=y
+# CONFIG_MMC_TIFM_SD is not set
+CONFIG_MMC_UNSAFE_RESUME=y
+
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+
+#
+# RTC drivers
+#
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+CONFIG_RTC_DRV_SA1100=y
+# CONFIG_RTC_DRV_TEST is not set
+# CONFIG_RTC_DRV_V3020 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=m
+# CONFIG_EXT4DEV_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_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 is not set
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY 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_SQUASHFS=m
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+# CONFIG_SQUASHFS_VMALLOC is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+# CONFIG_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 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="cp437"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=y
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_TIMER_STATS=y
+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_PREEMPT=y
+# 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 is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
+CONFIG_FRAME_POINTER=y
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_DEBUG_USER 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=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_MANAGER=m
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC 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_GF128MUL is not set
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=m
+# CONFIG_CRYPTO_LRW 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=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
+# CONFIG_SHARPSL_RC is not set
diff --git a/packages/kexecboot/linux-kexecboot-2.6.23/mtd-module.patch b/packages/kexecboot/linux-kexecboot-2.6.23/mtd-module.patch
new file mode 100644 (file)
index 0000000..4aa2f22
--- /dev/null
@@ -0,0 +1,13 @@
+Index: linux-2.6.23/drivers/mtd/maps/Kconfig
+===================================================================
+--- linux-2.6.23/drivers/mtd/maps/Kconfig
++++ linux-2.6.23/drivers/mtd/maps/Kconfig
+@@ -600,7 +600,7 @@
+       default "4"
+ config MTD_SHARP_SL
+-      bool "ROM mapped on Sharp SL Series"
++      tristate "ROM mapped on Sharp SL Series"
+       depends on ARCH_PXA
+       help
+         This enables access to the flash chip on the Sharp SL Series of PDAs.
diff --git a/packages/kexecboot/linux-kexecboot-2.6.23/poodle/defconfig b/packages/kexecboot/linux-kexecboot-2.6.23/poodle/defconfig
new file mode 100644 (file)
index 0000000..5afa7c5
--- /dev/null
@@ -0,0 +1,1741 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.23
+# Fri Dec 28 17:28:59 2007
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_MMU=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ZONE_DMA=y
+CONFIG_ARCH_MTD_XIP=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=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_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+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_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=m
+CONFIG_IOSCHED_CFQ=m
+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_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_MXC 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_DAVINCI is not set
+# CONFIG_ARCH_OMAP 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=y
+# CONFIG_MACH_TRIZEPS4 is not set
+# CONFIG_MACH_EM_X270 is not set
+# CONFIG_MACH_HX2750 is not set
+# CONFIG_MACH_HTCUNIVERSAL is not set
+CONFIG_PXA_SHARPSL_25x=y
+# CONFIG_PXA_SHARPSL_27x is not set
+CONFIG_MACH_POODLE=y
+# CONFIG_MACH_CORGI is not set
+# CONFIG_MACH_SHEPHERD is not set
+# CONFIG_MACH_HUSKY is not set
+# CONFIG_MACH_TOSA is not set
+CONFIG_PXA25x=y
+CONFIG_PXA_SSP=y
+# CONFIG_PXA_KEYS is not set
+
+#
+# Boot options
+#
+
+#
+# Power management
+#
+
+#
+# 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
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_OUTER_CACHE is not set
+# CONFIG_IWMMXT is not set
+CONFIG_XSCALE_PMU=y
+CONFIG_SHARP_LOCOMO=y
+CONFIG_SHARP_PARAM=y
+CONFIG_SHARPSL_PM=y
+CONFIG_SHARP_SCOOP=y
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI 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
+
+#
+# PC-card bridges
+#
+CONFIG_PCMCIA_PXA2XX=y
+
+#
+# Kernel Features
+#
+# CONFIG_TICK_ONESHOT is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_PREEMPT=y
+CONFIG_HZ=100
+CONFIG_AEABI=y
+CONFIG_OABI_COMPAT=y
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=ttyS0,115200n8 console=tty1 noinitrd root=/dev/mtdblock2 rootfstype=jffs2  fbcon=rotate:1 dyntick=enable debug"
+# CONFIG_XIP_KERNEL is not set
+CONFIG_KEXEC=y
+CONFIG_ATAGS_PROC=y
+CONFIG_CPU_FREQ_PXA25x=y
+
+#
+# CPU Frequency scaling
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+CONFIG_CPU_FREQ_DEBUG=y
+CONFIG_CPU_FREQ_STAT=y
+# CONFIG_CPU_FREQ_STAT_DETAILS is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_AOUT=m
+CONFIG_BINFMT_MISC=m
+
+#
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND_UP_POSSIBLE=y
+CONFIG_SUSPEND=y
+CONFIG_APM_EMULATION=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=m
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=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=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IP_VS is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+# CONFIG_IPV6_MIP6 is not set
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=m
+CONFIG_IPV6_TUNNEL=m
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK is not set
+# CONFIG_NF_CONNTRACK_ENABLED is not set
+# CONFIG_NF_CONNTRACK is not set
+CONFIG_NETFILTER_XTABLES=m
+# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
+# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
+# CONFIG_NETFILTER_XT_TARGET_MARK is not set
+# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
+# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
+# CONFIG_NETFILTER_XT_TARGET_TRACE is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
+# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
+# CONFIG_NETFILTER_XT_MATCH_ESP is not set
+# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
+# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_MAC is not set
+# CONFIG_NETFILTER_XT_MATCH_MARK is not set
+# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
+# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
+# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
+# CONFIG_NETFILTER_XT_MATCH_REALM is not set
+# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
+# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
+# CONFIG_NETFILTER_XT_MATCH_STRING is not set
+# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_U32 is not set
+# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=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_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=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 is not set
+# CONFIG_IP6_NF_IPTABLES is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# 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 is not set
+
+#
+# IrDA options
+#
+# CONFIG_IRDA_CACHE_LAST_LSAP is not set
+# CONFIG_IRDA_FAST_RR is not set
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+# CONFIG_IRTTY_SIR is not set
+
+#
+# Dongle support
+#
+# CONFIG_KINGSUN_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=m
+# CONFIG_MCS_FIR is not set
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIUSB=m
+# CONFIG_BT_HCIUSB_SCO is not set
+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_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+CONFIG_WIRELESS_EXT=y
+# CONFIG_MAC80211 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_RFKILL is not set
+# CONFIG_NET_9P 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_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI 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=y
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_SHARP_SL=y
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_VERIFY_WRITE=y
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_H1900 is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+CONFIG_MTD_NAND_SHARPSL=y
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+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 is not set
+CONFIG_BLK_DEV_IDECS=y
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_PROC_FS=y
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_IDEPCI_PCIBUS_ORDER is not set
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=m
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=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 is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set
+# CONFIG_ATA is not set
+CONFIG_MD=y
+# CONFIG_BLK_DEV_MD is not set
+CONFIG_BLK_DEV_DM=m
+# CONFIG_DM_DEBUG is not set
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_EMC=m
+# CONFIG_DM_MULTIPATH_RDAC is not set
+# CONFIG_DM_DELAY is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+# CONFIG_AX88796 is not set
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+# CONFIG_SMC911X is not set
+CONFIG_NETDEV_1000=y
+CONFIG_NETDEV_10000=y
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+CONFIG_WLAN_80211=y
+# CONFIG_PCMCIA_RAYCS is not set
+# CONFIG_LIBERTAS is not set
+CONFIG_HERMES=m
+# CONFIG_ATMEL is not set
+CONFIG_PCMCIA_HERMES=m
+CONFIG_PCMCIA_SPECTRUM=m
+# CONFIG_AIRO_CS is not set
+# CONFIG_PCMCIA_WL3501 is not set
+# CONFIG_USB_ZD1201 is not set
+# CONFIG_RTL8187 is not set
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+# CONFIG_HOSTAP_FIRMWARE_NVRAM is not set
+CONFIG_HOSTAP_CS=m
+# CONFIG_ZD1211RW is not set
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET_MII=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_CDCETHER=m
+# CONFIG_USB_NET_DM9601 is not set
+# CONFIG_USB_NET_GL620A is not set
+CONFIG_USB_NET_NET1080=m
+# CONFIG_USB_NET_PLUSB is not set
+# CONFIG_USB_NET_MCS7830 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_NET_PCMCIA=y
+# CONFIG_PCMCIA_3C589 is not set
+# CONFIG_PCMCIA_3C574 is not set
+# CONFIG_PCMCIA_FMVJ18X is not set
+CONFIG_PCMCIA_PCNET=m
+# CONFIG_PCMCIA_NMCLAN is not set
+# CONFIG_PCMCIA_SMC91C92 is not set
+# CONFIG_PCMCIA_XIRC2PS is not set
+# CONFIG_PCMCIA_AXNET is not set
+# 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 is not set
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+# CONFIG_PPP_MPPE is not set
+# CONFIG_PPPOE is not set
+# CONFIG_PPPOL2TP is not set
+# CONFIG_SLIP is not set
+CONFIG_SLHC=m
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=m
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=240
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=320
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+CONFIG_INPUT_POWER=y
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+CONFIG_KEYBOARD_LOCOMO=y
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_CORGI is not set
+# CONFIG_KEYBOARD_SPITZ is not set
+# CONFIG_KEYBOARD_GPIO is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_CORGI=y
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_UCB1400 is not set
+# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_ATI_REMOTE is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
+CONFIG_INPUT_UINPUT=m
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250_CS=m
+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_PXA=y
+CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_HW_RANDOM=m
+# CONFIG_NVRAM is not set
+# CONFIG_R3964 is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_CARDMAN_4000 is not set
+# CONFIG_CARDMAN_4040 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=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_GPIO is not set
+CONFIG_I2C_PXA=y
+# CONFIG_I2C_PXA_SLAVE is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_DS1682 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_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_EEPROM_93CX6 is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_ASIC3 is not set
+# CONFIG_HTC_ASIC3_DS1WM is not set
+
+#
+# Multi-Function Devices
+#
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+CONFIG_LEDS_LOCOMO=y
+# CONFIG_LEDS_TOSA is not set
+# CONFIG_LEDS_GPIO is not set
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_IDE_DISK=y
+# CONFIG_LEDS_TRIGGER_HEARTBEAT is not set
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_VIDEO_V4L2=y
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_TUNER_3036 is not set
+# CONFIG_TUNER_TEA5761 is not set
+CONFIG_V4L_USB_DRIVERS=y
+# CONFIG_VIDEO_PVRUSB2 is not set
+# CONFIG_VIDEO_EM28XX is not set
+# CONFIG_VIDEO_USBVISION is not set
+CONFIG_VIDEO_USBVIDEO=m
+CONFIG_USB_VICAM=m
+CONFIG_USB_IBMCAM=m
+CONFIG_USB_KONICAWC=m
+# CONFIG_USB_QUICKCAM_MESSENGER is not set
+# CONFIG_USB_ET61X251 is not set
+# CONFIG_VIDEO_OVCAMCHIP is not set
+# CONFIG_USB_W9968CF is not set
+CONFIG_USB_OV511=m
+CONFIG_USB_SE401=m
+CONFIG_USB_SN9C102=m
+CONFIG_USB_STV680=m
+# CONFIG_USB_ZC0301 is not set
+# CONFIG_USB_PWC is not set
+# CONFIG_USB_ZR364XX is not set
+CONFIG_RADIO_ADAPTERS=y
+CONFIG_USB_DSBR=m
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
+CONFIG_USB_DABUSB=m
+
+#
+# Graphics support
+#
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=m
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+# CONFIG_BACKLIGHT_CORGI is not set
+CONFIG_BACKLIGHT_LOCOMO=y
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=m
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_SYS_FOPS is not set
+CONFIG_FB_DEFERRED_IO=y
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+CONFIG_FB_MODE_HELPERS=y
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_PXA=y
+CONFIG_FB_PXA_LCD_QVGA=y
+# CONFIG_FB_PXA_LCD_VGA is not set
+# CONFIG_FB_PXA_OVERLAY is not set
+# CONFIG_FB_PXA_PARAMETERS is not set
+# CONFIG_FB_MBX is not set
+# CONFIG_FB_W100 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_DETECT_PRIMARY is not set
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+CONFIG_FONTS=y
+# CONFIG_FONT_8x8 is not set
+# CONFIG_FONT_8x16 is not set
+# 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=y
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_10x18 is not set
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+CONFIG_LOGO_OHAND_CLUT224=y
+# CONFIG_LOGO_OZ240_CLUT224 is not set
+# CONFIG_LOGO_OZ480_CLUT224 is not set
+# CONFIG_LOGO_OZ640_CLUT224 is not set
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+# CONFIG_SND_SEQUENCER is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# ALSA ARM devices
+#
+# CONFIG_SND_PXA2XX_AC97 is not set
+
+#
+# USB devices
+#
+# CONFIG_SND_USB_AUDIO is not set
+# CONFIG_SND_USB_CAIAQ is not set
+
+#
+# PCMCIA devices
+#
+# CONFIG_SND_VXPOCKET is not set
+# CONFIG_SND_PDAUDIOCF is not set
+
+#
+# System on Chip audio support
+#
+CONFIG_SND_SOC=m
+CONFIG_SND_PXA2XX_SOC=m
+CONFIG_SND_PXA2XX_SOC_I2S=m
+CONFIG_SND_PXA2XX_SOC_POODLE=m
+
+#
+# SoC Audio support for SuperH
+#
+CONFIG_SND_SOC_WM8731=m
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=m
+# CONFIG_HID_DEBUG is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=m
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+CONFIG_USB_KBD=m
+CONFIG_USB_MOUSE=m
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_PERSIST 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
+CONFIG_USB_SL811_CS=m
+# CONFIG_USB_R8A66597_HCD is not set
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_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_KARMA is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+CONFIG_USB_MDC800=m
+CONFIG_USB_MICROTEK=m
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+# CONFIG_USB_SERIAL_AIRCABLE is not set
+# CONFIG_USB_SERIAL_AIRPRIME is not set
+# CONFIG_USB_SERIAL_ARK3116 is not set
+CONFIG_USB_SERIAL_BELKIN=m
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+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=m
+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_MOS7720 is not set
+# CONFIG_USB_SERIAL_MOS7840 is not set
+# CONFIG_USB_SERIAL_NAVMAN is not set
+CONFIG_USB_SERIAL_PL2303=m
+# CONFIG_USB_SERIAL_OTI6858 is not set
+# 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=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+# CONFIG_USB_SERIAL_OPTION is not set
+CONFIG_USB_SERIAL_OMNINET=m
+# CONFIG_USB_SERIAL_DEBUG is not set
+CONFIG_USB_EZUSB=y
+
+#
+# USB Miscellaneous drivers
+#
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+# CONFIG_USB_ADUTUX is not set
+CONFIG_USB_AUERSWALD=m
+CONFIG_USB_RIO500=m
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+# CONFIG_USB_BERRY_CHARGE is not set
+CONFIG_USB_LED=m
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+CONFIG_USB_CYTHERM=m
+# CONFIG_USB_PHIDGET is not set
+CONFIG_USB_IDMOUSE=m
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG is not set
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+CONFIG_USB_GADGET_PXA2XX=y
+CONFIG_USB_PXA2XX=y
+# CONFIG_USB_PXA2XX_SMALL is not set
+# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_PXA27X is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+# CONFIG_USB_GADGET_DUALSPEED is not set
+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
+# CONFIG_USB_MIDI_GADGET is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_UNSAFE_RESUME=y
+
+#
+# MMC/SD Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+
+#
+# MMC/SD Host Controller Drivers
+#
+CONFIG_MMC_PXA=y
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_SA1100=m
+
+#
+# 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=m
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_JBD=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 is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+# CONFIG_MSDOS_FS is not set
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+CONFIG_JFFS2_SUMMARY=y
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_SYSFS is not set
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_LZO=y
+CONFIG_JFFS2_RTIME=y
+CONFIG_JFFS2_RUBIN=y
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
+CONFIG_CRAMFS=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 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=y
+# 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_SUNRPC_GSS=m
+# CONFIG_SUNRPC_BIND34 is not set
+CONFIG_RPCSEC_GSS_KRB5=m
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+CONFIG_SMB_NLS_DEFAULT=y
+CONFIG_SMB_NLS_REMOTE="cp437"
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_WEAK_PW_HASH is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="cp437"
+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=m
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=y
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
+# Profiling support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+# CONFIG_DETECT_SOFTLOCKUP is not set
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_SCHEDSTATS is not set
+CONFIG_TIMER_STATS=y
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_PREEMPT is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_FORCED_INLINING is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_DEBUG_USER is not set
+CONFIG_DEBUG_ERRORS=y
+# CONFIG_DEBUG_LL is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=m
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_HASH=m
+CONFIG_CRYPTO_MANAGER=m
+CONFIG_CRYPTO_HMAC=m
+# CONFIG_CRYPTO_XCBC is not set
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+CONFIG_CRYPTO_DES=m
+# CONFIG_CRYPTO_FCRYPT is not set
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_LZO=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_CAMELLIA=m
+CONFIG_CRYPTO_TEST=m
+CONFIG_CRYPTO_HW=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/packages/kexecboot/linux-kexecboot-2.6.23/pxa-serial-hack.patch b/packages/kexecboot/linux-kexecboot-2.6.23/pxa-serial-hack.patch
new file mode 100644 (file)
index 0000000..bf20f46
--- /dev/null
@@ -0,0 +1,90 @@
+---
+ drivers/serial/8250.c        |    5 +++++
+ drivers/serial/serial_core.c |    1 +
+ drivers/serial/serial_cs.c   |   12 +++++++++---
+ include/linux/serial_core.h  |    1 +
+ 4 files changed, 16 insertions(+), 3 deletions(-)
+
+Index: linux-2.6.20/drivers/serial/8250.c
+===================================================================
+--- linux-2.6.20.orig/drivers/serial/8250.c    2007-04-27 13:37:26.000000000 +0100
++++ linux-2.6.20/drivers/serial/8250.c 2007-04-27 13:38:16.000000000 +0100
+@@ -2429,7 +2429,12 @@
+       .driver_name            = "serial",
+       .dev_name               = "ttyS",
+       .major                  = TTY_MAJOR,
++#ifdef CONFIG_SERIAL_PXA
++      .minor                  = 64 + 4,
++      .name_base              = 4,
++#else
+       .minor                  = 64,
++#endif
+       .nr                     = UART_NR,
+       .cons                   = SERIAL8250_CONSOLE,
+ };
+Index: linux-2.6.20/drivers/serial/serial_core.c
+===================================================================
+--- linux-2.6.20.orig/drivers/serial/serial_core.c     2007-02-04 18:44:54.000000000 +0000
++++ linux-2.6.20/drivers/serial/serial_core.c  2007-04-27 13:39:39.000000000 +0100
+@@ -2068,7 +2068,8 @@
+       printk(KERN_INFO "%s%s%s%d at %s (irq = %d) is a %s\n",
+              port->dev ? port->dev->bus_id : "",
+              port->dev ? ": " : "",
+-             drv->dev_name, port->line, address, port->irq, uart_type(port));
++             drv->dev_name, port->line + drv->name_base, address, port->irq,
++             uart_type(port));
+ }
+ static void
+@@ -2183,6 +2184,7 @@
+       normal->owner           = drv->owner;
+       normal->driver_name     = drv->driver_name;
+       normal->name            = drv->dev_name;
++      normal->name_base       = drv->name_base;
+       normal->major           = drv->major;
+       normal->minor_start     = drv->minor;
+       normal->type            = TTY_DRIVER_TYPE_SERIAL;
+Index: linux-2.6.20/include/linux/serial_core.h
+===================================================================
+--- linux-2.6.20.orig/include/linux/serial_core.h      2007-02-04 18:44:54.000000000 +0000
++++ linux-2.6.20/include/linux/serial_core.h   2007-04-27 13:37:27.000000000 +0100
+@@ -341,6 +341,7 @@
+       struct module           *owner;
+       const char              *driver_name;
+       const char              *dev_name;
++      int                      name_base;
+       int                      major;
+       int                      minor;
+       int                      nr;
+Index: linux-2.6.20/drivers/serial/serial_cs.c
+===================================================================
+--- linux-2.6.20.orig/drivers/serial/serial_cs.c       2007-02-04 18:44:54.000000000 +0000
++++ linux-2.6.20/drivers/serial/serial_cs.c    2007-04-27 13:40:34.000000000 +0100
+@@ -390,7 +390,7 @@
+                       kio_addr_t iobase, int irq)
+ {
+       struct uart_port port;
+-      int line;
++      int line, linestart;
+       memset(&port, 0, sizeof (struct uart_port));
+       port.iobase = iobase;
+@@ -411,10 +411,16 @@
+               return -EINVAL;
+       }
++#if CONFIG_SERIAL_PXA
++      linestart = 4;
++#else
++      linestart = 0;
++#endif
++
+       info->line[info->ndev] = line;
+-      sprintf(info->node[info->ndev].dev_name, "ttyS%d", line);
++      sprintf(info->node[info->ndev].dev_name, "ttyS%d", line+linestart);
+       info->node[info->ndev].major = TTY_MAJOR;
+-      info->node[info->ndev].minor = 0x40 + line;
++      info->node[info->ndev].minor = 0x40 + line + linestart;
+       if (info->ndev > 0)
+               info->node[info->ndev - 1].next = &info->node[info->ndev];
+       info->ndev++;
diff --git a/packages/kexecboot/linux-kexecboot-2.6.23/pxa2xx_udc_support_inverse_vbus.patch b/packages/kexecboot/linux-kexecboot-2.6.23/pxa2xx_udc_support_inverse_vbus.patch
new file mode 100644 (file)
index 0000000..72211aa
--- /dev/null
@@ -0,0 +1,120 @@
+From dbaryshkov@gmail.com Fri Dec  7 00:05:32 2007
+Return-Path: <SRS0=7TBh+psr=Q5=lists.arm.linux.org.uk=linux-arm-kernel-bounces+openembedded=haerwu.biz@haerwu.biz>
+X-Spam-Checker-Version: SpamAssassin 3.1.7 (2006-10-05) on 3080.s.tld.pl
+X-Spam-Level: 
+X-Spam-Status: No, score=1.0 required=5.0 tests=BAYES_40,SPF_FAIL 
+       autolearn=disabled version=3.1.7
+Delivered-To: haerwu.biz-marcin@haerwu.biz
+Received: (qmail 3062 invoked by uid 813007); 6 Dec 2007 23:44:39 -0000
+Delivered-To: haerwu.biz-openembedded@haerwu.biz
+Received: (qmail 3048 invoked by uid 813007); 6 Dec 2007 23:44:39 -0000
+X-clamdmail: clamdmail 0.18a
+Received: from zeniv.linux.org.uk (195.92.253.2)
+  by smtp.host4.kei.pl with SMTP; 6 Dec 2007 23:44:38 -0000
+Received: from [2002:4e20:1eda:1:201:3dff:fe00:156] (helo=lists.arm.linux.org.uk)
+       by ZenIV.linux.org.uk with esmtpsa (Exim 4.63 #1 (Red Hat Linux))
+       id 1J0Pts-0004dN-KF; Thu, 06 Dec 2007 23:13:03 +0000
+Received: from localhost ([127.0.0.1] helo=lists.arm.linux.org.uk)
+       by lists.arm.linux.org.uk with esmtp (Exim 4.50)
+       id 1J0Pr7-0000cF-OJ; Thu, 06 Dec 2007 23:10:10 +0000
+Received: from mu-out-0910.google.com ([209.85.134.185])
+       by lists.arm.linux.org.uk with esmtp (Exim 4.50) id 1J0Pn3-0000bt-0E
+       for linux-arm-kernel@lists.arm.linux.org.uk;
+       Thu, 06 Dec 2007 23:06:40 +0000
+Received: by mu-out-0910.google.com with SMTP id i2so13552mue
+       for <linux-arm-kernel@lists.arm.linux.org.uk>;
+       Thu, 06 Dec 2007 15:05:40 -0800 (PST)
+DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma;
+       h=domainkey-signature:received:received:date:to:subject:message-id:mime-version:content-type:content-disposition:user-agent:from;
+       bh=cfa4MUFsOjAsSKDax5Yk97Hu762FByFSAfUQi5KP2cc=;
+       b=aA5uLmMsFBL6uxIQjxwtR4vD/2zBfGHiN/xepdZSggrNmYu0DJ75Q8JsSqzU/z7Vh9hALIiHjCR3WeqlJqZKCBMSrANzpFN4KVunUajamxn85btZMYysQ3YuZI+DUTYPovoZhuPjmT+SUT7RFpOhwKXbs7z9J8DCgodOVS+YwEY=
+DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma;
+       h=date:to:subject:message-id:mime-version:content-type:content-disposition:user-agent:from;
+       b=oWC1DMK+88t4jXf/5sY2gvSAjKuYypZhUflAHvCNbKYn2iFzpEFoFfjcUgV+lArS06OuT/R4v4Cp87JGK1NLA/uei3fhFZwNsoHcqWkgdsOqp5dSWMZFWCCrO4ODJahoFlnsxoS6OiceJM6EKX8u3RTELEVZEnVl3H2HWM4JJh4=
+Received: by 10.82.107.15 with SMTP id f15mr9802870buc.1196982339522;
+       Thu, 06 Dec 2007 15:05:39 -0800 (PST)
+Received: from doriath.ww600.siemens.net ( [91.122.9.34])
+       by mx.google.com with ESMTPS id 5sm15474nfv.2007.12.06.15.05.37
+       (version=SSLv3 cipher=OTHER); Thu, 06 Dec 2007 15:05:38 -0800 (PST)
+Date: Fri, 7 Dec 2007 02:05:32 +0300
+To: linux-arm-kernel@lists.arm.linux.org.uk
+Message-ID: <20071206230532.GA13332@doriath.ww600.siemens.net>
+MIME-Version: 1.0
+Content-Type: text/plain;
+  charset=us-ascii
+Content-Disposition: inline
+User-Agent: Mutt/1.5.17 (2007-11-01)
+From: Dmitry Baryshkov <dbaryshkov@gmail.com>
+Subject: [PATCH 1/2] pxa2xx_udc_support_inverse_vbus.patch
+X-BeenThere: linux-arm-kernel@lists.arm.linux.org.uk
+X-Mailman-Version: 2.1.5
+Precedence: list
+List-Id: ARM Linux kernel discussions <linux-arm-kernel.lists.arm.linux.org.uk>
+List-Unsubscribe: <http://lists.arm.linux.org.uk/mailman/listinfo/linux-arm-kernel>,
+       <mailto:linux-arm-kernel-request@lists.arm.linux.org.uk?subject=unsubscribe>
+List-Archive: <http://lists.arm.linux.org.uk/pipermail/linux-arm-kernel>
+List-Post: <mailto:linux-arm-kernel@lists.arm.linux.org.uk>
+List-Help: <mailto:linux-arm-kernel-request@lists.arm.linux.org.uk?subject=help>
+List-Subscribe: <http://lists.arm.linux.org.uk/mailman/listinfo/linux-arm-kernel>,
+       <mailto:linux-arm-kernel-request@lists.arm.linux.org.uk?subject=subscribe>
+Sender: linux-arm-kernel-bounces@lists.arm.linux.org.uk
+Errors-To: linux-arm-kernel-bounces+openembedded=haerwu.biz+openembedded=haerwu.biz@lists.arm.linux.org.uk
+X-Length: 5827
+Status: R
+X-Status: NC
+X-KMail-EncryptionState:  
+X-KMail-SignatureState:  
+X-KMail-MDN-Sent:  
+
+Some pxa-based boards (like e.g. tosa) have the VBUS-detection gpio pin
+inverted. I.e. it's low when VBUS is connected and high when
+disconnected. Allow specifiing whether gpio_vbus value is inverted.
+
+Signed-off-by: Dmitry Baryshkov <dbaryshkov@gmail.com>
+
+Index: linux-test/drivers/usb/gadget/pxa2xx_udc.c
+===================================================================
+--- linux-test.orig/drivers/usb/gadget/pxa2xx_udc.c    2007-12-06 12:41:25.784337009 +0300
++++ linux-test/drivers/usb/gadget/pxa2xx_udc.c 2007-12-06 13:39:33.504345084 +0300
+@@ -125,8 +125,12 @@ static int is_vbus_present(void)
+ {
+       struct pxa2xx_udc_mach_info             *mach = the_controller->mach;
+-      if (mach->gpio_vbus)
+-              return gpio_get_value(mach->gpio_vbus);
++      if (mach->gpio_vbus) {
++              int value = gpio_get_value(mach->gpio_vbus);
++              return mach->gpio_vbus_inverted ?
++                      !value :
++                      value;
++      }
+       if (mach->udc_is_connected)
+               return mach->udc_is_connected();
+       return 1;
+@@ -1396,6 +1400,9 @@ static irqreturn_t udc_vbus_irq(int irq,
+       struct pxa2xx_udc       *dev = _dev;
+       int                     vbus = gpio_get_value(dev->mach->gpio_vbus);
++      if (dev->mach->gpio_vbus_inverted)
++              vbus = !vbus;
++
+       pxa2xx_udc_vbus_session(&dev->gadget, vbus);
+       return IRQ_HANDLED;
+ }
+Index: linux-test/include/asm-arm/mach/udc_pxa2xx.h
+===================================================================
+--- linux-test.orig/include/asm-arm/mach/udc_pxa2xx.h  2007-12-06 12:38:49.872349393 +0300
++++ linux-test/include/asm-arm/mach/udc_pxa2xx.h       2007-12-06 12:41:03.594903549 +0300
+@@ -22,5 +22,6 @@ struct pxa2xx_udc_mach_info {
+        */
+       u16     gpio_vbus;                      /* high == vbus present */
+       u16     gpio_pullup;                    /* high == pullup activated */
++      unsigned char gpio_vbus_inverted:1;
+ };
+
+-------------------------------------------------------------------
+List admin: http://lists.arm.linux.org.uk/mailman/listinfo/linux-arm-kernel
+FAQ:        http://www.arm.linux.org.uk/mailinglists/faq.php
+Etiquette:  http://www.arm.linux.org.uk/mailinglists/etiquette.php
+
diff --git a/packages/kexecboot/linux-kexecboot-2.6.23/pxa_fb_overlay.patch b/packages/kexecboot/linux-kexecboot-2.6.23/pxa_fb_overlay.patch
new file mode 100644 (file)
index 0000000..49c59b3
--- /dev/null
@@ -0,0 +1,26 @@
+---
+ drivers/video/pxafb.h |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+Index: linux-2.6.22/drivers/video/pxafb.h
+===================================================================
+--- linux-2.6.22.orig/drivers/video/pxafb.h    2007-09-25 15:44:42.000000000 +0200
++++ linux-2.6.22/drivers/video/pxafb.h 2007-09-25 15:45:07.000000000 +0200
+@@ -36,7 +36,7 @@
+       struct fb_bitfield      transp;
+ };
+-#ifdef CONFIG_PXA27x
++#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
+ /* PXA Overlay Framebuffer Support */
+ struct overlayfb_info
+ {
+@@ -142,7 +142,7 @@
+       wait_queue_head_t       ctrlr_wait;
+       struct work_struct      task;
+-#ifdef CONFIG_PXA27x
++#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
+       /* PXA Overlay Framebuffer Support */
+       struct overlayfb_info  *overlay1fb;
+       struct overlayfb_info  *overlay2fb;
diff --git a/packages/kexecboot/linux-kexecboot-2.6.23/qemuarm/defconfig b/packages/kexecboot/linux-kexecboot-2.6.23/qemuarm/defconfig
new file mode 100644 (file)
index 0000000..78f08be
--- /dev/null
@@ -0,0 +1,1397 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.23
+# Fri Jan 11 00:23:17 2008
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+# CONFIG_GENERIC_GPIO is not set
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_MMU=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ZONE_DMA=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_AUDIT is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_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_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+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
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+CONFIG_ARCH_VERSATILE=y
+# 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_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP is not set
+
+#
+# Boot options
+#
+
+#
+# Power management
+#
+
+#
+# Versatile platform type
+#
+CONFIG_ARCH_VERSATILE_PB=y
+# CONFIG_MACH_VERSATILE_AB 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
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
+# CONFIG_OUTER_CACHE is not set
+CONFIG_ARM_VIC=y
+CONFIG_ICST307=y
+
+#
+# Bus support
+#
+CONFIG_ARM_AMBA=y
+CONFIG_PCI=y
+CONFIG_PCI_SYSCALL=y
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCI_DEBUG is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_TICK_ONESHOT is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+# CONFIG_PREEMPT is not set
+CONFIG_HZ=100
+CONFIG_AEABI=y
+CONFIG_OABI_COMPAT=y
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_LEDS=y
+CONFIG_LEDS_CPU=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=ttyAMA0,115200n8 console=tty1 noinitrd root=/dev/mtdblock2 rootfstype=jffs2   dyntick=enable debug"
+# CONFIG_XIP_KERNEL is not set
+CONFIG_KEXEC=y
+CONFIG_ATAGS_PROC=y
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+CONFIG_VFP=y
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND_UP_POSSIBLE=y
+CONFIG_SUSPEND=y
+# CONFIG_APM_EMULATION is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=m
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=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 is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK is not set
+# CONFIG_NF_CONNTRACK_ENABLED is not set
+# CONFIG_NF_CONNTRACK is not set
+CONFIG_NETFILTER_XTABLES=m
+# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
+# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
+# CONFIG_NETFILTER_XT_TARGET_MARK is not set
+# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
+# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
+# CONFIG_NETFILTER_XT_TARGET_TRACE is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
+# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
+# CONFIG_NETFILTER_XT_MATCH_ESP is not set
+# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
+# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_MAC is not set
+# CONFIG_NETFILTER_XT_MATCH_MARK is not set
+# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
+# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
+# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
+# CONFIG_NETFILTER_XT_MATCH_REALM is not set
+# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
+# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
+# CONFIG_NETFILTER_XT_MATCH_STRING is not set
+# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_U32 is not set
+# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=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_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# 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_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_AFS_PARTS=y
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_NOSWAP=y
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_GEOMETRY is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_OTP is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# 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=51200
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+CONFIG_SCSI_SPI_ATTRS=y
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ARCMSR is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_STEX is not set
+CONFIG_SCSI_SYM53C8XX_2=y
+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_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
+# CONFIG_ATA is not set
+CONFIG_MD=y
+# CONFIG_BLK_DEV_MD is not set
+CONFIG_BLK_DEV_DM=m
+# CONFIG_DM_DEBUG is not set
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_EMC=m
+# CONFIG_DM_MULTIPATH_RDAC is not set
+# CONFIG_DM_DELAY 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_FIREWIRE is not set
+# CONFIG_IEEE1394 is not set
+# CONFIG_I2O is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+# CONFIG_ARCNET is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+CONFIG_SMC91X=y
+# CONFIG_DM9000 is not set
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+CONFIG_NETDEV_1000=y
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+# CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
+CONFIG_NETDEV_10000=y
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
+# CONFIG_MLX4_CORE is not set
+# CONFIG_TR is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 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_MII is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+# CONFIG_INPUT_POWER is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+CONFIG_INPUT_TABLET=y
+# CONFIG_TABLET_USB_ACECAD is not set
+# CONFIG_TABLET_USB_AIPTEK is not set
+# CONFIG_TABLET_USB_GTCO is not set
+# CONFIG_TABLET_USB_KBTAB is not set
+CONFIG_TABLET_USB_WACOM=y
+# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_ATI_REMOTE is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
+# CONFIG_INPUT_UINPUT is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIO_AMBAKMI=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 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_AMBA_PL011=y
+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_HW_RANDOM=m
+# CONFIG_NVRAM is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_DEVPORT=y
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_ABITUGURU3 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_VT8231 is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_PHANTOM is not set
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_ASIC3 is not set
+# CONFIG_HTC_ASIC3_DS1WM is not set
+
+#
+# Multi-Function Devices
+#
+CONFIG_NEW_LEDS=y
+# CONFIG_LEDS_CLASS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+# CONFIG_LEDS_TRIGGERS is not set
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_VIDEO_V4L2=y
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+# CONFIG_VIDEO_VIVI is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_VIDEO_STRADIS is not set
+CONFIG_V4L_USB_DRIVERS=y
+# CONFIG_USB_VICAM is not set
+# CONFIG_USB_IBMCAM is not set
+# CONFIG_USB_KONICAWC is not set
+# CONFIG_USB_QUICKCAM_MESSENGER is not set
+# CONFIG_USB_ET61X251 is not set
+# CONFIG_USB_OV511 is not set
+# CONFIG_USB_SE401 is not set
+# CONFIG_USB_SN9C102 is not set
+# CONFIG_USB_STV680 is not set
+# CONFIG_USB_ZC0301 is not set
+# CONFIG_USB_PWC is not set
+# CONFIG_USB_ZR364XX is not set
+CONFIG_RADIO_ADAPTERS=y
+# CONFIG_RADIO_GEMTEK_PCI is not set
+# CONFIG_RADIO_MAXIRADIO is not set
+# CONFIG_RADIO_MAESTRO is not set
+# CONFIG_USB_DSBR is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=m
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_SYS_FOPS is not set
+CONFIG_FB_DEFERRED_IO=y
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+CONFIG_FB_ARMCLCD=y
+# 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_S3 is not set
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_VT8623 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_ARK is not set
+# CONFIG_FB_PM3 is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+CONFIG_LOGO_OHAND_CLUT224=y
+# CONFIG_LOGO_OZ240_CLUT224 is not set
+# CONFIG_LOGO_OZ480_CLUT224 is not set
+# CONFIG_LOGO_OZ640_CLUT224 is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=m
+# CONFIG_HID_DEBUG is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEVICEFS is not set
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_PERSIST is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_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 Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK 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_ADUTUX is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+# CONFIG_MMC is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_RTC_DRV_PL031 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=m
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_JBD=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 is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_SYSFS is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_LZO=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS 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=y
+# CONFIG_NFSD_V3_ACL is not set
+# CONFIG_NFSD_V4 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=y
+# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+
+#
+# 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
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
+# Profiling support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+CONFIG_TIMER_STATS=y
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
+CONFIG_FRAME_POINTER=y
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_DEBUG_USER 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
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=m
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_MANAGER=m
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC 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_GF128MUL is not set
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_TEST is not set
+CONFIG_CRYPTO_HW=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/packages/kexecboot/linux-kexecboot-2.6.23/qemux86/defconfig b/packages/kexecboot/linux-kexecboot-2.6.23/qemux86/defconfig
new file mode 100644 (file)
index 0000000..62bbace
--- /dev/null
@@ -0,0 +1,1756 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.23
+# Thu Jan 10 23:22:30 2008
+#
+CONFIG_X86_32=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_CLOCKSOURCE_WATCHDOG=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_SEMAPHORE_SLEEPERS=y
+CONFIG_X86=y
+CONFIG_MMU=y
+CONFIG_ZONE_DMA=y
+CONFIG_QUICKLIST=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_GENERIC_IOMAP=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_DMI=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_USER_NS is not set
+CONFIG_AUDIT=y
+CONFIG_AUDITSYSCALL=y
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=15
+# CONFIG_CPUSETS is not set
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
+CONFIG_BLOCK=y
+CONFIG_LBD=y
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# Processor type and features
+#
+# CONFIG_TICK_ONESHOT is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_SMP=y
+CONFIG_X86_PC=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_PARAVIRT is not set
+CONFIG_M386=y
+# CONFIG_M486 is not set
+# CONFIG_M586 is not set
+# 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_MCORE2 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_MVIAC7 is not set
+CONFIG_X86_GENERIC=y
+CONFIG_X86_L1_CACHE_SHIFT=7
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_X86_PPRO_FENCE=y
+CONFIG_X86_F00F_BUG=y
+CONFIG_X86_INTEL_USERCOPY=y
+CONFIG_X86_MINIMUM_CPU_FAMILY=3
+# CONFIG_HPET_TIMER is not set
+CONFIG_NR_CPUS=8
+CONFIG_SCHED_SMT=y
+CONFIG_SCHED_MC=y
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_PREEMPT_BKL=y
+CONFIG_X86_LOCAL_APIC=y
+CONFIG_X86_IO_APIC=y
+CONFIG_X86_MCE=y
+CONFIG_X86_MCE_NONFATAL=y
+CONFIG_X86_MCE_P4THERMAL=y
+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 is not set
+# CONFIG_X86_CPUID is not set
+
+#
+# Firmware Drivers
+#
+# CONFIG_EDD is not set
+# CONFIG_DELL_RBU is not set
+# CONFIG_DCDBAS is not set
+CONFIG_DMIID=y
+CONFIG_NOHIGHMEM=y
+# CONFIG_HIGHMEM4G is not set
+# CONFIG_HIGHMEM64G is not set
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_3G_OPT is not set
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_2G_OPT is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+# CONFIG_X86_PAE is not set
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_SPARSEMEM_STATIC=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_NR_QUICK=1
+CONFIG_VIRT_TO_BUS=y
+# CONFIG_MATH_EMULATION is not set
+CONFIG_MTRR=y
+# CONFIG_EFI is not set
+CONFIG_IRQBALANCE=y
+CONFIG_SECCOMP=y
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_KEXEC=y
+CONFIG_PHYSICAL_START=0x100000
+# CONFIG_RELOCATABLE is not set
+CONFIG_PHYSICAL_ALIGN=0x100000
+CONFIG_HOTPLUG_CPU=y
+CONFIG_COMPAT_VDSO=y
+
+#
+# Power management options (ACPI, APM)
+#
+CONFIG_PM=y
+CONFIG_PM_LEGACY=y
+# CONFIG_PM_DEBUG is not set
+CONFIG_PM_SLEEP_SMP=y
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND_SMP_POSSIBLE=y
+CONFIG_SUSPEND=y
+CONFIG_HIBERNATION_SMP_POSSIBLE=y
+# CONFIG_HIBERNATION is not set
+CONFIG_ACPI=y
+CONFIG_ACPI_SLEEP=y
+# CONFIG_ACPI_PROCFS is not set
+CONFIG_ACPI_PROC_EVENT=y
+CONFIG_ACPI_AC=y
+CONFIG_ACPI_BATTERY=y
+CONFIG_ACPI_BUTTON=y
+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_ASUS is not set
+# CONFIG_ACPI_TOSHIBA is not set
+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 is not set
+# CONFIG_APM is not set
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ 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_GOANY=y
+CONFIG_PCI_BIOS=y
+CONFIG_PCI_DIRECT=y
+CONFIG_PCI_MMCONFIG=y
+# CONFIG_PCIEPORTBUS is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+# CONFIG_PCI_MSI is not set
+CONFIG_HT_IRQ=y
+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 is not set
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_AOUT=y
+CONFIG_BINFMT_MISC=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=m
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=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 is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_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=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NF_CONNTRACK_ENABLED=m
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CT_ACCT=y
+CONFIG_NF_CONNTRACK_MARK=y
+# CONFIG_NF_CONNTRACK_EVENTS is not set
+CONFIG_NF_CT_PROTO_GRE=m
+CONFIG_NF_CT_PROTO_SCTP=m
+CONFIG_NF_CT_PROTO_UDPLITE=m
+CONFIG_NF_CONNTRACK_AMANDA=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_H323=m
+CONFIG_NF_CONNTRACK_IRC=m
+CONFIG_NF_CONNTRACK_NETBIOS_NS=m
+CONFIG_NF_CONNTRACK_PPTP=m
+CONFIG_NF_CONNTRACK_SANE=m
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NF_CT_NETLINK=m
+CONFIG_NETFILTER_XTABLES=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_DSCP=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_TARGET_TRACE=m
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_DSCP=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_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
+CONFIG_NETFILTER_XT_MATCH_U32=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
+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_AH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_NF_NAT=m
+CONFIG_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_NF_NAT_SNMP_BASIC=m
+CONFIG_NF_NAT_PROTO_GRE=m
+CONFIG_NF_NAT_FTP=m
+CONFIG_NF_NAT_IRC=m
+CONFIG_NF_NAT_TFTP=m
+CONFIG_NF_NAT_AMANDA=m
+CONFIG_NF_NAT_PPTP=m
+CONFIG_NF_NAT_H323=m
+CONFIG_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_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
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+CONFIG_NET_CLS_ROUTE=y
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+CONFIG_WIRELESS_EXT=y
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=m
+# CONFIG_SYS_HYPERVISOR is not set
+CONFIG_CONNECTOR=y
+CONFIG_PROC_EVENTS=y
+# CONFIG_MTD is not set
+CONFIG_PARPORT=y
+CONFIG_PARPORT_PC=y
+# CONFIG_PARPORT_SERIAL is not set
+# CONFIG_PARPORT_PC_FIFO is not set
+# CONFIG_PARPORT_PC_SUPERIO is not set
+# CONFIG_PARPORT_GSC is not set
+# CONFIG_PARPORT_AX88796 is not set
+# CONFIG_PARPORT_1284 is not set
+CONFIG_PNP=y
+# CONFIG_PNP_DEBUG is not set
+
+#
+# Protocols
+#
+# CONFIG_ISAPNP is not set
+# CONFIG_PNPBIOS is not set
+CONFIG_PNPACPI=y
+CONFIG_BLK_DEV=y
+CONFIG_BLK_DEV_FD=y
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=51200
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_IBM_ASM is not set
+# CONFIG_PHANTOM is not set
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+# CONFIG_SONY_LAPTOP is not set
+# CONFIG_THINKPAD_ACPI is not set
+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_HD_IDE 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_BLK_DEV_IDEACPI is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_PROC_FS=y
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_CMD640=y
+# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
+# CONFIG_BLK_DEV_IDEPNP is not set
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+CONFIG_IDEPCI_PCIBUS_ORDER=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_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_ATIIXP 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_CS5535 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_JMICRON is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+CONFIG_BLK_DEV_PIIX=y
+# CONFIG_BLK_DEV_IT8213 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_SIS5513 is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_BLK_DEV_TC86C001 is not set
+# CONFIG_IDE_ARM is not set
+# CONFIG_IDE_CHIPSETS is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+CONFIG_CHR_DEV_SG=y
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_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_AIC94XX is not set
+CONFIG_SCSI_DPT_I2O=m
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_IN2000 is not set
+# CONFIG_SCSI_ARCMSR is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_SCSI_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_PPA is not set
+# CONFIG_SCSI_IMM is not set
+# CONFIG_SCSI_NCR53C406A is not set
+# CONFIG_SCSI_STEX is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_PAS16 is not set
+# CONFIG_SCSI_PSI240I is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_SEAGATE 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_ULTRASTOR is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
+# CONFIG_ATA is not set
+CONFIG_MD=y
+# CONFIG_BLK_DEV_MD is not set
+CONFIG_BLK_DEV_DM=m
+# CONFIG_DM_DEBUG is not set
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_EMC=m
+# CONFIG_DM_MULTIPATH_RDAC is not set
+# CONFIG_DM_DELAY 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_FIREWIRE is not set
+CONFIG_IEEE1394=y
+
+#
+# Subsystem Options
+#
+# CONFIG_IEEE1394_VERBOSEDEBUG is not set
+
+#
+# Controllers
+#
+
+#
+# Texas Instruments PCILynx requires I2C
+#
+CONFIG_IEEE1394_OHCI1394=y
+
+#
+# Protocols
+#
+# CONFIG_IEEE1394_VIDEO1394 is not set
+# CONFIG_IEEE1394_SBP2 is not set
+# CONFIG_IEEE1394_ETH1394_ROM_ENTRY is not set
+# CONFIG_IEEE1394_ETH1394 is not set
+# CONFIG_IEEE1394_DV1394 is not set
+CONFIG_IEEE1394_RAWIO=y
+# CONFIG_I2O is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
+CONFIG_DUMMY=m
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_NET_SB1000 is not set
+# CONFIG_ARCNET is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_LANCE is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_NET_TULIP 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 is not set
+# 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=y
+# CONFIG_ZNET is not set
+# CONFIG_SEEQ8005 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_AC3200 is not set
+# CONFIG_APRICOT is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_CS89x0 is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+CONFIG_NE2K_PCI=y
+# CONFIG_8139CP is not set
+CONFIG_8139TOO=y
+CONFIG_8139TOO_PIO=y
+# CONFIG_8139TOO_TUNE_TWISTER 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
+# CONFIG_SC92031 is not set
+# CONFIG_NET_POCKET is not set
+CONFIG_NETDEV_1000=y
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+# CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
+CONFIG_NETDEV_10000=y
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
+# CONFIG_IXGB is not set
+CONFIG_S2IO=m
+# CONFIG_S2IO_NAPI is not set
+# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
+# CONFIG_MLX4_CORE is not set
+# CONFIG_TR is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 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_MII is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PLIP 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
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+# CONFIG_INPUT_POWER is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+CONFIG_INPUT_TABLET=y
+# CONFIG_TABLET_USB_ACECAD is not set
+# CONFIG_TABLET_USB_AIPTEK is not set
+# CONFIG_TABLET_USB_GTCO is not set
+# CONFIG_TABLET_USB_KBTAB is not set
+CONFIG_TABLET_USB_WACOM=y
+# 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 is not set
+# 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 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 is not set
+CONFIG_FIX_EARLYCON_MEM=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_PNP=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_JSM is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_PRINTER=y
+# CONFIG_LP_CONSOLE is not set
+# CONFIG_PPDEV is not set
+# CONFIG_TIPAR is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_WATCHDOG is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_SONYPI is not set
+CONFIG_AGP=y
+# CONFIG_AGP_ALI is not set
+# 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 is not set
+# CONFIG_AGP_SWORKS is not set
+# CONFIG_AGP_VIA is not set
+# CONFIG_AGP_EFFICEON is not set
+CONFIG_DRM=y
+# CONFIG_DRM_TDFX is not set
+# CONFIG_DRM_R128 is not set
+# CONFIG_DRM_RADEON is not set
+# CONFIG_DRM_I810 is not set
+# CONFIG_DRM_I830 is not set
+# CONFIG_DRM_I915 is not set
+# CONFIG_DRM_MGA is not set
+# CONFIG_DRM_SIS is not set
+# CONFIG_DRM_VIA is not set
+# CONFIG_DRM_SAVAGE is not set
+# CONFIG_MWAVE is not set
+# CONFIG_PC8736x_GPIO is not set
+# CONFIG_NSC_GPIO is not set
+# CONFIG_CS5535_GPIO is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_HPET is not set
+# CONFIG_HANGCHECK_TIMER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+CONFIG_DEVPORT=y
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_ABITUGURU3 is not set
+# CONFIG_SENSORS_K8TEMP is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_CORETEMP is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_VT8231 is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_SENSORS_HDAPS is not set
+# CONFIG_SENSORS_APPLESMC is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_ASIC3 is not set
+# CONFIG_HTC_ASIC3_DS1WM is not set
+
+#
+# Multi-Function Devices
+#
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_VIDEO_V4L2=y
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+# CONFIG_VIDEO_VIVI is not set
+# CONFIG_VIDEO_PMS is not set
+# CONFIG_VIDEO_BWQCAM is not set
+# CONFIG_VIDEO_CQCAM is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_VIDEO_STRADIS is not set
+CONFIG_V4L_USB_DRIVERS=y
+# CONFIG_USB_VICAM is not set
+# CONFIG_USB_IBMCAM is not set
+# CONFIG_USB_KONICAWC is not set
+# CONFIG_USB_QUICKCAM_MESSENGER is not set
+# CONFIG_USB_ET61X251 is not set
+# CONFIG_USB_OV511 is not set
+# CONFIG_USB_SE401 is not set
+# CONFIG_USB_SN9C102 is not set
+# CONFIG_USB_STV680 is not set
+# CONFIG_USB_ZC0301 is not set
+# CONFIG_USB_PWC is not set
+# CONFIG_USB_ZR364XX is not set
+CONFIG_RADIO_ADAPTERS=y
+# 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 is not set
+# CONFIG_RADIO_MAXIRADIO is not set
+# CONFIG_RADIO_MAESTRO is not set
+# 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 is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=m
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+CONFIG_FB_CFB_FILLRECT=m
+CONFIG_FB_CFB_COPYAREA=m
+CONFIG_FB_CFB_IMAGEBLIT=m
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_SYS_FOPS is not set
+CONFIG_FB_DEFERRED_IO=y
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+CONFIG_FB_MODE_HELPERS=y
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ARC is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_VGA16 is not set
+CONFIG_FB_UVESA=m
+# CONFIG_FB_VESA is not set
+# CONFIG_FB_HECUBA is not set
+# CONFIG_FB_HGA is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_I810 is not set
+# CONFIG_FB_LE80578 is not set
+# CONFIG_FB_INTEL is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_S3 is not set
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_VT8623 is not set
+# CONFIG_FB_CYBLA is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_ARK is not set
+# CONFIG_FB_PM3 is not set
+# CONFIG_FB_GEODE 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_VIDEO_SELECT=y
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+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
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+CONFIG_LOGO_OHAND_CLUT224=y
+# CONFIG_LOGO_OZ240_CLUT224 is not set
+# CONFIG_LOGO_OZ480_CLUT224 is not set
+# CONFIG_LOGO_OZ640_CLUT224 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=y
+# CONFIG_SND_SEQ_DUMMY is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_SEQUENCER_OSS=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+CONFIG_SND_AC97_CODEC=y
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_VIRMIDI is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_MTS64 is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+# CONFIG_SND_PORTMAN2X4 is not set
+
+#
+# ISA devices
+#
+# CONFIG_SND_ADLIB is not set
+# 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 is not set
+# 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 is not set
+# CONFIG_SND_OPTI92X_AD1848 is not set
+# CONFIG_SND_OPTI92X_CS4231 is not set
+# CONFIG_SND_OPTI93X is not set
+# CONFIG_SND_MIRO is not set
+# CONFIG_SND_SB8 is not set
+# CONFIG_SND_SB16 is not set
+# CONFIG_SND_SBAWE 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 is not set
+# CONFIG_SND_ALS300 is not set
+# CONFIG_SND_ALS4000 is not set
+# CONFIG_SND_ALI5451 is not set
+# CONFIG_SND_ATIIXP is not set
+# CONFIG_SND_ATIIXP_MODEM is not set
+# CONFIG_SND_AU8810 is not set
+# CONFIG_SND_AU8820 is not set
+# CONFIG_SND_AU8830 is not set
+# CONFIG_SND_AZT3328 is not set
+# CONFIG_SND_BT87X is not set
+# CONFIG_SND_CA0106 is not set
+# CONFIG_SND_CMIPCI is not set
+# CONFIG_SND_CS4281 is not set
+# CONFIG_SND_CS46XX is not set
+# CONFIG_SND_CS5530 is not set
+# CONFIG_SND_CS5535AUDIO is not set
+# CONFIG_SND_DARLA20 is not set
+# CONFIG_SND_GINA20 is not set
+# CONFIG_SND_LAYLA20 is not set
+# CONFIG_SND_DARLA24 is not set
+# CONFIG_SND_GINA24 is not set
+# CONFIG_SND_LAYLA24 is not set
+# CONFIG_SND_MONA is not set
+# CONFIG_SND_MIA is not set
+# CONFIG_SND_ECHO3G is not set
+# CONFIG_SND_INDIGO is not set
+# CONFIG_SND_INDIGOIO is not set
+# CONFIG_SND_INDIGODJ is not set
+# CONFIG_SND_EMU10K1 is not set
+# CONFIG_SND_EMU10K1X is not set
+# CONFIG_SND_ENS1370 is not set
+# CONFIG_SND_ENS1371 is not set
+# CONFIG_SND_ES1938 is not set
+# CONFIG_SND_ES1968 is not set
+# CONFIG_SND_FM801 is not set
+# CONFIG_SND_HDA_INTEL is not set
+# CONFIG_SND_HDSP is not set
+# CONFIG_SND_HDSPM is not set
+# CONFIG_SND_ICE1712 is not set
+# CONFIG_SND_ICE1724 is not set
+CONFIG_SND_INTEL8X0=y
+# CONFIG_SND_INTEL8X0M is not set
+# CONFIG_SND_KORG1212 is not set
+# CONFIG_SND_MAESTRO3 is not set
+# CONFIG_SND_MIXART is not set
+# CONFIG_SND_NM256 is not set
+# CONFIG_SND_PCXHR is not set
+# CONFIG_SND_RIPTIDE is not set
+# CONFIG_SND_RME32 is not set
+# CONFIG_SND_RME96 is not set
+# CONFIG_SND_RME9652 is not set
+# CONFIG_SND_SONICVIBES is not set
+# CONFIG_SND_TRIDENT is not set
+# CONFIG_SND_VIA82XX is not set
+# CONFIG_SND_VIA82XX_MODEM is not set
+# CONFIG_SND_VX222 is not set
+# CONFIG_SND_YMFPCI is not set
+# CONFIG_SND_AC97_POWER_SAVE is not set
+
+#
+# USB devices
+#
+# CONFIG_SND_USB_AUDIO is not set
+# CONFIG_SND_USB_USX2Y is not set
+# CONFIG_SND_USB_CAIAQ is not set
+
+#
+# System on Chip audio support
+#
+# CONFIG_SND_SOC is not set
+
+#
+# SoC Audio support for SuperH
+#
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+CONFIG_AC97_BUS=y
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_PERSIST 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_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=y
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+CONFIG_USB_PRINTER=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+# CONFIG_USB_USS720 is not set
+
+#
+# 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_ADUTUX is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+CONFIG_USB_CYTHERM=m
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+# CONFIG_MMC is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_INFINIBAND is not set
+# CONFIG_EDAC is not set
+# CONFIG_RTC_CLASS is not set
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+# CONFIG_AUXDISPLAY is not set
+CONFIG_VIRTUALIZATION=y
+# CONFIG_KVM is not set
+
+#
+# Userspace I/O
+#
+# CONFIG_UIO is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+CONFIG_AUTOFS4_FS=y
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+# CONFIG_ZISOFS is not set
+CONFIG_UDF_FS=y
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS 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=y
+# CONFIG_NFSD_V3 is not set
+CONFIG_NFSD_TCP=y
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_EXPORTFS=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+CONFIG_INSTRUMENTATION=y
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=y
+# CONFIG_KPROBES is not set
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_UNUSED_SYMBOLS=y
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_EARLY_PRINTK=y
+CONFIG_X86_FIND_SMP_CONFIG=y
+CONFIG_X86_MPPARSE=y
+CONFIG_DOUBLEFAULT=y
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=m
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_MANAGER=m
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC 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=m
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_TWOFISH_586 is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_AES_586 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_LZO is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_TEST is not set
+CONFIG_CRYPTO_HW=y
+CONFIG_CRYPTO_DEV_PADLOCK=m
+CONFIG_CRYPTO_DEV_PADLOCK_AES=m
+CONFIG_CRYPTO_DEV_PADLOCK_SHA=m
+CONFIG_CRYPTO_DEV_GEODE=m
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+CONFIG_LIBCRC32C=m
+CONFIG_AUDIT_GENERIC=y
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=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/packages/kexecboot/linux-kexecboot-2.6.23/serial-add-support-for-non-standard-xtals-to-16c950-driver.patch b/packages/kexecboot/linux-kexecboot-2.6.23/serial-add-support-for-non-standard-xtals-to-16c950-driver.patch
new file mode 100644 (file)
index 0000000..b513ba1
--- /dev/null
@@ -0,0 +1,155 @@
+
+From: Petr Vandrovec <vandrove@vc.cvut.cz>
+
+Patch below adds support for using different prescaler than 16 for 16c950
+chips.  This is needed for using Fujitsu-Siemens Connect2Air compact-flash
+card, which comes (apparently) with 806kHz clocks, and so you have to
+program prescaler for division by 7, and DLAB to 1, to get 115200Bd.  
+
+To get card properly running you also have to add lines below to
+/etc/pcmcia/serial.opts so kernel knows that base speed is not 115200 but
+50400 (50400 * 16 = 806400; 806400 / 7 = 115200).  As I've found no code
+specifying baud_rate in serial_cs, I assume that specifying it in
+serial.opts is right way to do this type of things.
+
+Patch also fixes problem that for UPF_MAGIC_MULTIPLIER maximum possible
+baud rate passed to uart code was uartclk / 16 while correct value for
+these devices (and for 16c950) is uartclk / 4.
+
+Patch also fixes problem that for UPF_MAGIC_MULTIPLIER devices with
+baud_rate 19200 or 9600 spd_cust did not work correctly.  Not that such
+devices exist, but we should not ignore spd_cust, user probably knows why
+he asked for spd_cust.
+
+serial.opts:
+
+case "$MANFID-$FUNCID-$PRODID_1-$PRODID_2-$PRODID_3-$PRODID_4" in
+'0279,950b-2-GPRS Modem---')
+    SERIAL_OPTS="baud_base 50400"
+    ;;
+esac
+
+Cc: David Woodhouse <dwmw2@infradead.org>
+Signed-off-by: Andrew Morton <akpm@osdl.org>
+---
+
+ drivers/serial/8250.c |   82 +++++++++++++++++++++++++++++++++++++++-----------
+ 1 file changed, 64 insertions(+), 18 deletions(-)
+
+Index: linux-2.6.21/drivers/serial/8250.c
+===================================================================
+--- linux-2.6.21.orig/drivers/serial/8250.c    2007-07-01 16:59:52.000000000 +0100
++++ linux-2.6.21/drivers/serial/8250.c 2007-07-01 17:01:21.000000000 +0100
+@@ -1964,24 +1964,58 @@ static void serial8250_shutdown(struct u
+               serial_unlink_irq_chain(up);
+ }
+-static unsigned int serial8250_get_divisor(struct uart_port *port, unsigned int baud)
++static unsigned int serial8250_get_divisor(struct uart_port *port, unsigned int baud,
++                                         unsigned int *prescaler)
+ {
+-      unsigned int quot;
+-
+-      /*
+-       * Handle magic divisors for baud rates above baud_base on
+-       * SMSC SuperIO chips.
++        /*
++       * Use special handling only if user did not supply its own divider.
++       * spd_cust is defined in terms of baud_base, so always use default
++       * prescaler when spd_cust is requested.
+        */
+-      if ((port->flags & UPF_MAGIC_MULTIPLIER) &&
+-          baud == (port->uartclk/4))
+-              quot = 0x8001;
+-      else if ((port->flags & UPF_MAGIC_MULTIPLIER) &&
+-               baud == (port->uartclk/8))
+-              quot = 0x8002;
+-      else
+-              quot = uart_get_divisor(port, baud);
+-      return quot;
++      *prescaler = 16;
++        if (baud != 38400 || (port->flags & UPF_SPD_MASK) != UPF_SPD_CUST) {
++              unsigned int quot = port->uartclk / baud;
++
++              /*
++               * Handle magic divisors for baud rates above baud_base on
++               * SMSC SuperIO chips.
++               */
++              if (port->flags & UPF_MAGIC_MULTIPLIER) {
++                      if (quot == 4) {
++                              return 0x8001;
++                      } else if (quot == 8) {
++                              return 0x8002;
++                      }
++              }
++              if (port->type == PORT_16C950) {
++                      /*
++                       * This computes TCR value (4 to 16), not CPR value (which can
++                       * be between 1.000 and 31.875) - chip I have uses XTAL of
++                       * 806400Hz, and so a division by 7 is required to get 115200Bd.
++                       * I'm leaving CPR disabled for now, until someone will
++                       * hit even more exotic XTAL (it is needed to get 500kbps
++                       * or 1000kbps from 18.432MHz XTAL, but I have no device
++                       * which would benefit from doing that).
++                       *
++                       * If we can use divide by 16, use it.  Otherwise look for
++                       * better prescaler, from 15 to 4.  If quotient cannot
++                       * be divided by any integer value between 4 and 15, use 4.
++                       */
++                      if (quot & 0x0F) {
++                              unsigned int div;
++
++                              for (div = 15; div > 4; div--) {
++                                      if (quot % div == 0) {
++                                              break;
++                                      }
++                              }
++                              *prescaler = div;
++                              return quot / div;
++                      }
++              }
++      }
++      return uart_get_divisor(port, baud);
+ }
+ static void
+@@ -1991,7 +2025,7 @@ serial8250_set_termios(struct uart_port 
+       struct uart_8250_port *up = (struct uart_8250_port *)port;
+       unsigned char cval, fcr = 0;
+       unsigned long flags;
+-      unsigned int baud, quot;
++      unsigned int baud, quot, prescaler;
+       switch (termios->c_cflag & CSIZE) {
+       case CS5:
+@@ -2023,8 +2057,13 @@ serial8250_set_termios(struct uart_port 
+       /*
+        * Ask the core to calculate the divisor for us.
+        */
+-      baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
+-      quot = serial8250_get_divisor(port, baud);
++      if (port->type == PORT_16C950 || (port->flags & UPF_MAGIC_MULTIPLIER)) {
++              baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/4);
++      } else {
++              baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
++      }
++      quot = serial8250_get_divisor(port, baud, &prescaler);
++
+       /*
+        * Oxford Semi 952 rev B workaround
+@@ -2139,6 +2178,13 @@ serial8250_set_termios(struct uart_port 
+       serial_dl_write(up, quot);
+       /*
++       * Program prescaler for 16C950 chips.
++       */
++      if (up->port.type == PORT_16C950) {
++              serial_icr_write(up, UART_TCR, prescaler == 16 ? 0 : prescaler);
++      }
++
++      /*
+        * LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR
+        * is written without DLAB set, this mode will be disabled.
+        */
diff --git a/packages/kexecboot/linux-kexecboot-2.6.23/sharpsl-pm-postresume-r1.patch b/packages/kexecboot/linux-kexecboot-2.6.23/sharpsl-pm-postresume-r1.patch
new file mode 100644 (file)
index 0000000..409daf0
--- /dev/null
@@ -0,0 +1,30 @@
+ arch/arm/common/sharpsl_pm.c          |    3 +++
+ include/asm-arm/hardware/sharpsl_pm.h |    1 +
+ 2 files changed, 4 insertions(+)
+
+Index: git/include/asm-arm/hardware/sharpsl_pm.h
+===================================================================
+--- git.orig/include/asm-arm/hardware/sharpsl_pm.h     2006-10-31 16:09:33.000000000 +0000
++++ git/include/asm-arm/hardware/sharpsl_pm.h  2006-11-07 22:08:41.000000000 +0000
+@@ -26,6 +26,7 @@ struct sharpsl_charger_machinfo {
+       void (*presuspend)(void);
+       void (*postsuspend)(void);
+       void (*earlyresume)(void);
++      void (*postresume)(void);
+       unsigned long (*read_devdata)(int);
+ #define SHARPSL_BATT_VOLT       1
+ #define SHARPSL_BATT_TEMP       2
+Index: git/arch/arm/common/sharpsl_pm.c
+===================================================================
+--- git.orig/arch/arm/common/sharpsl_pm.c      2006-11-07 22:03:48.000000000 +0000
++++ git/arch/arm/common/sharpsl_pm.c   2006-11-07 22:04:20.000000000 +0000
+@@ -584,6 +584,9 @@ static int corgi_pxa_pm_enter(suspend_st
+       if (sharpsl_pm.machinfo->earlyresume)
+               sharpsl_pm.machinfo->earlyresume();
++      if (sharpsl_pm.machinfo->postresume)
++              sharpsl_pm.machinfo->postresume();
++      
+       dev_dbg(sharpsl_pm.dev, "SharpSL resuming...\n");
+       return 0;
diff --git a/packages/kexecboot/linux-kexecboot-2.6.23/sharpsl-rc-r1.patch b/packages/kexecboot/linux-kexecboot-2.6.23/sharpsl-rc-r1.patch
new file mode 100644 (file)
index 0000000..08f1f2e
--- /dev/null
@@ -0,0 +1,519 @@
+Index: linux-2.6.23/arch/arm/mach-pxa/spitz.c
+===================================================================
+--- linux-2.6.23.orig/arch/arm/mach-pxa/spitz.c
++++ linux-2.6.23/arch/arm/mach-pxa/spitz.c
+@@ -245,6 +245,13 @@ static struct platform_device spitzkbd_d
+       .id             = -1,
+ };
++/*
++ * Spitz Remote Control Device
++ */
++static struct platform_device sharpsl_rc_device = {
++      .name           = "sharpsl-remote-control",
++      .id             = -1,
++};
+ /*
+  * Spitz LEDs
+@@ -477,6 +484,7 @@ static struct platform_device *devices[]
+       &spitzscoop_device,
+       &spitzssp_device,
+       &spitzkbd_device,
++      &sharpsl_rc_device,
+       &spitzts_device,
+       &spitzbl_device,
+       &spitzled_device,
+Index: linux-2.6.23/drivers/input/keyboard/Kconfig
+===================================================================
+--- linux-2.6.23.orig/drivers/input/keyboard/Kconfig
++++ linux-2.6.23/drivers/input/keyboard/Kconfig
+@@ -154,6 +154,17 @@ config KEYBOARD_SPITZ
+         To compile this driver as a module, choose M here: the
+         module will be called spitzkbd.
++config SHARPSL_RC
++      tristate "Sharp SL-Cxx00 Remote Control"
++      depends on PXA_SHARPSL
++      default y
++      help
++        Say Y here to enable the remote on the Sharp Zaurus SL-Cxx00,
++        SL-C1000, SL-C3000 and Sl-C3100 series of PDAs.
++
++        To compile this driver as a module, choose M here: the
++        module will be called sharpsl_rc.
++
+ config KEYBOARD_AMIGA
+       tristate "Amiga keyboard"
+       depends on AMIGA
+Index: linux-2.6.23/drivers/input/keyboard/Makefile
+===================================================================
+--- linux-2.6.23.orig/drivers/input/keyboard/Makefile
++++ linux-2.6.23/drivers/input/keyboard/Makefile
+@@ -15,6 +15,7 @@ obj-$(CONFIG_KEYBOARD_NEWTON)                += newton
+ obj-$(CONFIG_KEYBOARD_STOWAWAY)               += stowaway.o
+ obj-$(CONFIG_KEYBOARD_CORGI)          += corgikbd.o
+ obj-$(CONFIG_KEYBOARD_SPITZ)          += spitzkbd.o
++obj-$(CONFIG_SHARPSL_RC)                      += sharpsl_rc.o
+ obj-$(CONFIG_KEYBOARD_HIL)            += hil_kbd.o
+ obj-$(CONFIG_KEYBOARD_HIL_OLD)                += hilkbd.o
+ obj-$(CONFIG_KEYBOARD_OMAP)           += omap-keypad.o
+Index: linux-2.6.23/drivers/input/keyboard/sharpsl_rc.c
+===================================================================
+--- /dev/null
++++ linux-2.6.23/drivers/input/keyboard/sharpsl_rc.c
+@@ -0,0 +1,291 @@
++/*
++ *  Keyboard driver for Sharp Clamshell Models (SL-Cxx00)
++ *
++ *  Copyright (c) 2004-2005 Richard Purdie
++ *
++ *  Based on corgikbd.c and Sharp's RC driver
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License version 2 as
++ *  published by the Free Software Foundation.
++ *
++ */
++
++#define DEBUG 1
++#include <linux/delay.h>
++#include <linux/platform_device.h>
++#include <linux/init.h>
++#include <linux/input.h>
++#include <linux/interrupt.h>
++#include <linux/jiffies.h>
++#include <linux/module.h>
++#include <linux/slab.h>
++
++#ifdef CONFIG_MACH_SPITZ
++#include <asm/arch/spitz.h>
++#endif
++#ifdef CONFIG_MACH_CORGI
++#include <asm/arch/corgi.h>
++#endif
++
++#include <asm/arch/hardware.h>
++#include <asm/arch/pxa-regs.h>
++#include <asm/hardware/scoop.h>
++#include <asm/arch/sharpsl.h>
++#include <asm/hardware/sharpsl_pm.h>
++
++#define DPRINTK(fmt, args...) dev_dbg(data->dev, fmt "\n", ##args)
++
++struct remote_control_key {
++      unsigned char min;
++      unsigned char max;
++      unsigned char key;
++};
++
++#ifdef CONFIG_MACH_SPITZ
++#define REMOTE_AKIN_PULLUP SPITZ_SCP2_AKIN_PULLUP
++#define REMOTE_SCOOP_DEVICE spitzscoop2_device
++#define REMOTE_GPIO_INT SPITZ_GPIO_AK_INT
++#define REMOTE_IRQ_INT SPITZ_IRQ_GPIO_AK_INT
++static struct remote_control_key remote_keys[] = {
++      { 25, 35, KEY_STOPCD},
++      { 55, 65, KEY_PLAYPAUSE},
++      { 85, 95, KEY_NEXTSONG},
++      { 115, 125, KEY_VOLUMEUP},
++      { 145, 155, KEY_PREVIOUSSONG},
++      { 180, 190, KEY_MUTE},
++      { 215, 225, KEY_VOLUMEDOWN},
++};
++#endif
++#ifdef CONFIG_MACH_CORGI
++#define REMOTE_AKIN_PULLUP CORGI_SCP_AKIN_PULLUP
++#define REMOTE_SCOOP_DEVICE corgiscoop_device
++#define REMOTE_GPIO_INT CORGI_GPIO_AK_INT
++#define REMOTE_IRQ_INT CORGI_IRQ_GPIO_AK_INT
++static struct remote_control_key remote_keys[] = {
++    //These need to be fixed for the CE-RH1's values
++      { 25, 35, KEY_STOPCD},
++      { 55, 65, KEY_PLAYPAUSE},
++      { 85, 95, KEY_NEXTSONG},
++      { 115, 125, KEY_VOLUMEUP},
++      { 145, 155, KEY_PREVIOUSSONG},
++      { 180, 190, KEY_MUTE},
++      { 215, 225, KEY_VOLUMEDOWN},
++};
++#endif
++
++#define RELEASE_HI      230
++#define MAX_EARPHONE    6
++#define RC_POLL_MS      10
++#define RC_FINISH_MS    500
++#define WAIT_STATE      3
++#define NOISE_THRESHOLD 100
++
++struct sharpsl_rc {
++      struct input_dev *input;
++      struct device *dev;
++
++      spinlock_t lock;
++      struct timer_list rctimer;
++      struct timer_list rctimer_finish;
++
++      unsigned int handling_press;
++      unsigned int noise;
++      unsigned int state;
++      unsigned int last_key;
++};
++
++static int get_remocon_raw(void)
++{
++      int i, val;
++
++      val = sharpsl_pm_pxa_read_max1111(MAX1111_REMCOM);
++      for (i = 0; i < ARRAY_SIZE(remote_keys); ++i) {
++              if (val >= remote_keys[i].min
++                      && val <= remote_keys[i].max) {
++                      printk("get_remocon_raw: VAL=%i, KEY=%i\n", val, remote_keys[i].key);
++                      return remote_keys[i].key;
++              }
++      }
++      return 0;
++}
++
++static irqreturn_t sharpsl_rc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
++{
++      struct sharpsl_rc *data = dev_id;
++      DPRINTK("sharpsl_rc_interrupt %d\n", irq);
++      if (!data->handling_press) {
++              DPRINTK("handling interrupt");
++              data->handling_press = 1;
++              data->noise = 0;
++              data->state = 0;
++              data->last_key = 0;
++
++              reset_scoop_gpio(&REMOTE_SCOOP_DEVICE.dev, REMOTE_AKIN_PULLUP);
++
++              mod_timer(&data->rctimer, jiffies + msecs_to_jiffies(RC_POLL_MS));
++      }
++      return IRQ_HANDLED;
++}
++
++static void sharpsl_rc_timer_callback(unsigned long dataPtr)
++{
++      struct sharpsl_rc *data = (struct sharpsl_rc *) dataPtr;
++      int timer = 1;
++      int key = get_remocon_raw();
++      DPRINTK("timer callback, key: %d", key);
++
++      //wait for value to stabilize
++      if (data->state < WAIT_STATE) {
++              if (data->last_key != key) {
++                      ++data->noise;
++                      if (data->noise > NOISE_THRESHOLD) {
++                              DPRINTK("too much noise, bailing");
++                              timer = 0;
++                      }
++                      data->state = 0;
++              } else {
++                      ++data->state;
++              }
++              data->last_key = key;
++
++      //stable value, send event
++      } else if (data->state == WAIT_STATE) {
++              data->noise = 0;
++              //non-key returned, skip the rest of the states and bail now
++              if (data->last_key == 0) {
++                      DPRINTK("non-key detected %d, noise: %d", data->last_key, data->noise);
++                      timer = 0;
++              //send button press
++              } else {
++                      DPRINTK("key press detected %d, noise %d", data->last_key, data->noise);
++                      input_report_key(data->input, data->last_key, 1);
++              }
++              ++data->state;
++
++      //wait until key is released
++      } else if (data->state < WAIT_STATE * 2) {
++              if (key == data->last_key
++                      && data->noise < NOISE_THRESHOLD) {
++                      data->state = WAIT_STATE + 1;
++                      ++data->noise;
++              } else {
++                      ++data->state;
++              }
++      //key is released, send event
++      } else {
++              //send button release
++              DPRINTK("release key %d", data->last_key);
++              input_report_key(data->input, data->last_key, 0);
++              timer = 0;
++      }
++      if (timer) {
++              mod_timer(&data->rctimer, jiffies + msecs_to_jiffies(RC_POLL_MS));
++      } else {
++              set_scoop_gpio(&REMOTE_SCOOP_DEVICE.dev, REMOTE_AKIN_PULLUP);
++              data->handling_press = 0;
++      }
++}
++
++static int __init sharpsl_rc_probe(struct platform_device *pdev)
++{
++      struct sharpsl_rc *sharpsl_rc;
++      struct input_dev *input_dev;
++      int i, ret;
++
++      dev_dbg(&pdev->dev, "sharpsl_rc_probe\n");
++
++      sharpsl_rc = kzalloc(sizeof(struct sharpsl_rc), GFP_KERNEL);
++      input_dev = input_allocate_device();
++      if (!sharpsl_rc || !input_dev) {
++              kfree(sharpsl_rc);
++              input_free_device(input_dev);
++              return -ENOMEM;
++      }
++
++      platform_set_drvdata(pdev, sharpsl_rc);
++
++      sharpsl_rc->dev = &pdev->dev;
++      sharpsl_rc->input = input_dev;
++      spin_lock_init(&sharpsl_rc->lock);
++
++      /* Init Remote Control Timer */
++      init_timer(&sharpsl_rc->rctimer);
++      sharpsl_rc->rctimer.function = sharpsl_rc_timer_callback;
++      sharpsl_rc->rctimer.data = (unsigned long) sharpsl_rc;
++
++      input_dev->name = "Sharp Remote Control CE-RHX";
++      input_dev->phys = "sharpsl_rc/input0";
++      input_dev->id.bustype = BUS_HOST;
++      input_dev->id.vendor = 0x0001;
++      input_dev->id.product = 0x0001;
++      input_dev->id.version = 0x0100;
++      input_dev->cdev.dev = &pdev->dev;
++      input_dev->private = sharpsl_rc;
++
++      input_dev->evbit[0] = BIT(EV_KEY);
++
++      for (i = 0; i <= ARRAY_SIZE(remote_keys); i++)
++        set_bit(remote_keys[i].key, input_dev->keybit);
++
++      input_register_device(sharpsl_rc->input);
++
++      pxa_gpio_mode(REMOTE_GPIO_INT | GPIO_IN);
++      ret = request_irq(REMOTE_IRQ_INT,
++                                        sharpsl_rc_interrupt,
++                                        IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_SHARED,
++                                        "sharpsl_rc",
++                                        sharpsl_rc);
++      if (ret < 0) {
++              dev_dbg(&pdev->dev, "Can't get IRQ: %d!\n", i);
++              kfree(sharpsl_rc);
++              input_free_device(input_dev);
++              return ret;
++      }
++
++      return 0;
++}
++
++static int sharpsl_rc_remove(struct platform_device *pdev)
++{
++      struct sharpsl_rc *sharpsl_rc = platform_get_drvdata(pdev);
++
++      dev_dbg(&pdev->dev, "sharpsl_rc_remove\n");
++
++      free_irq(REMOTE_IRQ_INT, sharpsl_rc);
++      del_timer_sync(&sharpsl_rc->rctimer);
++      input_unregister_device(sharpsl_rc->input);
++      kfree(sharpsl_rc);
++
++      return 0;
++}
++
++static struct platform_driver sharpsl_rc_driver = {
++      .probe          = sharpsl_rc_probe,
++      .remove         = sharpsl_rc_remove,
++      .suspend        = NULL,
++      .resume         = NULL,
++      .driver         = {
++              .name   = "sharpsl-remote-control",
++      },
++};
++
++static int __devinit sharpsl_rc_init(void)
++{
++      printk("sharpsl_rc_init\n");
++      return platform_driver_register(&sharpsl_rc_driver);
++}
++
++static void __exit sharpsl_rc_exit(void)
++{
++      printk("sharpsl_rc_exit\n");
++      platform_driver_unregister(&sharpsl_rc_driver);
++}
++
++module_init(sharpsl_rc_init);
++module_exit(sharpsl_rc_exit);
++
++MODULE_AUTHOR("Justin Patrin <papercrane@reversefold.com>");
++MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>");
++MODULE_DESCRIPTION("SharpSL Remote Control Driver");
++MODULE_LICENSE("GPL");
+Index: linux-2.6.23/drivers/input/keyboard/spitzkbd.c
+===================================================================
+--- linux-2.6.23.orig/drivers/input/keyboard/spitzkbd.c
++++ linux-2.6.23/drivers/input/keyboard/spitzkbd.c
+@@ -19,6 +19,7 @@
+ #include <linux/jiffies.h>
+ #include <linux/module.h>
+ #include <linux/slab.h>
++#include <linux/kmod.h>
+ #include <asm/arch/spitz.h>
+ #include <asm/arch/hardware.h>
+@@ -279,13 +280,21 @@ static irqreturn_t spitzkbd_hinge_isr(in
+ static int sharpsl_hinge_state;
+ static int hinge_count;
++void spitzkbd_handle_sharpsl_rc(void *arg) {
++      request_module("sharpsl_rc");
++}
++
++DECLARE_WORK(spitzkbd_work, spitzkbd_handle_sharpsl_rc);
++
+ static void spitzkbd_hinge_timer(unsigned long data)
+ {
+       struct spitzkbd *spitzkbd_data = (struct spitzkbd *) data;
+       unsigned long state;
+       unsigned long flags;
++      unsigned int headphone, remote;
+       state = GPLR(SPITZ_GPIO_SWA) & (GPIO_bit(SPITZ_GPIO_SWA)|GPIO_bit(SPITZ_GPIO_SWB));
++      state |= (GPLR(SPITZ_GPIO_HP_IN) & GPIO_bit(SPITZ_GPIO_HP_IN));
+       state |= (GPLR(SPITZ_GPIO_AK_INT) & GPIO_bit(SPITZ_GPIO_AK_INT));
+       if (state != sharpsl_hinge_state) {
+               hinge_count = 0;
+@@ -299,9 +308,18 @@ static void spitzkbd_hinge_timer(unsigne
+               input_report_switch(spitzkbd_data->input, SW_LID, ((GPLR(SPITZ_GPIO_SWA) & GPIO_bit(SPITZ_GPIO_SWA)) != 0));
+               input_report_switch(spitzkbd_data->input, SW_TABLET_MODE, ((GPLR(SPITZ_GPIO_SWB) & GPIO_bit(SPITZ_GPIO_SWB)) != 0));
+-              input_report_switch(spitzkbd_data->input, SW_HEADPHONE_INSERT, ((GPLR(SPITZ_GPIO_AK_INT) & GPIO_bit(SPITZ_GPIO_AK_INT)) != 0));
++
++              headphone = ((GPLR(SPITZ_GPIO_HP_IN) & GPIO_bit(SPITZ_GPIO_HP_IN)) != 0);
++              input_report_switch(spitzkbd_data->input, SW_HEADPHONE_INSERT, headphone);
++
++              remote = headphone && ((GPLR(SPITZ_GPIO_AK_INT) & GPIO_bit(SPITZ_GPIO_AK_INT)) == 0);
++              input_report_switch(spitzkbd_data->input, SW_REMOTE_INSERT, remote);
+               input_sync(spitzkbd_data->input);
++              if (remote) {
++                      schedule_work(&spitzkbd_work);
++              }
++
+               spin_unlock_irqrestore(&spitzkbd_data->lock, flags);
+       } else {
+               mod_timer(&spitzkbd_data->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL));
+@@ -393,6 +411,7 @@ static int __init spitzkbd_probe(struct 
+       set_bit(SW_LID, input_dev->swbit);
+       set_bit(SW_TABLET_MODE, input_dev->swbit);
+       set_bit(SW_HEADPHONE_INSERT, input_dev->swbit);
++      set_bit(SW_REMOTE_INSERT, input_dev->swbit);
+       err = input_register_device(input_dev);
+       if (err)
+@@ -430,9 +449,12 @@ static int __init spitzkbd_probe(struct 
+       request_irq(SPITZ_IRQ_GPIO_SWB, spitzkbd_hinge_isr,
+                   IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+                   "Spitzkbd SWB", spitzkbd);
+-      request_irq(SPITZ_IRQ_GPIO_AK_INT, spitzkbd_hinge_isr,
++      request_irq(SPITZ_IRQ_GPIO_HP_IN, spitzkbd_hinge_isr,
+                   IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+                   "Spitzkbd HP", spitzkbd);
++      request_irq(SPITZ_IRQ_GPIO_AK_INT, spitzkbd_hinge_isr,
++                  IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_SHARED,
++            "Spitzkbd HP Type", spitzkbd);
+       return 0;
+@@ -453,6 +475,7 @@ static int spitzkbd_remove(struct platfo
+       free_irq(SPITZ_IRQ_GPIO_ON_KEY, spitzkbd);
+       free_irq(SPITZ_IRQ_GPIO_SWA, spitzkbd);
+       free_irq(SPITZ_IRQ_GPIO_SWB, spitzkbd);
++      free_irq(SPITZ_IRQ_GPIO_HP_IN, spitzkbd);
+       free_irq(SPITZ_IRQ_GPIO_AK_INT, spitzkbd);
+       del_timer_sync(&spitzkbd->htimer);
+Index: linux-2.6.23/arch/arm/mach-pxa/sharpsl.h
+===================================================================
+--- linux-2.6.23.orig/arch/arm/mach-pxa/sharpsl.h
++++ linux-2.6.23/arch/arm/mach-pxa/sharpsl.h
+@@ -50,15 +50,10 @@ void spitz_wait_hsync(void);
+ #define READ_GPIO_BIT(x)    (GPLR(x) & GPIO_bit(x))
+-/* MAX1111 Channel Definitions */
+-#define MAX1111_BATT_VOLT   4u
+-#define MAX1111_BATT_TEMP   2u
+-#define MAX1111_ACIN_VOLT   6u
+-
+ extern struct battery_thresh spitz_battery_levels_acin[];
+ extern struct battery_thresh spitz_battery_levels_noac[];
+ void sharpsl_pm_pxa_init(void);
+ void sharpsl_pm_pxa_remove(void);
+-int sharpsl_pm_pxa_read_max1111(int channel);
++
+Index: linux-2.6.23/arch/arm/mach-pxa/sharpsl_pm.c
+===================================================================
+--- linux-2.6.23.orig/arch/arm/mach-pxa/sharpsl_pm.c
++++ linux-2.6.23/arch/arm/mach-pxa/sharpsl_pm.c
+@@ -135,6 +135,8 @@ int sharpsl_pm_pxa_read_max1111(int chan
+                       | MAXCTRL_SGL | MAXCTRL_UNI | MAXCTRL_STR);
+ }
++EXPORT_SYMBOL(sharpsl_pm_pxa_read_max1111);
++
+ void sharpsl_pm_pxa_init(void)
+ {
+       pxa_gpio_mode(sharpsl_pm.machinfo->gpio_acin | GPIO_IN);
+Index: linux-2.6.23/include/asm-arm/hardware/sharpsl_pm.h
+===================================================================
+--- linux-2.6.23.orig/include/asm-arm/hardware/sharpsl_pm.h
++++ linux-2.6.23/include/asm-arm/hardware/sharpsl_pm.h
+@@ -104,3 +104,10 @@ irqreturn_t sharpsl_ac_isr(int irq, void
+ irqreturn_t sharpsl_chrg_full_isr(int irq, void *dev_id);
+ irqreturn_t sharpsl_fatal_isr(int irq, void *dev_id);
++/* MAX1111 Channel Definitions */
++#define MAX1111_REMCOM      0u
++#define MAX1111_BATT_VOLT   4u
++#define MAX1111_BATT_TEMP   2u
++#define MAX1111_ACIN_VOLT   6u
++
++int sharpsl_pm_pxa_read_max1111(int channel);
+Index: linux-2.6.23/include/linux/input.h
+===================================================================
+--- linux-2.6.23.orig/include/linux/input.h
++++ linux-2.6.23/include/linux/input.h
+@@ -621,6 +621,7 @@ struct input_absinfo {
+ #define SW_TABLET_MODE                0x01  /* set = tablet mode */
+ #define SW_HEADPHONE_INSERT   0x02  /* set = inserted */
+ #define SW_RADIO              0x03  /* set = radio enabled */
++#define SW_REMOTE_INSERT      0x04  /* set = remote */
+ #define SW_MAX                        0x0f
+ /*
+Index: linux-2.6.23/arch/arm/mach-pxa/spitz_pm.c
+===================================================================
+--- linux-2.6.23.orig/arch/arm/mach-pxa/spitz_pm.c
++++ linux-2.6.23/arch/arm/mach-pxa/spitz_pm.c
+@@ -162,6 +162,13 @@ static int spitz_should_wakeup(unsigned 
+       if (resume_on_alarm && (PEDR & PWER_RTC))
+               is_resume |= PWER_RTC;
++      printk("wakeup: PEDR: %x, PKSR: %x, HP_IN: %x, AK_INT: %x\n", PEDR, PKSR, GPIO_bit(SPITZ_GPIO_HP_IN), GPIO_bit(SPITZ_GPIO_AK_INT));
++
++      //remote/headphone interrupt, wakeup
++      if (PEDR == 0 && (PKSR & 0xc0d01) != 0) {
++              is_resume |= PWER_RTC;
++      }
++
+       dev_dbg(sharpsl_pm.dev, "is_resume: %x\n",is_resume);
+       return is_resume;
+ }
diff --git a/packages/kexecboot/linux-kexecboot-2.6.23/spitz/defconfig b/packages/kexecboot/linux-kexecboot-2.6.23/spitz/defconfig
new file mode 100644 (file)
index 0000000..d3512f2
--- /dev/null
@@ -0,0 +1,1741 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.23
+# Thu Dec 27 17:03:44 2007
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_MMU=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ZONE_DMA=y
+CONFIG_ARCH_MTD_XIP=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=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_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+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_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=m
+CONFIG_IOSCHED_CFQ=m
+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_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_MXC 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_DAVINCI is not set
+# CONFIG_ARCH_OMAP 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=y
+# CONFIG_MACH_TRIZEPS4 is not set
+# CONFIG_MACH_EM_X270 is not set
+# CONFIG_MACH_HX2750 is not set
+# CONFIG_MACH_HTCUNIVERSAL is not set
+# CONFIG_PXA_SHARPSL_25x is not set
+CONFIG_PXA_SHARPSL_27x=y
+CONFIG_MACH_AKITA=y
+CONFIG_MACH_SPITZ=y
+CONFIG_MACH_BORZOI=y
+CONFIG_PXA27x=y
+CONFIG_PXA_SHARP_Cxx00=y
+CONFIG_PXA_SSP=y
+# CONFIG_PXA_KEYS is not set
+
+#
+# Boot options
+#
+
+#
+# Power management
+#
+
+#
+# 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
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_OUTER_CACHE is not set
+CONFIG_IWMMXT=y
+CONFIG_XSCALE_PMU=y
+CONFIG_SHARP_PARAM=y
+CONFIG_SHARPSL_PM=y
+CONFIG_SHARP_SCOOP=y
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI 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
+
+#
+# PC-card bridges
+#
+CONFIG_PCMCIA_PXA2XX=y
+
+#
+# Kernel Features
+#
+# CONFIG_TICK_ONESHOT is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_PREEMPT=y
+CONFIG_HZ=100
+CONFIG_AEABI=y
+CONFIG_OABI_COMPAT=y
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=ttyS0,115200n8 console=tty1 noinitrd root=/dev/hda1 rootfstype=ext3 rootdelay=1 rw  fbcon=rotate:1 dyntick=enable debug"
+# CONFIG_XIP_KERNEL is not set
+CONFIG_KEXEC=y
+CONFIG_ATAGS_PROC=y
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_AOUT=m
+CONFIG_BINFMT_MISC=m
+
+#
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND_UP_POSSIBLE=y
+CONFIG_SUSPEND=y
+CONFIG_APM_EMULATION=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=m
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=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=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IP_VS is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+# CONFIG_IPV6_MIP6 is not set
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=m
+CONFIG_IPV6_TUNNEL=m
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK is not set
+# CONFIG_NF_CONNTRACK_ENABLED is not set
+# CONFIG_NF_CONNTRACK is not set
+CONFIG_NETFILTER_XTABLES=m
+# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
+# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
+# CONFIG_NETFILTER_XT_TARGET_MARK is not set
+# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
+# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
+# CONFIG_NETFILTER_XT_TARGET_TRACE is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
+# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
+# CONFIG_NETFILTER_XT_MATCH_ESP is not set
+# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
+# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_MAC is not set
+# CONFIG_NETFILTER_XT_MATCH_MARK is not set
+# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
+# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
+# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
+# CONFIG_NETFILTER_XT_MATCH_REALM is not set
+# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
+# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
+# CONFIG_NETFILTER_XT_MATCH_STRING is not set
+# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_U32 is not set
+# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=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_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=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 is not set
+# CONFIG_IP6_NF_IPTABLES is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# 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 is not set
+
+#
+# IrDA options
+#
+# CONFIG_IRDA_CACHE_LAST_LSAP is not set
+# CONFIG_IRDA_FAST_RR is not set
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+# CONFIG_IRTTY_SIR is not set
+
+#
+# Dongle support
+#
+# CONFIG_KINGSUN_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=m
+# CONFIG_MCS_FIR is not set
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIUSB=m
+# CONFIG_BT_HCIUSB_SCO is not set
+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_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+CONFIG_WIRELESS_EXT=y
+# CONFIG_MAC80211 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_RFKILL is not set
+# CONFIG_NET_9P 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_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=m
+# 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_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=m
+CONFIG_MTD_BLKDEVS=m
+CONFIG_MTD_BLOCK=m
+# CONFIG_MTD_BLOCK_RO is not set
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+
+#
+# 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=m
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_SHARP_SL=m
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=m
+CONFIG_MTD_NAND_VERIFY_WRITE=y
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_H1900 is not set
+CONFIG_MTD_NAND_IDS=m
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+CONFIG_MTD_NAND_SHARPSL=m
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+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 is not set
+CONFIG_BLK_DEV_IDECS=y
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_PROC_FS=y
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_IDEPCI_PCIBUS_ORDER is not set
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=m
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=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 is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set
+# CONFIG_ATA is not set
+CONFIG_MD=y
+# CONFIG_BLK_DEV_MD is not set
+CONFIG_BLK_DEV_DM=m
+# CONFIG_DM_DEBUG is not set
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_EMC=m
+# CONFIG_DM_MULTIPATH_RDAC is not set
+# CONFIG_DM_DELAY is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+# CONFIG_AX88796 is not set
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+# CONFIG_SMC911X is not set
+CONFIG_NETDEV_1000=y
+CONFIG_NETDEV_10000=y
+
+#
+# Wireless LAN
+#
+CONFIG_WLAN_PRE80211=y
+# CONFIG_STRIP is not set
+# CONFIG_PCMCIA_WAVELAN is not set
+# CONFIG_PCMCIA_NETWAVE is not set
+CONFIG_WLAN_80211=y
+# CONFIG_PCMCIA_RAYCS is not set
+# CONFIG_LIBERTAS is not set
+CONFIG_HERMES=m
+# CONFIG_ATMEL is not set
+CONFIG_PCMCIA_HERMES=m
+CONFIG_PCMCIA_SPECTRUM=m
+CONFIG_AIRO_CS=m
+# CONFIG_PCMCIA_WL3501 is not set
+# CONFIG_USB_ZD1201 is not set
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+# CONFIG_HOSTAP_FIRMWARE_NVRAM is not set
+CONFIG_HOSTAP_CS=m
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET_MII=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_CDCETHER=m
+# CONFIG_USB_NET_DM9601 is not set
+# CONFIG_USB_NET_GL620A is not set
+CONFIG_USB_NET_NET1080=m
+# CONFIG_USB_NET_PLUSB is not set
+# CONFIG_USB_NET_MCS7830 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_NET_PCMCIA=y
+# CONFIG_PCMCIA_3C589 is not set
+# CONFIG_PCMCIA_3C574 is not set
+# CONFIG_PCMCIA_FMVJ18X is not set
+CONFIG_PCMCIA_PCNET=m
+# CONFIG_PCMCIA_NMCLAN is not set
+# CONFIG_PCMCIA_SMC91C92 is not set
+# CONFIG_PCMCIA_XIRC2PS is not set
+# CONFIG_PCMCIA_AXNET is not set
+# 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 is not set
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+# CONFIG_PPP_MPPE is not set
+# CONFIG_PPPOE is not set
+# CONFIG_PPPOL2TP is not set
+# CONFIG_SLIP is not set
+CONFIG_SLHC=m
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=m
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=640
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=480
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+CONFIG_INPUT_POWER=y
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_CORGI is not set
+CONFIG_KEYBOARD_SPITZ=y
+CONFIG_SHARPSL_RC=m
+# CONFIG_KEYBOARD_PXA27x is not set
+# CONFIG_KEYBOARD_GPIO is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_CORGI=y
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_UCB1400 is not set
+# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_ATI_REMOTE is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
+CONFIG_INPUT_UINPUT=m
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250_CS=m
+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_PXA=y
+CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_HW_RANDOM=m
+# CONFIG_NVRAM is not set
+# CONFIG_R3964 is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_CARDMAN_4000 is not set
+# CONFIG_CARDMAN_4040 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=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_GPIO is not set
+CONFIG_I2C_PXA=y
+# CONFIG_I2C_PXA_SLAVE is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_DS1682 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_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_EEPROM_93CX6 is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_ASIC3 is not set
+# CONFIG_HTC_ASIC3_DS1WM is not set
+
+#
+# Multi-Function Devices
+#
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+CONFIG_LEDS_SPITZ=y
+# CONFIG_LEDS_TOSA is not set
+# CONFIG_LEDS_GPIO is not set
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_IDE_DISK=y
+# CONFIG_LEDS_TRIGGER_HEARTBEAT is not set
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_VIDEO_V4L2=y
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_TUNER_3036 is not set
+# CONFIG_TUNER_TEA5761 is not set
+CONFIG_V4L_USB_DRIVERS=y
+# CONFIG_VIDEO_PVRUSB2 is not set
+# CONFIG_VIDEO_EM28XX is not set
+# CONFIG_VIDEO_USBVISION is not set
+# CONFIG_USB_VICAM is not set
+# CONFIG_USB_IBMCAM is not set
+# CONFIG_USB_KONICAWC is not set
+# CONFIG_USB_QUICKCAM_MESSENGER is not set
+# CONFIG_USB_ET61X251 is not set
+# CONFIG_VIDEO_OVCAMCHIP is not set
+# CONFIG_USB_W9968CF is not set
+# CONFIG_USB_OV511 is not set
+# CONFIG_USB_SE401 is not set
+# CONFIG_USB_SN9C102 is not set
+# CONFIG_USB_STV680 is not set
+# CONFIG_USB_ZC0301 is not set
+# CONFIG_USB_PWC is not set
+# CONFIG_USB_ZR364XX is not set
+CONFIG_RADIO_ADAPTERS=y
+# CONFIG_USB_DSBR is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
+CONFIG_USB_DABUSB=m
+
+#
+# Graphics support
+#
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_CORGI=y
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=m
+CONFIG_FB=y
+CONFIG_FIRMWARE_EDID=y
+# CONFIG_FB_DDC is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_SYS_FOPS is not set
+CONFIG_FB_DEFERRED_IO=y
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_PXA=y
+CONFIG_FB_PXA_LCD_QVGA=y
+# CONFIG_FB_PXA_LCD_VGA is not set
+CONFIG_FB_PXA_OVERLAY=y
+# CONFIG_FB_PXA_PARAMETERS is not set
+# CONFIG_FB_MBX is not set
+# CONFIG_FB_W100 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_DETECT_PRIMARY is not set
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+CONFIG_FONTS=y
+# CONFIG_FONT_8x8 is not set
+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
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+CONFIG_LOGO_OHAND_CLUT224=y
+# CONFIG_LOGO_OZ240_CLUT224 is not set
+# CONFIG_LOGO_OZ480_CLUT224 is not set
+# CONFIG_LOGO_OZ640_CLUT224 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 is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+# CONFIG_SND_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=y
+# CONFIG_SND_DEBUG_DETECT is not set
+# CONFIG_SND_PCM_XRUN_DEBUG is not set
+
+#
+# Generic devices
+#
+CONFIG_SND_AC97_CODEC=m
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_VIRMIDI is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# ALSA ARM devices
+#
+CONFIG_SND_PXA2XX_PCM=m
+CONFIG_SND_PXA2XX_AC97=m
+
+#
+# USB devices
+#
+CONFIG_SND_USB_AUDIO=m
+# CONFIG_SND_USB_CAIAQ is not set
+
+#
+# PCMCIA devices
+#
+# CONFIG_SND_VXPOCKET is not set
+# CONFIG_SND_PDAUDIOCF is not set
+
+#
+# System on Chip audio support
+#
+CONFIG_SND_SOC=m
+CONFIG_SND_PXA2XX_SOC=m
+CONFIG_SND_PXA2XX_SOC_I2S=m
+CONFIG_SND_PXA2XX_SOC_SPITZ=m
+
+#
+# SoC Audio support for SuperH
+#
+CONFIG_SND_SOC_WM8750=m
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+CONFIG_AC97_BUS=m
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=m
+# CONFIG_HID_DEBUG is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=m
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+CONFIG_USB_KBD=m
+CONFIG_USB_MOUSE=m
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_PERSIST is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_SL811_HCD=m
+CONFIG_USB_SL811_CS=m
+# CONFIG_USB_R8A66597_HCD is not set
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_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_KARMA is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+CONFIG_USB_MDC800=m
+CONFIG_USB_MICROTEK=m
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+# CONFIG_USB_SERIAL_AIRCABLE is not set
+# CONFIG_USB_SERIAL_AIRPRIME is not set
+# CONFIG_USB_SERIAL_ARK3116 is not set
+CONFIG_USB_SERIAL_BELKIN=m
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+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=m
+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_MOS7720 is not set
+# CONFIG_USB_SERIAL_MOS7840 is not set
+# CONFIG_USB_SERIAL_NAVMAN is not set
+CONFIG_USB_SERIAL_PL2303=m
+# CONFIG_USB_SERIAL_OTI6858 is not set
+# 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=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+# CONFIG_USB_SERIAL_OPTION is not set
+CONFIG_USB_SERIAL_OMNINET=m
+# CONFIG_USB_SERIAL_DEBUG is not set
+CONFIG_USB_EZUSB=y
+
+#
+# USB Miscellaneous drivers
+#
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+# CONFIG_USB_ADUTUX is not set
+CONFIG_USB_AUERSWALD=m
+CONFIG_USB_RIO500=m
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+# CONFIG_USB_BERRY_CHARGE is not set
+CONFIG_USB_LED=m
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+CONFIG_USB_CYTHERM=m
+# CONFIG_USB_PHIDGET is not set
+CONFIG_USB_IDMOUSE=m
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+CONFIG_USB_GADGET=m
+# CONFIG_USB_GADGET_DEBUG is not set
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_PXA2XX is not set
+# CONFIG_USB_GADGET_M66592 is not set
+CONFIG_USB_GADGET_PXA27X=y
+CONFIG_USB_PXA27X=m
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+# CONFIG_USB_GADGET_DUALSPEED is not set
+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
+# CONFIG_USB_MIDI_GADGET is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_UNSAFE_RESUME=y
+
+#
+# MMC/SD Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+
+#
+# MMC/SD Host Controller Drivers
+#
+CONFIG_MMC_PXA=y
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_SA1100=y
+
+#
+# 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 is not set
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+# CONFIG_MSDOS_FS is not set
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=m
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+CONFIG_JFFS2_SUMMARY=y
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_SYSFS is not set
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_LZO=y
+CONFIG_JFFS2_RTIME=y
+CONFIG_JFFS2_RUBIN=y
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
+CONFIG_CRAMFS=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 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=y
+# CONFIG_NFS_DIRECTIO is not set
+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_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+# CONFIG_SUNRPC_BIND34 is not set
+CONFIG_RPCSEC_GSS_KRB5=m
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+CONFIG_SMB_NLS_DEFAULT=y
+CONFIG_SMB_NLS_REMOTE="cp437"
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_WEAK_PW_HASH is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="cp437"
+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=m
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=y
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
+# Profiling support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+# CONFIG_DETECT_SOFTLOCKUP is not set
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_SCHEDSTATS is not set
+CONFIG_TIMER_STATS=y
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_PREEMPT is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_FORCED_INLINING is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_DEBUG_USER is not set
+CONFIG_DEBUG_ERRORS=y
+# CONFIG_DEBUG_LL is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+CONFIG_CRYPTO_DES=m
+# CONFIG_CRYPTO_FCRYPT is not set
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+# CONFIG_CRYPTO_LZO is not set
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_CAMELLIA is not set
+CONFIG_CRYPTO_TEST=m
+# CONFIG_CRYPTO_HW is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_LZO_COMPRESS=m
+CONFIG_LZO_DECOMPRESS=m
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/packages/kexecboot/linux-kexecboot-2.6.23/squashfs3.0-2.6.15.patch b/packages/kexecboot/linux-kexecboot-2.6.23/squashfs3.0-2.6.15.patch
new file mode 100644 (file)
index 0000000..a210afc
--- /dev/null
@@ -0,0 +1,4189 @@
+ fs/Kconfig                     |   65 +
+ fs/Makefile                    |    1 
+ fs/squashfs/Makefile           |    7 
+ fs/squashfs/inode.c            | 2122 +++++++++++++++++++++++++++++++++++++++++
+ fs/squashfs/squashfs.h         |   86 +
+ fs/squashfs/squashfs2_0.c      |  757 ++++++++++++++
+ include/linux/squashfs_fs.h    |  911 +++++++++++++++++
+ include/linux/squashfs_fs_i.h  |   45 
+ include/linux/squashfs_fs_sb.h |   74 +
+ init/do_mounts_rd.c            |   13 
+ 10 files changed, 4081 insertions(+)
+
+Index: linux-2.6.22/fs/Kconfig
+===================================================================
+--- linux-2.6.22.orig/fs/Kconfig       2007-08-28 21:56:32.000000000 +0100
++++ linux-2.6.22/fs/Kconfig    2007-08-28 21:56:34.000000000 +0100
+@@ -1394,6 +1394,71 @@ config CRAMFS
+         If unsure, say N.
++config SQUASHFS
++      tristate "SquashFS 3.0 - Squashed file system support"
++      select ZLIB_INFLATE
++      help
++        Saying Y here includes support for SquashFS 3.0 (a Compressed Read-Only File
++        System).  Squashfs is a highly compressed read-only filesystem for Linux.
++        It uses zlib compression to compress both files, inodes and directories.
++        Inodes in the system are very small and all blocks are packed to minimise
++        data overhead. Block sizes greater than 4K are supported up to a maximum of 64K.
++        SquashFS 3.0 supports 64 bit filesystems and files (larger than 4GB), full
++        uid/gid information, hard links and timestamps.
++
++        Squashfs is intended for general read-only filesystem use, for archival
++        use (i.e. in cases where a .tar.gz file may be used), and in embedded
++        systems where low overhead is needed.  Further information and filesystem tools
++        are available from http://squashfs.sourceforge.net.
++
++        If you want to compile this as a module ( = code which can be
++        inserted in and removed from the running kernel whenever you want),
++        say M here and read <file:Documentation/modules.txt>.  The module
++        will be called squashfs.  Note that the root file system (the one
++        containing the directory /) cannot be compiled as a module.
++
++        If unsure, say N.
++
++config SQUASHFS_EMBEDDED
++
++      bool "Additional options for memory-constrained systems" 
++      depends on SQUASHFS
++      default n
++      help
++        Saying Y here allows you to specify cache sizes and how Squashfs
++        allocates memory.  This is only intended for memory constrained
++        systems.
++
++        If unsure, say N.
++
++config SQUASHFS_FRAGMENT_CACHE_SIZE
++      int "Number of fragments cached" if SQUASHFS_EMBEDDED
++      depends on SQUASHFS
++      default "3"
++      help
++        By default SquashFS caches the last 3 fragments read from
++        the filesystem.  Increasing this amount may mean SquashFS
++        has to re-read fragments less often from disk, at the expense
++        of extra system memory.  Decreasing this amount will mean
++        SquashFS uses less memory at the expense of extra reads from disk.
++
++        Note there must be at least one cached fragment.  Anything
++        much more than three will probably not make much difference.
++
++config SQUASHFS_VMALLOC
++      bool "Use Vmalloc rather than Kmalloc" if SQUASHFS_EMBEDDED
++      depends on SQUASHFS
++      default n
++      help
++        By default SquashFS uses kmalloc to obtain fragment cache memory.
++        Kmalloc memory is the standard kernel allocator, but it can fail
++        on memory constrained systems.  Because of the way Vmalloc works,
++        Vmalloc can succeed when kmalloc fails.  Specifying this option
++        will make SquashFS always use Vmalloc to allocate the
++        fragment cache memory.
++
++        If unsure, say N.
++
+ config VXFS_FS
+       tristate "FreeVxFS file system support (VERITAS VxFS(TM) compatible)"
+       depends on BLOCK
+Index: linux-2.6.22/fs/Makefile
+===================================================================
+--- linux-2.6.22.orig/fs/Makefile      2007-08-28 21:54:14.000000000 +0100
++++ linux-2.6.22/fs/Makefile   2007-08-28 21:56:34.000000000 +0100
+@@ -72,6 +72,7 @@ obj-$(CONFIG_JBD)            += jbd/
+ obj-$(CONFIG_JBD2)            += jbd2/
+ obj-$(CONFIG_EXT2_FS)         += ext2/
+ obj-$(CONFIG_CRAMFS)          += cramfs/
++obj-$(CONFIG_SQUASHFS)                += squashfs/
+ obj-$(CONFIG_RAMFS)           += ramfs/
+ obj-$(CONFIG_HUGETLBFS)               += hugetlbfs/
+ obj-$(CONFIG_CODA_FS)         += coda/
+Index: linux-2.6.22/fs/squashfs/inode.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/fs/squashfs/inode.c   2007-08-28 22:12:03.000000000 +0100
+@@ -0,0 +1,2122 @@
++/*
++ * 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.
++ *
++ * inode.c
++ */
++
++#include <linux/types.h>
++#include <linux/squashfs_fs.h>
++#include <linux/module.h>
++#include <linux/errno.h>
++#include <linux/slab.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 void squashfs_put_super(struct super_block *);
++static int squashfs_statfs(struct dentry *, struct kstatfs *);
++static int squashfs_symlink_readpage(struct file *file, struct page *page);
++static int squashfs_readpage(struct file *file, struct page *page);
++static int squashfs_readpage4K(struct file *file, struct page *page);
++static int squashfs_readdir(struct file *, void *, filldir_t);
++static struct inode *squashfs_alloc_inode(struct super_block *sb);
++static void squashfs_destroy_inode(struct inode *inode);
++static int init_inodecache(void);
++static void destroy_inodecache(void);
++static struct dentry *squashfs_lookup(struct inode *, struct dentry *,
++                              struct nameidata *);
++static struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode);
++static long long read_blocklist(struct inode *inode, int index,
++                              int readahead_blks, char *block_list,
++                              unsigned short **block_p, unsigned int *bsize);
++static int squashfs_get_sb(struct file_system_type *, int,
++                              const char *, void *, struct vfsmount *);
++
++
++static z_stream stream;
++
++static struct file_system_type squashfs_fs_type = {
++      .owner = THIS_MODULE,
++      .name = "squashfs",
++      .get_sb = squashfs_get_sb,
++      .kill_sb = kill_block_super,
++      .fs_flags = FS_REQUIRES_DEV
++};
++
++static unsigned char squashfs_filetype_table[] = {
++      DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK
++};
++
++static struct super_operations squashfs_ops = {
++      .alloc_inode = squashfs_alloc_inode,
++      .destroy_inode = squashfs_destroy_inode,
++      .statfs = squashfs_statfs,
++      .put_super = squashfs_put_super,
++};
++
++SQSH_EXTERN struct address_space_operations squashfs_symlink_aops = {
++      .readpage = squashfs_symlink_readpage
++};
++
++SQSH_EXTERN struct address_space_operations squashfs_aops = {
++      .readpage = squashfs_readpage
++};
++
++SQSH_EXTERN struct address_space_operations squashfs_aops_4K = {
++      .readpage = squashfs_readpage4K
++};
++
++static struct file_operations squashfs_dir_ops = {
++      .read = generic_read_dir,
++      .readdir = squashfs_readdir
++};
++
++SQSH_EXTERN struct inode_operations squashfs_dir_inode_ops = {
++      .lookup = squashfs_lookup
++};
++
++
++static struct buffer_head *get_block_length(struct super_block *s,
++                              int *cur_index, int *offset, int *c_byte)
++{
++      struct squashfs_sb_info *msblk = s->s_fs_info;
++      unsigned short temp;
++      struct buffer_head *bh;
++
++      if (!(bh = sb_bread(s, *cur_index)))
++              goto out;
++
++      if (msblk->devblksize - *offset == 1) {
++              if (msblk->swap)
++                      ((unsigned char *) &temp)[1] = *((unsigned char *)
++                              (bh->b_data + *offset));
++              else
++                      ((unsigned char *) &temp)[0] = *((unsigned char *)
++                              (bh->b_data + *offset));
++              brelse(bh);
++              if (!(bh = sb_bread(s, ++(*cur_index))))
++                      goto out;
++              if (msblk->swap)
++                      ((unsigned char *) &temp)[0] = *((unsigned char *)
++                              bh->b_data); 
++              else
++                      ((unsigned char *) &temp)[1] = *((unsigned char *)
++                              bh->b_data); 
++              *c_byte = temp;
++              *offset = 1;
++      } else {
++              if (msblk->swap) {
++                      ((unsigned char *) &temp)[1] = *((unsigned char *)
++                              (bh->b_data + *offset));
++                      ((unsigned char *) &temp)[0] = *((unsigned char *)
++                              (bh->b_data + *offset + 1)); 
++              } else {
++                      ((unsigned char *) &temp)[0] = *((unsigned char *)
++                              (bh->b_data + *offset));
++                      ((unsigned char *) &temp)[1] = *((unsigned char *)
++                              (bh->b_data + *offset + 1)); 
++              }
++              *c_byte = temp;
++              *offset += 2;
++      }
++
++      if (SQUASHFS_CHECK_DATA(msblk->sblk.flags)) {
++              if (*offset == msblk->devblksize) {
++                      brelse(bh);
++                      if (!(bh = sb_bread(s, ++(*cur_index))))
++                              goto out;
++                      *offset = 0;
++              }
++              if (*((unsigned char *) (bh->b_data + *offset)) !=
++                                              SQUASHFS_MARKER_BYTE) {
++                      ERROR("Metadata block marker corrupt @ %x\n",
++                                              *cur_index);
++                      brelse(bh);
++                      goto out;
++              }
++              (*offset)++;
++      }
++      return bh;
++
++out:
++      return NULL;
++}
++
++
++SQSH_EXTERN unsigned int squashfs_read_data(struct super_block *s, char *buffer,
++                      long long index, unsigned int length,
++                      long long *next_index)
++{
++      struct squashfs_sb_info *msblk = s->s_fs_info;
++      struct buffer_head *bh[((SQUASHFS_FILE_MAX_SIZE - 1) >>
++                      msblk->devblksize_log2) + 2];
++      unsigned int offset = index & ((1 << msblk->devblksize_log2) - 1);
++      unsigned int cur_index = index >> msblk->devblksize_log2;
++      int bytes, avail_bytes, b = 0, k;
++      char *c_buffer;
++      unsigned int compressed;
++      unsigned int c_byte = length;
++
++      if (c_byte) {
++              bytes = msblk->devblksize - offset;
++              compressed = SQUASHFS_COMPRESSED_BLOCK(c_byte);
++              c_buffer = compressed ? msblk->read_data : buffer;
++              c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte);
++
++              TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed
++                                      ? "" : "un", (unsigned int) c_byte);
++
++              if (!(bh[0] = sb_getblk(s, cur_index)))
++                      goto block_release;
++
++              for (b = 1; bytes < c_byte; b++) {
++                      if (!(bh[b] = sb_getblk(s, ++cur_index)))
++                              goto block_release;
++                      bytes += msblk->devblksize;
++              }
++              ll_rw_block(READ, b, bh);
++      } else {
++              if (!(bh[0] = get_block_length(s, &cur_index, &offset,
++                                                              &c_byte)))
++                      goto read_failure;
++
++              bytes = msblk->devblksize - offset;
++              compressed = SQUASHFS_COMPRESSED(c_byte);
++              c_buffer = compressed ? msblk->read_data : buffer;
++              c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte);
++
++              TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed
++                                      ? "" : "un", (unsigned int) c_byte);
++
++              for (b = 1; bytes < c_byte; b++) {
++                      if (!(bh[b] = sb_getblk(s, ++cur_index)))
++                              goto block_release;
++                      bytes += msblk->devblksize;
++              }
++              ll_rw_block(READ, b - 1, bh + 1);
++      }
++
++      if (compressed)
++              down(&msblk->read_data_mutex);
++
++      for (bytes = 0, k = 0; k < b; k++) {
++              avail_bytes = (c_byte - bytes) > (msblk->devblksize - offset) ?
++                                      msblk->devblksize - offset :
++                                      c_byte - bytes;
++              wait_on_buffer(bh[k]);
++              if (!buffer_uptodate(bh[k]))
++                      goto block_release;
++              memcpy(c_buffer + bytes, bh[k]->b_data + offset, avail_bytes);
++              bytes += avail_bytes;
++              offset = 0;
++              brelse(bh[k]);
++      }
++
++      /*
++       * uncompress block
++       */
++      if (compressed) {
++              int zlib_err;
++
++              stream.next_in = c_buffer;
++              stream.avail_in = c_byte;
++              stream.next_out = buffer;
++              stream.avail_out = msblk->read_size;
++
++              if (((zlib_err = zlib_inflateInit(&stream)) != Z_OK) ||
++                              ((zlib_err = zlib_inflate(&stream, Z_FINISH))
++                               != Z_STREAM_END) || ((zlib_err =
++                              zlib_inflateEnd(&stream)) != Z_OK)) {
++                      ERROR("zlib_fs returned unexpected result 0x%x\n",
++                              zlib_err);
++                      bytes = 0;
++              } else
++                      bytes = stream.total_out;
++              
++              up(&msblk->read_data_mutex);
++      }
++
++      if (next_index)
++              *next_index = index + c_byte + (length ? 0 :
++                              (SQUASHFS_CHECK_DATA(msblk->sblk.flags)
++                               ? 3 : 2));
++      return bytes;
++
++block_release:
++      while (--b >= 0)
++              brelse(bh[b]);
++
++read_failure:
++      ERROR("sb_bread failed reading block 0x%x\n", cur_index);
++      return 0;
++}
++
++
++SQSH_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)
++{
++      struct squashfs_sb_info *msblk = s->s_fs_info;
++      int n, i, bytes, return_length = length;
++      long long next_index;
++
++      TRACE("Entered squashfs_get_cached_block [%llx:%x]\n", block, offset);
++
++      while ( 1 ) {
++              for (i = 0; i < SQUASHFS_CACHED_BLKS; i++) 
++                      if (msblk->block_cache[i].block == block)
++                              break; 
++              
++              down(&msblk->block_cache_mutex);
++
++              if (i == SQUASHFS_CACHED_BLKS) {
++                      /* read inode header block */
++                      for (i = msblk->next_cache, n = SQUASHFS_CACHED_BLKS;
++                                      n ; n --, i = (i + 1) %
++                                      SQUASHFS_CACHED_BLKS)
++                              if (msblk->block_cache[i].block !=
++                                                      SQUASHFS_USED_BLK)
++                                      break;
++
++                      if (n == 0) {
++                              wait_queue_t wait;
++
++                              init_waitqueue_entry(&wait, current);
++                              add_wait_queue(&msblk->waitq, &wait);
++                              set_current_state(TASK_UNINTERRUPTIBLE);
++                              up(&msblk->block_cache_mutex);
++                              schedule();
++                              set_current_state(TASK_RUNNING);
++                              remove_wait_queue(&msblk->waitq, &wait);
++                              continue;
++                      }
++                      msblk->next_cache = (i + 1) % SQUASHFS_CACHED_BLKS;
++
++                      if (msblk->block_cache[i].block ==
++                                                      SQUASHFS_INVALID_BLK) {
++                              if (!(msblk->block_cache[i].data =
++                                              kmalloc(SQUASHFS_METADATA_SIZE,
++                                              GFP_KERNEL))) {
++                                      ERROR("Failed to allocate cache"
++                                                      "block\n");
++                                      up(&msblk->block_cache_mutex);
++                                      goto out;
++                              }
++                      }
++      
++                      msblk->block_cache[i].block = SQUASHFS_USED_BLK;
++                      up(&msblk->block_cache_mutex);
++
++                      if (!(msblk->block_cache[i].length =
++                                              squashfs_read_data(s,
++                                              msblk->block_cache[i].data,
++                                              block, 0, &next_index))) {
++                              ERROR("Unable to read cache block [%llx:%x]\n",
++                                              block, offset);
++                              goto out;
++                      }
++
++                      down(&msblk->block_cache_mutex);
++                      wake_up(&msblk->waitq);
++                      msblk->block_cache[i].block = block;
++                      msblk->block_cache[i].next_index = next_index;
++                      TRACE("Read cache block [%llx:%x]\n", block, offset);
++              }
++
++              if (msblk->block_cache[i].block != block) {
++                      up(&msblk->block_cache_mutex);
++                      continue;
++              }
++
++              if ((bytes = msblk->block_cache[i].length - offset) >= length) {
++                      if (buffer)
++                              memcpy(buffer, msblk->block_cache[i].data +
++                                              offset, length);
++                      if (msblk->block_cache[i].length - offset == length) {
++                              *next_block = msblk->block_cache[i].next_index;
++                              *next_offset = 0;
++                      } else {
++                              *next_block = block;
++                              *next_offset = offset + length;
++                      }
++                      up(&msblk->block_cache_mutex);
++                      goto finish;
++              } else {
++                      if (buffer) {
++                              memcpy(buffer, msblk->block_cache[i].data +
++                                              offset, bytes);
++                              buffer += bytes;
++                      }
++                      block = msblk->block_cache[i].next_index;
++                      up(&msblk->block_cache_mutex);
++                      length -= bytes;
++                      offset = 0;
++              }
++      }
++
++finish:
++      return return_length;
++out:
++      return 0;
++}
++
++
++static int get_fragment_location(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[SQUASHFS_FRAGMENT_INDEX(fragment)];
++      int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment);
++      struct squashfs_fragment_entry fragment_entry;
++
++      if (msblk->swap) {
++              struct squashfs_fragment_entry 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(&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;
++}
++
++
++SQSH_EXTERN void release_cached_fragment(struct squashfs_sb_info *msblk, struct
++                                      squashfs_fragment_cache *fragment)
++{
++      down(&msblk->fragment_mutex);
++      fragment->locked --;
++      wake_up(&msblk->fragment_wait_queue);
++      up(&msblk->fragment_mutex);
++}
++
++
++SQSH_EXTERN struct squashfs_fragment_cache *get_cached_fragment(struct super_block
++                                      *s, long long start_block,
++                                      int length)
++{
++      int i, n, nf;
++      struct squashfs_sb_info *msblk = s->s_fs_info;
++
++      while ( 1 ) {
++              down(&msblk->fragment_mutex);
++
++              for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS &&
++                              msblk->fragment[i].block != start_block; i++);
++
++              if (i == SQUASHFS_CACHED_FRAGMENTS) {
++                      nf = (msblk->next_fragment + 1) % 
++                              SQUASHFS_CACHED_FRAGMENTS;
++                      for (i = msblk->next_fragment, n =
++                              SQUASHFS_CACHED_FRAGMENTS; n &&
++                              msblk->fragment[i].locked; n--, i = (i + 1) %
++                              SQUASHFS_CACHED_FRAGMENTS);
++
++                      if (n == 0) {
++                              wait_queue_t wait;
++
++                              init_waitqueue_entry(&wait, current);
++                              add_wait_queue(&msblk->fragment_wait_queue,
++                                                                      &wait);
++                              set_current_state(TASK_UNINTERRUPTIBLE);
++                              up(&msblk->fragment_mutex);
++                              schedule();
++                              set_current_state(TASK_RUNNING);
++                              remove_wait_queue(&msblk->fragment_wait_queue,
++                                                                      &wait);
++                              continue;
++                      }
++                      msblk->next_fragment = nf;
++                      
++                      if (msblk->fragment[i].data == NULL)
++                              if (!(msblk->fragment[i].data = SQUASHFS_ALLOC
++                                              (SQUASHFS_FILE_MAX_SIZE))) {
++                                      ERROR("Failed to allocate fragment "
++                                                      "cache block\n");
++                                      up(&msblk->fragment_mutex);
++                                      goto out;
++                              }
++
++                      msblk->fragment[i].block = SQUASHFS_INVALID_BLK;
++                      msblk->fragment[i].locked = 1;
++                      up(&msblk->fragment_mutex);
++
++                      if (!(msblk->fragment[i].length = squashfs_read_data(s,
++                                              msblk->fragment[i].data,
++                                              start_block, length, NULL))) {
++                              ERROR("Unable to read fragment cache block "
++                                                      "[%llx]\n", start_block);
++                              msblk->fragment[i].locked = 0;
++                              goto out;
++                      }
++
++                      msblk->fragment[i].block = start_block;
++                      TRACE("New fragment %d, start block %lld, locked %d\n",
++                                              i, msblk->fragment[i].block,
++                                              msblk->fragment[i].locked);
++                      break;
++              }
++
++              msblk->fragment[i].locked++;
++              up(&msblk->fragment_mutex);
++              TRACE("Got fragment %d, start block %lld, locked %d\n", i,
++                                              msblk->fragment[i].block,
++                                              msblk->fragment[i].locked);
++              break;
++      }
++
++      return &msblk->fragment[i];
++
++out:
++      return NULL;
++}
++
++
++static struct inode *squashfs_new_inode(struct super_block *s,
++              struct squashfs_base_inode_header *inodeb)
++{
++      struct squashfs_sb_info *msblk = s->s_fs_info;
++      struct inode *i = new_inode(s);
++
++      if (i) {
++              i->i_ino = inodeb->inode_number;
++              i->i_mtime.tv_sec = inodeb->mtime;
++              i->i_atime.tv_sec = inodeb->mtime;
++              i->i_ctime.tv_sec = inodeb->mtime;
++              i->i_uid = msblk->uid[inodeb->uid];
++              i->i_mode = inodeb->mode;
++              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(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;
++      long long block = SQUASHFS_INODE_BLK(inode) +
++              sblk->inode_table_start;
++      unsigned int offset = SQUASHFS_INODE_OFFSET(inode);
++      long long next_block;
++      unsigned int next_offset;
++      union squashfs_inode_header id, sid;
++      struct squashfs_base_inode_header *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(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: {
++                      unsigned int frag_size;
++                      long long frag_blk;
++                      struct squashfs_reg_inode_header *inodep = &id.reg;
++                      struct squashfs_reg_inode_header *sinodep = &sid.reg;
++                              
++                      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(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(s,
++                                      inodep->fragment, &frag_blk, &frag_size))
++                              goto failed_read;
++                              
++                      if((i = squashfs_new_inode(s, inodeb)) == NULL)
++                              goto failed_read1;
++
++                      i->i_nlink = 1;
++                      i->i_size = inodep->file_size;
++                      i->i_fop = &generic_ro_fops;
++                      i->i_mode |= S_IFREG;
++                      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 %llx, "
++                                      "block_list_start %llx, offset %x\n",
++                                      SQUASHFS_INODE_BLK(inode), offset,
++                                      inodep->start_block, next_block,
++                                      next_offset);
++                      break;
++              }
++              case SQUASHFS_LREG_TYPE: {
++                      unsigned int frag_size;
++                      long long frag_blk;
++                      struct squashfs_lreg_inode_header *inodep = &id.lreg;
++                      struct squashfs_lreg_inode_header *sinodep = &sid.lreg;
++                              
++                      if (msblk->swap) {
++                              if (!squashfs_get_cached_block(s, (char *)
++                                              sinodep, block, offset,
++                                              sizeof(*sinodep), &next_block,
++                                              &next_offset))
++                                      goto failed_read;
++                              SQUASHFS_SWAP_LREG_INODE_HEADER(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(s,
++                                      inodep->fragment, &frag_blk, &frag_size))
++                              goto failed_read;
++                              
++                      if((i = squashfs_new_inode(s, inodeb)) == NULL)
++                              goto failed_read1;
++
++                      i->i_nlink = inodep->nlink;
++                      i->i_size = inodep->file_size;
++                      i->i_fop = &generic_ro_fops;
++                      i->i_mode |= S_IFREG;
++                      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 %llx, "
++                                      "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 *inodep = &id.dir;
++                      struct squashfs_dir_inode_header *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(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)) == NULL)
++                              goto failed_read1;
++
++                      i->i_nlink = inodep->nlink;
++                      i->i_size = inodep->file_size;
++                      i->i_op = &squashfs_dir_inode_ops;
++                      i->i_fop = &squashfs_dir_ops;
++                      i->i_mode |= S_IFDIR;
++                      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 = inodep->parent_inode;
++
++                      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 *inodep = &id.ldir;
++                      struct squashfs_ldir_inode_header *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(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)) == NULL)
++                              goto failed_read1;
++
++                      i->i_nlink = inodep->nlink;
++                      i->i_size = inodep->file_size;
++                      i->i_op = &squashfs_dir_inode_ops;
++                      i->i_fop = &squashfs_dir_ops;
++                      i->i_mode |= S_IFDIR;
++                      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 = inodep->parent_inode;
++
++                      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 *inodep =
++                                                              &id.symlink;
++                      struct squashfs_symlink_inode_header *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(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)) == NULL)
++                              goto failed_read1;
++
++                      i->i_nlink = inodep->nlink;
++                      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 *inodep = &id.dev;
++                      struct squashfs_dev_inode_header *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(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)) == NULL)
++                              goto failed_read1;
++
++                      i->i_nlink = inodep->nlink;
++                      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: {
++                      struct squashfs_ipc_inode_header *inodep = &id.ipc;
++                      struct squashfs_ipc_inode_header *sinodep = &sid.ipc;
++
++                      if (msblk->swap) {
++                              if (!squashfs_get_cached_block(s, (char *)
++                                              sinodep, block, offset,
++                                              sizeof(*sinodep), &next_block,
++                                              &next_offset))
++                                      goto failed_read;
++                              SQUASHFS_SWAP_IPC_INODE_HEADER(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)) == NULL)
++                              goto failed_read1;
++
++                      i->i_nlink = inodep->nlink;
++                      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 [%llx:%x]\n", block, offset);
++
++failed_read1:
++      return NULL;
++}
++
++
++static int read_fragment_index_table(struct super_block *s)
++{
++      struct squashfs_sb_info *msblk = s->s_fs_info;
++      struct squashfs_super_block *sblk = &msblk->sblk;
++
++      /* Allocate fragment index table */
++      if (!(msblk->fragment_index = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES
++                                      (sblk->fragments), GFP_KERNEL))) {
++              ERROR("Failed to allocate uid/gid table\n");
++              return 0;
++      }
++   
++      if (SQUASHFS_FRAGMENT_INDEX_BYTES(sblk->fragments) &&
++                                      !squashfs_read_data(s, (char *)
++                                      msblk->fragment_index,
++                                      sblk->fragment_table_start,
++                                      SQUASHFS_FRAGMENT_INDEX_BYTES
++                                      (sblk->fragments) |
++                                      SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) {
++              ERROR("unable to read fragment index table\n");
++              return 0;
++      }
++
++      if (msblk->swap) {
++              int i;
++              long long fragment;
++
++              for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES(sblk->fragments);
++                                                                      i++) {
++                      SQUASHFS_SWAP_FRAGMENT_INDEXES((&fragment),
++                                              &msblk->fragment_index[i], 1);
++                      msblk->fragment_index[i] = fragment;
++              }
++      }
++
++      return 1;
++}
++
++
++static int supported_squashfs_filesystem(struct squashfs_sb_info *msblk, int silent)
++{
++      struct squashfs_super_block *sblk = &msblk->sblk;
++
++      msblk->iget = squashfs_iget;
++      msblk->read_blocklist = read_blocklist;
++      msblk->read_fragment_index_table = read_fragment_index_table;
++
++      if (sblk->s_major == 1) {
++              if (!squashfs_1_0_supported(msblk)) {
++                      SERROR("Major/Minor mismatch, Squashfs 1.0 filesystems "
++                              "are unsupported\n");
++                      SERROR("Please recompile with "
++                              "Squashfs 1.0 support enabled\n");
++                      return 0;
++              }
++      } else if (sblk->s_major == 2) {
++              if (!squashfs_2_0_supported(msblk)) {
++                      SERROR("Major/Minor mismatch, Squashfs 2.0 filesystems "
++                              "are unsupported\n");
++                      SERROR("Please recompile with "
++                              "Squashfs 2.0 support enabled\n");
++                      return 0;
++              }
++      } else if(sblk->s_major != SQUASHFS_MAJOR || sblk->s_minor >
++                      SQUASHFS_MINOR) {
++              SERROR("Major/Minor mismatch, trying to mount newer %d.%d "
++                              "filesystem\n", sblk->s_major, sblk->s_minor);
++              SERROR("Please update your kernel\n");
++              return 0;
++      }
++
++      return 1;
++}
++
++
++static int squashfs_fill_super(struct super_block *s, void *data, int silent)
++{
++      struct squashfs_sb_info *msblk;
++      struct squashfs_super_block *sblk;
++      int i;
++      char b[BDEVNAME_SIZE];
++      struct inode *root;
++
++      TRACE("Entered squashfs_read_superblock\n");
++
++      if (!(s->s_fs_info = kmalloc(sizeof(struct squashfs_sb_info),
++                                              GFP_KERNEL))) {
++              ERROR("Failed to allocate superblock\n");
++              goto failure;
++      }
++      memset(s->s_fs_info, 0, sizeof(struct squashfs_sb_info));
++      msblk = s->s_fs_info;
++      sblk = &msblk->sblk;
++      
++      msblk->devblksize = sb_min_blocksize(s, BLOCK_SIZE);
++      msblk->devblksize_log2 = ffz(~msblk->devblksize);
++
++      init_MUTEX(&msblk->read_data_mutex);
++      init_MUTEX(&msblk->read_page_mutex);
++      init_MUTEX(&msblk->block_cache_mutex);
++      init_MUTEX(&msblk->fragment_mutex);
++      init_MUTEX(&msblk->meta_index_mutex);
++      
++      init_waitqueue_head(&msblk->waitq);
++      init_waitqueue_head(&msblk->fragment_wait_queue);
++
++      if (!squashfs_read_data(s, (char *) sblk, SQUASHFS_START,
++                                      sizeof(struct squashfs_super_block) |
++                                      SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) {
++              SERROR("unable to read superblock\n");
++              goto failed_mount;
++      }
++
++      /* Check it is a SQUASHFS superblock */
++      msblk->swap = 0;
++      if ((s->s_magic = sblk->s_magic) != SQUASHFS_MAGIC) {
++              if (sblk->s_magic == SQUASHFS_MAGIC_SWAP) {
++                      struct squashfs_super_block ssblk;
++
++                      WARNING("Mounting a different endian SQUASHFS "
++                              "filesystem on %s\n", bdevname(s->s_bdev, b));
++
++                      SQUASHFS_SWAP_SUPER_BLOCK(&ssblk, sblk);
++                      memcpy(sblk, &ssblk, sizeof(struct squashfs_super_block));
++                      msblk->swap = 1;
++              } else  {
++                      SERROR("Can't find a SQUASHFS superblock on %s\n",
++                                                      bdevname(s->s_bdev, b));
++                      goto failed_mount;
++              }
++      }
++
++      /* Check the MAJOR & MINOR versions */
++      if(!supported_squashfs_filesystem(msblk, silent))
++              goto failed_mount;
++
++      TRACE("Found valid superblock on %s\n", bdevname(s->s_bdev, b));
++      TRACE("Inodes are %scompressed\n",
++                                      SQUASHFS_UNCOMPRESSED_INODES
++                                      (sblk->flags) ? "un" : "");
++      TRACE("Data is %scompressed\n",
++                                      SQUASHFS_UNCOMPRESSED_DATA(sblk->flags)
++                                      ? "un" : "");
++      TRACE("Check data is %s present in the filesystem\n",
++                                      SQUASHFS_CHECK_DATA(sblk->flags) ?
++                                      "" : "not");
++      TRACE("Filesystem size %lld bytes\n", sblk->bytes_used);
++      TRACE("Block size %d\n", sblk->block_size);
++      TRACE("Number of inodes %d\n", sblk->inodes);
++      if (sblk->s_major > 1)
++              TRACE("Number of fragments %d\n", sblk->fragments);
++      TRACE("Number of uids %d\n", sblk->no_uids);
++      TRACE("Number of gids %d\n", sblk->no_guids);
++      TRACE("sblk->inode_table_start %llx\n", sblk->inode_table_start);
++      TRACE("sblk->directory_table_start %llx\n", sblk->directory_table_start);
++      if (sblk->s_major > 1)
++              TRACE("sblk->fragment_table_start %llx\n",
++                                      sblk->fragment_table_start);
++      TRACE("sblk->uid_start %llx\n", sblk->uid_start);
++
++      s->s_flags |= MS_RDONLY;
++      s->s_op = &squashfs_ops;
++
++      /* Init inode_table block pointer array */
++      if (!(msblk->block_cache = kmalloc(sizeof(struct squashfs_cache) *
++                                      SQUASHFS_CACHED_BLKS, GFP_KERNEL))) {
++              ERROR("Failed to allocate block cache\n");
++              goto failed_mount;
++      }
++
++      for (i = 0; i < SQUASHFS_CACHED_BLKS; i++)
++              msblk->block_cache[i].block = SQUASHFS_INVALID_BLK;
++
++      msblk->next_cache = 0;
++
++      /* Allocate read_data block */
++      msblk->read_size = (sblk->block_size < SQUASHFS_METADATA_SIZE) ?
++                                      SQUASHFS_METADATA_SIZE :
++                                      sblk->block_size;
++
++      if (!(msblk->read_data = kmalloc(msblk->read_size, GFP_KERNEL))) {
++              ERROR("Failed to allocate read_data block\n");
++              goto failed_mount;
++      }
++
++      /* Allocate read_page block */
++      if (!(msblk->read_page = kmalloc(sblk->block_size, GFP_KERNEL))) {
++              ERROR("Failed to allocate read_page block\n");
++              goto failed_mount;
++      }
++
++      /* Allocate uid and gid tables */
++      if (!(msblk->uid = kmalloc((sblk->no_uids + sblk->no_guids) *
++                                      sizeof(unsigned int), GFP_KERNEL))) {
++              ERROR("Failed to allocate uid/gid table\n");
++              goto failed_mount;
++      }
++      msblk->guid = msblk->uid + sblk->no_uids;
++   
++      if (msblk->swap) {
++              unsigned int suid[sblk->no_uids + sblk->no_guids];
++
++              if (!squashfs_read_data(s, (char *) &suid, sblk->uid_start,
++                                      ((sblk->no_uids + sblk->no_guids) *
++                                       sizeof(unsigned int)) |
++                                      SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) {
++                      ERROR("unable to read uid/gid table\n");
++                      goto failed_mount;
++              }
++
++              SQUASHFS_SWAP_DATA(msblk->uid, suid, (sblk->no_uids +
++                      sblk->no_guids), (sizeof(unsigned int) * 8));
++      } else
++              if (!squashfs_read_data(s, (char *) msblk->uid, sblk->uid_start,
++                                      ((sblk->no_uids + sblk->no_guids) *
++                                       sizeof(unsigned int)) |
++                                      SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) {
++                      ERROR("unable to read uid/gid table\n");
++                      goto failed_mount;
++              }
++
++
++      if (sblk->s_major == 1 && squashfs_1_0_supported(msblk))
++              goto allocate_root;
++
++      if (!(msblk->fragment = kmalloc(sizeof(struct squashfs_fragment_cache) *
++                              SQUASHFS_CACHED_FRAGMENTS, GFP_KERNEL))) {
++              ERROR("Failed to allocate fragment block cache\n");
++              goto failed_mount;
++      }
++
++      for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) {
++              msblk->fragment[i].locked = 0;
++              msblk->fragment[i].block = SQUASHFS_INVALID_BLK;
++              msblk->fragment[i].data = NULL;
++      }
++
++      msblk->next_fragment = 0;
++
++      /* Allocate fragment index table */
++      if (msblk->read_fragment_index_table(s) == 0)
++              goto failed_mount;
++
++allocate_root:
++      if ((root = (msblk->iget)(s, sblk->root_inode)) == NULL)
++              goto failed_mount;
++
++      if ((s->s_root = d_alloc_root(root)) == NULL) {
++              ERROR("Root inode create failed\n");
++              iput(root);
++              goto failed_mount;
++      }
++
++      TRACE("Leaving squashfs_read_super\n");
++      return 0;
++
++failed_mount:
++      kfree(msblk->fragment_index);
++      kfree(msblk->fragment);
++      kfree(msblk->uid);
++      kfree(msblk->read_page);
++      kfree(msblk->read_data);
++      kfree(msblk->block_cache);
++      kfree(msblk->fragment_index_2);
++      kfree(s->s_fs_info);
++      s->s_fs_info = NULL;
++      return -EINVAL;
++
++failure:
++      return -ENOMEM;
++}
++
++
++static int squashfs_statfs(struct dentry *dentry, struct kstatfs *buf)
++{
++      struct super_block *s = dentry->d_sb;
++      struct squashfs_sb_info *msblk = s->s_fs_info;
++      struct squashfs_super_block *sblk = &msblk->sblk;
++
++      TRACE("Entered squashfs_statfs\n");
++
++      buf->f_type = SQUASHFS_MAGIC;
++      buf->f_bsize = sblk->block_size;
++      buf->f_blocks = ((sblk->bytes_used - 1) >> sblk->block_log) + 1;
++      buf->f_bfree = buf->f_bavail = 0;
++      buf->f_files = sblk->inodes;
++      buf->f_ffree = 0;
++      buf->f_namelen = SQUASHFS_NAME_LEN;
++
++      return 0;
++}
++
++
++static int squashfs_symlink_readpage(struct file *file, struct page *page)
++{
++      struct inode *inode = page->mapping->host;
++      int index = page->index << PAGE_CACHE_SHIFT, length, bytes;
++      long long block = SQUASHFS_I(inode)->start_block;
++      int offset = SQUASHFS_I(inode)->offset;
++      void *pageaddr = kmap(page);
++
++      TRACE("Entered squashfs_symlink_readpage, page index %ld, start block "
++                              "%llx, offset %x\n", page->index,
++                              SQUASHFS_I(inode)->start_block,
++                              SQUASHFS_I(inode)->offset);
++
++      for (length = 0; length < index; length += bytes) {
++              if (!(bytes = squashfs_get_cached_block(inode->i_sb, NULL,
++                              block, offset, PAGE_CACHE_SIZE, &block,
++                              &offset))) {
++                      ERROR("Unable to read symbolic link [%llx:%x]\n", block,
++                                      offset);
++                      goto skip_read;
++              }
++      }
++
++      if (length != index) {
++              ERROR("(squashfs_symlink_readpage) length != index\n");
++              bytes = 0;
++              goto skip_read;
++      }
++
++      bytes = (i_size_read(inode) - length) > PAGE_CACHE_SIZE ? PAGE_CACHE_SIZE :
++                                      i_size_read(inode) - length;
++
++      if (!(bytes = squashfs_get_cached_block(inode->i_sb, pageaddr, block,
++                                      offset, bytes, &block, &offset)))
++              ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset);
++
++skip_read:
++      memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);
++      kunmap(page);
++      SetPageUptodate(page);
++      unlock_page(page);
++
++      return 0;
++}
++
++
++struct meta_index *locate_meta_index(struct inode *inode, int index, int offset)
++{
++      struct meta_index *meta = NULL;
++      struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
++      int i;
++
++      down(&msblk->meta_index_mutex);
++
++      TRACE("locate_meta_index: index %d, offset %d\n", index, offset);
++
++      if(msblk->meta_index == NULL)
++              goto not_allocated;
++
++      for (i = 0; i < SQUASHFS_META_NUMBER; i ++)
++              if (msblk->meta_index[i].inode_number == inode->i_ino &&
++                              msblk->meta_index[i].offset >= offset &&
++                              msblk->meta_index[i].offset <= index &&
++                              msblk->meta_index[i].locked == 0) {
++                      TRACE("locate_meta_index: entry %d, offset %d\n", i,
++                                      msblk->meta_index[i].offset);
++                      meta = &msblk->meta_index[i];
++                      offset = meta->offset;
++              }
++
++      if (meta)
++              meta->locked = 1;
++
++not_allocated:
++      up(&msblk->meta_index_mutex);
++
++      return meta;
++}
++
++
++struct meta_index *empty_meta_index(struct inode *inode, int offset, int skip)
++{
++      struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
++      struct meta_index *meta = NULL;
++      int i;
++
++      down(&msblk->meta_index_mutex);
++
++      TRACE("empty_meta_index: offset %d, skip %d\n", offset, skip);
++
++      if(msblk->meta_index == NULL) {
++              if (!(msblk->meta_index = kmalloc(sizeof(struct meta_index) *
++                                      SQUASHFS_META_NUMBER, GFP_KERNEL))) {
++                      ERROR("Failed to allocate meta_index\n");
++                      goto failed;
++              }
++              for(i = 0; i < SQUASHFS_META_NUMBER; i++) {
++                      msblk->meta_index[i].inode_number = 0;
++                      msblk->meta_index[i].locked = 0;
++              }
++              msblk->next_meta_index = 0;
++      }
++
++      for(i = SQUASHFS_META_NUMBER; i &&
++                      msblk->meta_index[msblk->next_meta_index].locked; i --)
++              msblk->next_meta_index = (msblk->next_meta_index + 1) %
++                      SQUASHFS_META_NUMBER;
++
++      if(i == 0) {
++              TRACE("empty_meta_index: failed!\n");
++              goto failed;
++      }
++
++      TRACE("empty_meta_index: returned meta entry %d, %p\n",
++                      msblk->next_meta_index,
++                      &msblk->meta_index[msblk->next_meta_index]);
++
++      meta = &msblk->meta_index[msblk->next_meta_index];
++      msblk->next_meta_index = (msblk->next_meta_index + 1) %
++                      SQUASHFS_META_NUMBER;
++
++      meta->inode_number = inode->i_ino;
++      meta->offset = offset;
++      meta->skip = skip;
++      meta->entries = 0;
++      meta->locked = 1;
++
++failed:
++      up(&msblk->meta_index_mutex);
++      return meta;
++}
++
++
++void release_meta_index(struct inode *inode, struct meta_index *meta)
++{
++      meta->locked = 0;
++}
++
++
++static int read_block_index(struct super_block *s, int blocks, char *block_list,
++              long long *start_block, int *offset)
++{
++      struct squashfs_sb_info *msblk = s->s_fs_info;
++      unsigned int *block_listp;
++      int block = 0;
++      
++      if (msblk->swap) {
++              char sblock_list[blocks << 2];
++
++              if (!squashfs_get_cached_block(s, sblock_list, *start_block,
++                              *offset, blocks << 2, start_block, offset)) {
++                      ERROR("Unable to read block list [%llx:%x]\n",
++                              *start_block, *offset);
++                      goto failure;
++              }
++              SQUASHFS_SWAP_INTS(((unsigned int *)block_list),
++                              ((unsigned int *)sblock_list), blocks);
++      } else
++              if (!squashfs_get_cached_block(s, block_list, *start_block,
++                              *offset, blocks << 2, start_block, offset)) {
++                      ERROR("Unable to read block list [%llx:%x]\n",
++                              *start_block, *offset);
++                      goto failure;
++              }
++
++      for (block_listp = (unsigned int *) block_list; blocks;
++                              block_listp++, blocks --)
++              block += SQUASHFS_COMPRESSED_SIZE_BLOCK(*block_listp);
++
++      return block;
++
++failure:
++      return -1;
++}
++
++
++#define SIZE 256
++
++static inline int calculate_skip(int blocks) {
++      int skip = (blocks - 1) / ((SQUASHFS_SLOTS * SQUASHFS_META_ENTRIES + 1) * SQUASHFS_META_INDEXES);
++      return skip >= 7 ? 7 : skip + 1;
++}
++
++
++static int get_meta_index(struct inode *inode, int index,
++              long long *index_block, int *index_offset,
++              long long *data_block, char *block_list)
++{
++      struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
++      struct squashfs_super_block *sblk = &msblk->sblk;
++      int skip = calculate_skip(i_size_read(inode) >> sblk->block_log);
++      int offset = 0;
++      struct meta_index *meta;
++      struct meta_entry *meta_entry;
++      long long cur_index_block = SQUASHFS_I(inode)->u.s1.block_list_start;
++      int cur_offset = SQUASHFS_I(inode)->offset;
++      long long cur_data_block = SQUASHFS_I(inode)->start_block;
++      int i;
++ 
++      index /= SQUASHFS_META_INDEXES * skip;
++
++      while ( offset < index ) {
++              meta = locate_meta_index(inode, index, offset + 1);
++
++              if (meta == NULL) {
++                      if ((meta = empty_meta_index(inode, offset + 1,
++                                                      skip)) == NULL)
++                              goto all_done;
++              } else {
++                      offset = index < meta->offset + meta->entries ? index :
++                              meta->offset + meta->entries - 1;
++                      meta_entry = &meta->meta_entry[offset - meta->offset];
++                      cur_index_block = meta_entry->index_block + sblk->inode_table_start;
++                      cur_offset = meta_entry->offset;
++                      cur_data_block = meta_entry->data_block;
++                      TRACE("get_meta_index: offset %d, meta->offset %d, "
++                              "meta->entries %d\n", offset, meta->offset,
++                              meta->entries);
++                      TRACE("get_meta_index: index_block 0x%llx, offset 0x%x"
++                              " data_block 0x%llx\n", cur_index_block,
++                              cur_offset, cur_data_block);
++              }
++
++              for (i = meta->offset + meta->entries; i <= index &&
++                              i < meta->offset + SQUASHFS_META_ENTRIES; i++) {
++                      int blocks = skip * SQUASHFS_META_INDEXES;
++
++                      while (blocks) {
++                              int block = blocks > (SIZE >> 2) ? (SIZE >> 2) :
++                                      blocks;
++                              int res = read_block_index(inode->i_sb, block,
++                                      block_list, &cur_index_block,
++                                      &cur_offset);
++
++                              if (res == -1)
++                                      goto failed;
++
++                              cur_data_block += res;
++                              blocks -= block;
++                      }
++
++                      meta_entry = &meta->meta_entry[i - meta->offset];
++                      meta_entry->index_block = cur_index_block - sblk->inode_table_start;
++                      meta_entry->offset = cur_offset;
++                      meta_entry->data_block = cur_data_block;
++                      meta->entries ++;
++                      offset ++;
++              }
++
++              TRACE("get_meta_index: meta->offset %d, meta->entries %d\n",
++                              meta->offset, meta->entries);
++
++              release_meta_index(inode, meta);
++      }
++
++all_done:
++      *index_block = cur_index_block;
++      *index_offset = cur_offset;
++      *data_block = cur_data_block;
++
++      return offset * SQUASHFS_META_INDEXES * skip;
++
++failed:
++      release_meta_index(inode, meta);
++      return -1;
++}
++
++
++static long long read_blocklist(struct inode *inode, int index,
++                              int readahead_blks, char *block_list,
++                              unsigned short **block_p, unsigned int *bsize)
++{
++      long long block_ptr;
++      int offset;
++      long long block;
++      int res = get_meta_index(inode, index, &block_ptr, &offset, &block,
++              block_list);
++
++      TRACE("read_blocklist: res %d, index %d, block_ptr 0x%llx, offset"
++                     " 0x%x, block 0x%llx\n", res, index, block_ptr, offset,
++                     block);
++
++      if(res == -1)
++              goto failure;
++
++      index -= res;
++
++      while ( index ) {
++              int blocks = index > (SIZE >> 2) ? (SIZE >> 2) : index;
++              int res = read_block_index(inode->i_sb, blocks, block_list,
++                      &block_ptr, &offset);
++              if (res == -1)
++                      goto failure;
++              block += res;
++              index -= blocks;
++      }
++
++      if (read_block_index(inode->i_sb, 1, block_list,
++                      &block_ptr, &offset) == -1)
++              goto failure;
++      *bsize = *((unsigned int *) block_list);
++
++      return block;
++
++failure:
++      return 0;
++}
++
++
++static int squashfs_readpage(struct file *file, struct page *page)
++{
++      struct inode *inode = page->mapping->host;
++      struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
++      struct squashfs_super_block *sblk = &msblk->sblk;
++      unsigned char block_list[SIZE];
++      long long block;
++      unsigned int bsize, i = 0, bytes = 0, byte_offset = 0;
++      int index = page->index >> (sblk->block_log - PAGE_CACHE_SHIFT);
++      void *pageaddr;
++      struct squashfs_fragment_cache *fragment = NULL;
++      char *data_ptr = msblk->read_page;
++      
++      int mask = (1 << (sblk->block_log - PAGE_CACHE_SHIFT)) - 1;
++      int start_index = page->index & ~mask;
++      int end_index = start_index | mask;
++
++      TRACE("Entered squashfs_readpage, page index %lx, start block %llx\n",
++                                      page->index,
++                                      SQUASHFS_I(inode)->start_block);
++
++      if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>
++                                      PAGE_CACHE_SHIFT))
++              goto skip_read;
++
++      if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK
++                                      || index < (i_size_read(inode) >>
++                                      sblk->block_log)) {
++              if ((block = (msblk->read_blocklist)(inode, index, 1,
++                                      block_list, NULL, &bsize)) == 0)
++                      goto skip_read;
++
++              down(&msblk->read_page_mutex);
++              
++              if (!(bytes = squashfs_read_data(inode->i_sb, msblk->read_page,
++                                      block, bsize, NULL))) {
++                      ERROR("Unable to read page, block %llx, size %x\n", block,
++                                      bsize);
++                      up(&msblk->read_page_mutex);
++                      goto skip_read;
++              }
++      } else {
++              if ((fragment = get_cached_fragment(inode->i_sb,
++                                      SQUASHFS_I(inode)->
++                                      u.s1.fragment_start_block,
++                                      SQUASHFS_I(inode)->u.s1.fragment_size))
++                                      == NULL) {
++                      ERROR("Unable to read page, block %llx, size %x\n",
++                                      SQUASHFS_I(inode)->
++                                      u.s1.fragment_start_block,
++                                      (int) SQUASHFS_I(inode)->
++                                      u.s1.fragment_size);
++                      goto skip_read;
++              }
++              bytes = SQUASHFS_I(inode)->u.s1.fragment_offset +
++                                      (i_size_read(inode) & (sblk->block_size
++                                      - 1));
++              byte_offset = SQUASHFS_I(inode)->u.s1.fragment_offset;
++              data_ptr = fragment->data;
++      }
++
++      for (i = start_index; i <= end_index && byte_offset < bytes;
++                                      i++, byte_offset += PAGE_CACHE_SIZE) {
++              struct page *push_page;
++              int available_bytes = (bytes - byte_offset) > PAGE_CACHE_SIZE ?
++                                      PAGE_CACHE_SIZE : bytes - byte_offset;
++
++              TRACE("bytes %d, i %d, byte_offset %d, available_bytes %d\n",
++                                      bytes, i, byte_offset, available_bytes);
++
++              if (i == page->index)  {
++                      pageaddr = kmap_atomic(page, KM_USER0);
++                      memcpy(pageaddr, data_ptr + byte_offset,
++                                      available_bytes);
++                      memset(pageaddr + available_bytes, 0,
++                                      PAGE_CACHE_SIZE - available_bytes);
++                      kunmap_atomic(pageaddr, KM_USER0);
++                      flush_dcache_page(page);
++                      SetPageUptodate(page);
++                      unlock_page(page);
++              } else if ((push_page =
++                              grab_cache_page_nowait(page->mapping, i))) {
++                      pageaddr = kmap_atomic(push_page, KM_USER0);
++
++                      memcpy(pageaddr, data_ptr + byte_offset,
++                                      available_bytes);
++                      memset(pageaddr + available_bytes, 0,
++                                      PAGE_CACHE_SIZE - available_bytes);
++                      kunmap_atomic(pageaddr, KM_USER0);
++                      flush_dcache_page(push_page);
++                      SetPageUptodate(push_page);
++                      unlock_page(push_page);
++                      page_cache_release(push_page);
++              }
++      }
++
++      if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK
++                                      || index < (i_size_read(inode) >>
++                                      sblk->block_log))
++              up(&msblk->read_page_mutex);
++      else
++              release_cached_fragment(msblk, fragment);
++
++      return 0;
++
++skip_read:
++      pageaddr = kmap_atomic(page, KM_USER0);
++      memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);
++      kunmap_atomic(pageaddr, KM_USER0);
++      flush_dcache_page(page);
++      SetPageUptodate(page);
++      unlock_page(page);
++
++      return 0;
++}
++
++
++static int squashfs_readpage4K(struct file *file, struct page *page)
++{
++      struct inode *inode = page->mapping->host;
++      struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
++      struct squashfs_super_block *sblk = &msblk->sblk;
++      unsigned char block_list[SIZE];
++      long long block;
++      unsigned int bsize, bytes = 0;
++      void *pageaddr;
++      
++      TRACE("Entered squashfs_readpage4K, page index %lx, start block %llx\n",
++                                      page->index,
++                                      SQUASHFS_I(inode)->start_block);
++
++      if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>
++                                      PAGE_CACHE_SHIFT)) {
++              pageaddr = kmap_atomic(page, KM_USER0);
++              goto skip_read;
++      }
++
++      if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK
++                                      || page->index < (i_size_read(inode) >>
++                                      sblk->block_log)) {
++              block = (msblk->read_blocklist)(inode, page->index, 1,
++                                      block_list, NULL, &bsize);
++
++              down(&msblk->read_page_mutex);
++              bytes = squashfs_read_data(inode->i_sb, msblk->read_page, block,
++                                      bsize, NULL);
++              pageaddr = kmap_atomic(page, KM_USER0);
++              if (bytes)
++                      memcpy(pageaddr, msblk->read_page, bytes);
++              else
++                      ERROR("Unable to read page, block %llx, size %x\n",
++                                      block, bsize);
++              up(&msblk->read_page_mutex);
++      } else {
++              struct squashfs_fragment_cache *fragment =
++                      get_cached_fragment(inode->i_sb,
++                                      SQUASHFS_I(inode)->
++                                      u.s1.fragment_start_block,
++                                      SQUASHFS_I(inode)-> u.s1.fragment_size);
++              pageaddr = kmap_atomic(page, KM_USER0);
++              if (fragment) {
++                      bytes = i_size_read(inode) & (sblk->block_size - 1);
++                      memcpy(pageaddr, fragment->data + SQUASHFS_I(inode)->
++                                      u.s1.fragment_offset, bytes);
++                      release_cached_fragment(msblk, fragment);
++              } else
++                      ERROR("Unable to read page, block %llx, size %x\n",
++                                      SQUASHFS_I(inode)->
++                                      u.s1.fragment_start_block, (int)
++                                      SQUASHFS_I(inode)-> u.s1.fragment_size);
++      }
++
++skip_read:
++      memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);
++      kunmap_atomic(pageaddr, KM_USER0);
++      flush_dcache_page(page);
++      SetPageUptodate(page);
++      unlock_page(page);
++
++      return 0;
++}
++
++
++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 index;
++
++      TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n",
++                                      i_count, (unsigned int) f_pos);
++
++      f_pos =- 3;
++      if (f_pos == 0)
++              goto finish;
++
++      for (i = 0; i < i_count; i++) {
++              if (msblk->swap) {
++                      struct squashfs_dir_index sindex;
++                      squashfs_get_cached_block(s, (char *) &sindex,
++                                      index_start, index_offset,
++                                      sizeof(sindex), &index_start,
++                                      &index_offset);
++                      SQUASHFS_SWAP_DIR_INDEX(&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 + 3;
++}
++
++
++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) + SQUASHFS_NAME_LEN + 1];
++      struct squashfs_dir_index *index = (struct squashfs_dir_index *) 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 sindex;
++                      squashfs_get_cached_block(s, (char *) &sindex,
++                                      index_start, index_offset,
++                                      sizeof(sindex), &index_start,
++                                      &index_offset);
++                      SQUASHFS_SWAP_DIR_INDEX(index, &sindex);
++              } else
++                      squashfs_get_cached_block(s, (char *) index,
++                                      index_start, index_offset,
++                                      sizeof(struct squashfs_dir_index),
++                                      &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 + 3;
++}
++
++              
++static int squashfs_readdir(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 dirh;
++      char buffer[sizeof(struct squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1];
++      struct squashfs_dir_entry *dire = (struct squashfs_dir_entry *) buffer;
++
++      TRACE("Entered squashfs_readdir [%llx:%x]\n", next_block, next_offset);
++
++      while(file->f_pos < 3) {
++              char *name;
++              int size, i_ino;
++
++              if(file->f_pos == 0) {
++                      name = ".";
++                      size = 1;
++                      i_ino = i->i_ino;
++              } else {
++                      name = "..";
++                      size = 2;
++                      i_ino = SQUASHFS_I(i)->u.s2.parent_inode;
++              }
++              TRACE("Calling filldir(%x, %s, %d, %d, %d, %d)\n",
++                              (unsigned int) dirent, name, size, (int)
++                              file->f_pos, i_ino,
++                              squashfs_filetype_table[1]);
++
++              if (filldir(dirent, name, size,
++                              file->f_pos, i_ino,
++                              squashfs_filetype_table[1]) < 0) {
++                              TRACE("Filldir returned less than 0\n");
++                              goto finish;
++              }
++              file->f_pos += size;
++              dirs_read++;
++      }
++
++      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 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(&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 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(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, %d)\n",
++                                      (unsigned int) dirent, dire->name,
++                                      dire->size + 1, (int) file->f_pos,
++                                      dirh.start_block, dire->offset,
++                                      dirh.inode_number + dire->inode_number,
++                                      squashfs_filetype_table[dire->type]);
++
++                      if (filldir(dirent, dire->name, dire->size + 1,
++                                      file->f_pos,
++                                      dirh.inode_number + dire->inode_number,
++                                      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(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 dirh;
++      char buffer[sizeof(struct squashfs_dir_entry) + SQUASHFS_NAME_LEN];
++      struct squashfs_dir_entry *dire = (struct squashfs_dir_entry *) buffer;
++
++      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 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(&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 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(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 (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, %d\n", name,
++                                      dirh.start_block, dire->offset,
++                                      dirh.inode_number + dire->inode_number);
++
++                              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;
++}
++
++
++static void squashfs_put_super(struct super_block *s)
++{
++      int i;
++
++      if (s->s_fs_info) {
++              struct squashfs_sb_info *sbi = s->s_fs_info;
++              if (sbi->block_cache)
++                      for (i = 0; i < SQUASHFS_CACHED_BLKS; i++)
++                              if (sbi->block_cache[i].block !=
++                                                      SQUASHFS_INVALID_BLK)
++                                      kfree(sbi->block_cache[i].data);
++              if (sbi->fragment)
++                      for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) 
++                              SQUASHFS_FREE(sbi->fragment[i].data);
++              kfree(sbi->fragment);
++              kfree(sbi->block_cache);
++              kfree(sbi->read_data);
++              kfree(sbi->read_page);
++              kfree(sbi->uid);
++              kfree(sbi->fragment_index);
++              kfree(sbi->fragment_index_2);
++              kfree(sbi->meta_index);
++              kfree(s->s_fs_info);
++              s->s_fs_info = NULL;
++      }
++}
++
++
++static int squashfs_get_sb(struct file_system_type *fs_type,
++                              int flags, const char *dev_name, void *data, struct vfsmount *mnt)
++{
++      return get_sb_bdev(fs_type, flags, dev_name, data, squashfs_fill_super, mnt);
++}
++
++
++static int __init init_squashfs_fs(void)
++{
++      int err = init_inodecache();
++      if (err)
++              goto out;
++
++      printk(KERN_INFO "squashfs: version 3.0 (2006/03/15) "
++              "Phillip Lougher\n");
++
++      if (!(stream.workspace = vmalloc(zlib_inflate_workspacesize()))) {
++              ERROR("Failed to allocate zlib workspace\n");
++              destroy_inodecache();
++              err = -ENOMEM;
++              goto out;
++      }
++
++      if ((err = register_filesystem(&squashfs_fs_type))) {
++              vfree(stream.workspace);
++              destroy_inodecache();
++      }
++
++out:
++      return err;
++}
++
++
++static void __exit exit_squashfs_fs(void)
++{
++      vfree(stream.workspace);
++      unregister_filesystem(&squashfs_fs_type);
++      destroy_inodecache();
++}
++
++
++static struct kmem_cache* squashfs_inode_cachep;
++
++
++static struct inode *squashfs_alloc_inode(struct super_block *sb)
++{
++      struct squashfs_inode_info *ei;
++      ei = kmem_cache_alloc(squashfs_inode_cachep, GFP_KERNEL);
++      if (!ei)
++              return NULL;
++      return &ei->vfs_inode;
++}
++
++
++static void squashfs_destroy_inode(struct inode *inode)
++{
++      kmem_cache_free(squashfs_inode_cachep, SQUASHFS_I(inode));
++}
++
++
++static void init_once(void * foo, struct kmem_cache *cachep, unsigned long flags)
++{
++      struct squashfs_inode_info *ei = foo;
++
++      inode_init_once(&ei->vfs_inode);
++}
++ 
++
++static int __init init_inodecache(void)
++{
++      squashfs_inode_cachep = kmem_cache_create("squashfs_inode_cache",
++           sizeof(struct squashfs_inode_info),
++           0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
++           init_once);
++      if (squashfs_inode_cachep == NULL)
++              return -ENOMEM;
++      return 0;
++}
++
++
++static void destroy_inodecache(void)
++{
++      kmem_cache_destroy(squashfs_inode_cachep);
++}
++
++
++module_init(init_squashfs_fs);
++module_exit(exit_squashfs_fs);
++MODULE_DESCRIPTION("squashfs, a compressed read-only filesystem");
++MODULE_AUTHOR("Phillip Lougher <phillip@lougher.org.uk>");
+Index: linux-2.6.22/fs/squashfs/Makefile
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/fs/squashfs/Makefile  2007-08-28 21:56:34.000000000 +0100
+@@ -0,0 +1,7 @@
++#
++# Makefile for the linux squashfs routines.
++#
++
++obj-$(CONFIG_SQUASHFS) += squashfs.o
++squashfs-y += inode.o
++squashfs-y += squashfs2_0.o
+Index: linux-2.6.22/fs/squashfs/squashfs2_0.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/fs/squashfs/squashfs2_0.c     2007-08-28 21:56:34.000000000 +0100
+@@ -0,0 +1,757 @@
++/*
++ * 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/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;
++}
+Index: linux-2.6.22/fs/squashfs/squashfs.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/fs/squashfs/squashfs.h        2007-08-28 21:56:34.000000000 +0100
+@@ -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
+Index: linux-2.6.22/include/linux/squashfs_fs.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/include/linux/squashfs_fs.h   2007-08-28 21:56:34.000000000 +0100
+@@ -0,0 +1,911 @@
++#ifndef SQUASHFS_FS
++#define SQUASHFS_FS
++
++/*
++ * Squashfs
++ *
++ * 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_fs.h
++ */
++
++#ifndef CONFIG_SQUASHFS_2_0_COMPATIBILITY
++#define CONFIG_SQUASHFS_2_0_COMPATIBILITY
++#endif
++
++#ifdef        CONFIG_SQUASHFS_VMALLOC
++#define SQUASHFS_ALLOC(a)             vmalloc(a)
++#define SQUASHFS_FREE(a)              vfree(a)
++#else
++#define SQUASHFS_ALLOC(a)             kmalloc(a, GFP_KERNEL)
++#define SQUASHFS_FREE(a)              kfree(a)
++#endif
++#define SQUASHFS_CACHED_FRAGMENTS     CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE     
++#define SQUASHFS_MAJOR                        3
++#define SQUASHFS_MINOR                        0
++#define SQUASHFS_MAGIC                        0x73717368
++#define SQUASHFS_MAGIC_SWAP           0x68737173
++#define SQUASHFS_START                        0
++
++/* size of metadata (inode and directory) blocks */
++#define SQUASHFS_METADATA_SIZE                8192
++#define SQUASHFS_METADATA_LOG         13
++
++/* default size of data blocks */
++#define SQUASHFS_FILE_SIZE            65536
++#define SQUASHFS_FILE_LOG             16
++
++#define SQUASHFS_FILE_MAX_SIZE                65536
++
++/* Max number of uids and gids */
++#define SQUASHFS_UIDS                 256
++#define SQUASHFS_GUIDS                        255
++
++/* Max length of filename (not 255) */
++#define SQUASHFS_NAME_LEN             256
++
++#define SQUASHFS_INVALID              ((long long) 0xffffffffffff)
++#define SQUASHFS_INVALID_FRAG         ((unsigned int) 0xffffffff)
++#define SQUASHFS_INVALID_BLK          ((long long) -1)
++#define SQUASHFS_USED_BLK             ((long long) -2)
++
++/* Filesystem flags */
++#define SQUASHFS_NOI                  0
++#define SQUASHFS_NOD                  1
++#define SQUASHFS_CHECK                        2
++#define SQUASHFS_NOF                  3
++#define SQUASHFS_NO_FRAG              4
++#define SQUASHFS_ALWAYS_FRAG          5
++#define SQUASHFS_DUPLICATE            6
++
++#define SQUASHFS_BIT(flag, bit)               ((flag >> bit) & 1)
++
++#define SQUASHFS_UNCOMPRESSED_INODES(flags)   SQUASHFS_BIT(flags, \
++                                              SQUASHFS_NOI)
++
++#define SQUASHFS_UNCOMPRESSED_DATA(flags)     SQUASHFS_BIT(flags, \
++                                              SQUASHFS_NOD)
++
++#define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags)        SQUASHFS_BIT(flags, \
++                                              SQUASHFS_NOF)
++
++#define SQUASHFS_NO_FRAGMENTS(flags)          SQUASHFS_BIT(flags, \
++                                              SQUASHFS_NO_FRAG)
++
++#define SQUASHFS_ALWAYS_FRAGMENTS(flags)      SQUASHFS_BIT(flags, \
++                                              SQUASHFS_ALWAYS_FRAG)
++
++#define SQUASHFS_DUPLICATES(flags)            SQUASHFS_BIT(flags, \
++                                              SQUASHFS_DUPLICATE)
++
++#define SQUASHFS_CHECK_DATA(flags)            SQUASHFS_BIT(flags, \
++                                              SQUASHFS_CHECK)
++
++#define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \
++              duplicate_checking)     (noi | (nod << 1) | (check_data << 2) \
++              | (nof << 3) | (no_frag << 4) | (always_frag << 5) | \
++              (duplicate_checking << 6))
++
++/* Max number of types and file types */
++#define SQUASHFS_DIR_TYPE             1
++#define SQUASHFS_FILE_TYPE            2
++#define SQUASHFS_SYMLINK_TYPE         3
++#define SQUASHFS_BLKDEV_TYPE          4
++#define SQUASHFS_CHRDEV_TYPE          5
++#define SQUASHFS_FIFO_TYPE            6
++#define SQUASHFS_SOCKET_TYPE          7
++#define SQUASHFS_LDIR_TYPE            8
++#define SQUASHFS_LREG_TYPE            9
++
++/* 1.0 filesystem type definitions */
++#define SQUASHFS_TYPES                        5
++#define SQUASHFS_IPC_TYPE             0
++
++/* Flag whether block is compressed or uncompressed, bit is set if block is
++ * uncompressed */
++#define SQUASHFS_COMPRESSED_BIT               (1 << 15)
++
++#define SQUASHFS_COMPRESSED_SIZE(B)   (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \
++              (B) & ~SQUASHFS_COMPRESSED_BIT :  SQUASHFS_COMPRESSED_BIT)
++
++#define SQUASHFS_COMPRESSED(B)                (!((B) & SQUASHFS_COMPRESSED_BIT))
++
++#define SQUASHFS_COMPRESSED_BIT_BLOCK         (1 << 24)
++
++#define SQUASHFS_COMPRESSED_SIZE_BLOCK(B)     (((B) & \
++      ~SQUASHFS_COMPRESSED_BIT_BLOCK) ? (B) & \
++      ~SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT_BLOCK)
++
++#define SQUASHFS_COMPRESSED_BLOCK(B)  (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK))
++
++/*
++ * Inode number ops.  Inodes consist of a compressed block number, and an
++ * uncompressed  offset within that block
++ */
++#define SQUASHFS_INODE_BLK(a)         ((unsigned int) ((a) >> 16))
++
++#define SQUASHFS_INODE_OFFSET(a)      ((unsigned int) ((a) & 0xffff))
++
++#define SQUASHFS_MKINODE(A, B)                ((squashfs_inode_t)(((squashfs_inode_t) (A)\
++                                      << 16) + (B)))
++
++/* Compute 32 bit VFS inode number from squashfs inode number */
++#define SQUASHFS_MK_VFS_INODE(a, b)   ((unsigned int) (((a) << 8) + \
++                                      ((b) >> 2) + 1))
++/* XXX */
++
++/* Translate between VFS mode and squashfs mode */
++#define SQUASHFS_MODE(a)              ((a) & 0xfff)
++
++/* fragment and fragment table defines */
++#define SQUASHFS_FRAGMENT_BYTES(A)    (A * sizeof(struct squashfs_fragment_entry))
++
++#define SQUASHFS_FRAGMENT_INDEX(A)    (SQUASHFS_FRAGMENT_BYTES(A) / \
++                                      SQUASHFS_METADATA_SIZE)
++
++#define SQUASHFS_FRAGMENT_INDEX_OFFSET(A)     (SQUASHFS_FRAGMENT_BYTES(A) % \
++                                              SQUASHFS_METADATA_SIZE)
++
++#define SQUASHFS_FRAGMENT_INDEXES(A)  ((SQUASHFS_FRAGMENT_BYTES(A) + \
++                                      SQUASHFS_METADATA_SIZE - 1) / \
++                                      SQUASHFS_METADATA_SIZE)
++
++#define SQUASHFS_FRAGMENT_INDEX_BYTES(A)      (SQUASHFS_FRAGMENT_INDEXES(A) *\
++                                              sizeof(long long))
++
++/* cached data constants for filesystem */
++#define SQUASHFS_CACHED_BLKS          8
++
++#define SQUASHFS_MAX_FILE_SIZE_LOG    64
++
++#define SQUASHFS_MAX_FILE_SIZE                ((long long) 1 << \
++                                      (SQUASHFS_MAX_FILE_SIZE_LOG - 2))
++
++#define SQUASHFS_MARKER_BYTE          0xff
++
++/* meta index cache */
++#define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int))
++#define SQUASHFS_META_ENTRIES 31
++#define SQUASHFS_META_NUMBER  8
++#define SQUASHFS_SLOTS                4
++
++struct meta_entry {
++      long long               data_block;
++      unsigned int            index_block;
++      unsigned short          offset;
++      unsigned short          pad;
++};
++
++struct meta_index {
++      unsigned int            inode_number;
++      unsigned int            offset;
++      unsigned short          entries;
++      unsigned short          skip;
++      unsigned short          locked;
++      unsigned short          pad;
++      struct meta_entry       meta_entry[SQUASHFS_META_ENTRIES];
++};
++
++
++/*
++ * definitions for structures on disk
++ */
++
++typedef long long             squashfs_block_t;
++typedef long long             squashfs_inode_t;
++
++struct squashfs_super_block {
++      unsigned int            s_magic;
++      unsigned int            inodes;
++      unsigned int            bytes_used_2;
++      unsigned int            uid_start_2;
++      unsigned int            guid_start_2;
++      unsigned int            inode_table_start_2;
++      unsigned int            directory_table_start_2;
++      unsigned int            s_major:16;
++      unsigned int            s_minor:16;
++      unsigned int            block_size_1:16;
++      unsigned int            block_log:16;
++      unsigned int            flags:8;
++      unsigned int            no_uids:8;
++      unsigned int            no_guids:8;
++      unsigned int            mkfs_time /* time of filesystem creation */;
++      squashfs_inode_t        root_inode;
++      unsigned int            block_size;
++      unsigned int            fragments;
++      unsigned int            fragment_table_start_2;
++      long long               bytes_used;
++      long long               uid_start;
++      long long               guid_start;
++      long long               inode_table_start;
++      long long               directory_table_start;
++      long long               fragment_table_start;
++      long long               unused;
++} __attribute__ ((packed));
++
++struct squashfs_dir_index {
++      unsigned int            index;
++      unsigned int            start_block;
++      unsigned char           size;
++      unsigned char           name[0];
++} __attribute__ ((packed));
++
++#define SQUASHFS_BASE_INODE_HEADER            \
++      unsigned int            inode_type:4;   \
++      unsigned int            mode:12;        \
++      unsigned int            uid:8;          \
++      unsigned int            guid:8;         \
++      unsigned int            mtime;          \
++      unsigned int            inode_number;
++
++struct squashfs_base_inode_header {
++      SQUASHFS_BASE_INODE_HEADER;
++} __attribute__ ((packed));
++
++struct squashfs_ipc_inode_header {
++      SQUASHFS_BASE_INODE_HEADER;
++      unsigned int            nlink;
++} __attribute__ ((packed));
++
++struct squashfs_dev_inode_header {
++      SQUASHFS_BASE_INODE_HEADER;
++      unsigned int            nlink;
++      unsigned short          rdev;
++} __attribute__ ((packed));
++      
++struct squashfs_symlink_inode_header {
++      SQUASHFS_BASE_INODE_HEADER;
++      unsigned int            nlink;
++      unsigned short          symlink_size;
++      char                    symlink[0];
++} __attribute__ ((packed));
++
++struct squashfs_reg_inode_header {
++      SQUASHFS_BASE_INODE_HEADER;
++      squashfs_block_t        start_block;
++      unsigned int            fragment;
++      unsigned int            offset;
++      unsigned int            file_size;
++      unsigned short          block_list[0];
++} __attribute__ ((packed));
++
++struct squashfs_lreg_inode_header {
++      SQUASHFS_BASE_INODE_HEADER;
++      unsigned int            nlink;
++      squashfs_block_t        start_block;
++      unsigned int            fragment;
++      unsigned int            offset;
++      long long               file_size;
++      unsigned short          block_list[0];
++} __attribute__ ((packed));
++
++struct squashfs_dir_inode_header {
++      SQUASHFS_BASE_INODE_HEADER;
++      unsigned int            nlink;
++      unsigned int            file_size:19;
++      unsigned int            offset:13;
++      unsigned int            start_block;
++      unsigned int            parent_inode;
++} __attribute__  ((packed));
++
++struct squashfs_ldir_inode_header {
++      SQUASHFS_BASE_INODE_HEADER;
++      unsigned int            nlink;
++      unsigned int            file_size:27;
++      unsigned int            offset:13;
++      unsigned int            start_block;
++      unsigned int            i_count:16;
++      unsigned int            parent_inode;
++      struct squashfs_dir_index       index[0];
++} __attribute__  ((packed));
++
++union squashfs_inode_header {
++      struct squashfs_base_inode_header       base;
++      struct squashfs_dev_inode_header        dev;
++      struct squashfs_symlink_inode_header    symlink;
++      struct squashfs_reg_inode_header        reg;
++      struct squashfs_lreg_inode_header       lreg;
++      struct squashfs_dir_inode_header        dir;
++      struct squashfs_ldir_inode_header       ldir;
++      struct squashfs_ipc_inode_header        ipc;
++};
++      
++struct squashfs_dir_entry {
++      unsigned int            offset:13;
++      unsigned int            type:3;
++      unsigned int            size:8;
++      int                     inode_number:16;
++      char                    name[0];
++} __attribute__ ((packed));
++
++struct squashfs_dir_header {
++      unsigned int            count:8;
++      unsigned int            start_block;
++      unsigned int            inode_number;
++} __attribute__ ((packed));
++
++struct squashfs_fragment_entry {
++      long long               start_block;
++      unsigned int            size;
++      unsigned int            unused;
++} __attribute__ ((packed));
++
++extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen);
++extern int squashfs_uncompress_init(void);
++extern int squashfs_uncompress_exit(void);
++
++/*
++ * macros to convert each packed bitfield structure from little endian to big
++ * endian and vice versa.  These are needed when creating or using a filesystem
++ * on a machine with different byte ordering to the target architecture.
++ *
++ */
++
++#define SQUASHFS_SWAP_START \
++      int bits;\
++      int b_pos;\
++      unsigned long long val;\
++      unsigned char *s;\
++      unsigned char *d;
++
++#define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\
++      SQUASHFS_SWAP_START\
++      SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\
++      SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\
++      SQUASHFS_SWAP((s)->inodes, d, 32, 32);\
++      SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\
++      SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\
++      SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\
++      SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\
++      SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\
++      SQUASHFS_SWAP((s)->s_major, d, 224, 16);\
++      SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\
++      SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\
++      SQUASHFS_SWAP((s)->block_log, d, 272, 16);\
++      SQUASHFS_SWAP((s)->flags, d, 288, 8);\
++      SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\
++      SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\
++      SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\
++      SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\
++      SQUASHFS_SWAP((s)->block_size, d, 408, 32);\
++      SQUASHFS_SWAP((s)->fragments, d, 440, 32);\
++      SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\
++      SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\
++      SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\
++      SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\
++      SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\
++      SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\
++      SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\
++      SQUASHFS_SWAP((s)->unused, d, 888, 64);\
++}
++
++#define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\
++      SQUASHFS_MEMSET(s, d, n);\
++      SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\
++      SQUASHFS_SWAP((s)->mode, d, 4, 12);\
++      SQUASHFS_SWAP((s)->uid, d, 16, 8);\
++      SQUASHFS_SWAP((s)->guid, d, 24, 8);\
++      SQUASHFS_SWAP((s)->mtime, d, 32, 32);\
++      SQUASHFS_SWAP((s)->inode_number, d, 64, 32);
++
++#define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\
++      SQUASHFS_SWAP_START\
++      SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\
++}
++
++#define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\
++      SQUASHFS_SWAP_START\
++      SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
++                      sizeof(struct squashfs_ipc_inode_header))\
++      SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
++}
++
++#define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\
++      SQUASHFS_SWAP_START\
++      SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
++                      sizeof(struct squashfs_dev_inode_header)); \
++      SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
++      SQUASHFS_SWAP((s)->rdev, d, 128, 16);\
++}
++
++#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\
++      SQUASHFS_SWAP_START\
++      SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
++                      sizeof(struct squashfs_symlink_inode_header));\
++      SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
++      SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\
++}
++
++#define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\
++      SQUASHFS_SWAP_START\
++      SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
++                      sizeof(struct squashfs_reg_inode_header));\
++      SQUASHFS_SWAP((s)->start_block, d, 96, 64);\
++      SQUASHFS_SWAP((s)->fragment, d, 160, 32);\
++      SQUASHFS_SWAP((s)->offset, d, 192, 32);\
++      SQUASHFS_SWAP((s)->file_size, d, 224, 32);\
++}
++
++#define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\
++      SQUASHFS_SWAP_START\
++      SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
++                      sizeof(struct squashfs_lreg_inode_header));\
++      SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
++      SQUASHFS_SWAP((s)->start_block, d, 128, 64);\
++      SQUASHFS_SWAP((s)->fragment, d, 192, 32);\
++      SQUASHFS_SWAP((s)->offset, d, 224, 32);\
++      SQUASHFS_SWAP((s)->file_size, d, 256, 64);\
++}
++
++#define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\
++      SQUASHFS_SWAP_START\
++      SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
++                      sizeof(struct squashfs_dir_inode_header));\
++      SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
++      SQUASHFS_SWAP((s)->file_size, d, 128, 19);\
++      SQUASHFS_SWAP((s)->offset, d, 147, 13);\
++      SQUASHFS_SWAP((s)->start_block, d, 160, 32);\
++      SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\
++}
++
++#define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\
++      SQUASHFS_SWAP_START\
++      SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
++                      sizeof(struct squashfs_ldir_inode_header));\
++      SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
++      SQUASHFS_SWAP((s)->file_size, d, 128, 27);\
++      SQUASHFS_SWAP((s)->offset, d, 155, 13);\
++      SQUASHFS_SWAP((s)->start_block, d, 168, 32);\
++      SQUASHFS_SWAP((s)->i_count, d, 200, 16);\
++      SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\
++}
++
++#define SQUASHFS_SWAP_DIR_INDEX(s, d) {\
++      SQUASHFS_SWAP_START\
++      SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\
++      SQUASHFS_SWAP((s)->index, d, 0, 32);\
++      SQUASHFS_SWAP((s)->start_block, d, 32, 32);\
++      SQUASHFS_SWAP((s)->size, d, 64, 8);\
++}
++
++#define SQUASHFS_SWAP_DIR_HEADER(s, d) {\
++      SQUASHFS_SWAP_START\
++      SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\
++      SQUASHFS_SWAP((s)->count, d, 0, 8);\
++      SQUASHFS_SWAP((s)->start_block, d, 8, 32);\
++      SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\
++}
++
++#define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\
++      SQUASHFS_SWAP_START\
++      SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\
++      SQUASHFS_SWAP((s)->offset, d, 0, 13);\
++      SQUASHFS_SWAP((s)->type, d, 13, 3);\
++      SQUASHFS_SWAP((s)->size, d, 16, 8);\
++      SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\
++}
++
++#define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\
++      SQUASHFS_SWAP_START\
++      SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\
++      SQUASHFS_SWAP((s)->start_block, d, 0, 64);\
++      SQUASHFS_SWAP((s)->size, d, 64, 32);\
++}
++
++#define SQUASHFS_SWAP_SHORTS(s, d, n) {\
++      int entry;\
++      int bit_position;\
++      SQUASHFS_SWAP_START\
++      SQUASHFS_MEMSET(s, d, n * 2);\
++      for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
++                      16)\
++              SQUASHFS_SWAP(s[entry], d, bit_position, 16);\
++}
++
++#define SQUASHFS_SWAP_INTS(s, d, n) {\
++      int entry;\
++      int bit_position;\
++      SQUASHFS_SWAP_START\
++      SQUASHFS_MEMSET(s, d, n * 4);\
++      for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
++                      32)\
++              SQUASHFS_SWAP(s[entry], d, bit_position, 32);\
++}
++
++#define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\
++      int entry;\
++      int bit_position;\
++      SQUASHFS_SWAP_START\
++      SQUASHFS_MEMSET(s, d, n * 8);\
++      for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
++                      64)\
++              SQUASHFS_SWAP(s[entry], d, bit_position, 64);\
++}
++
++#define SQUASHFS_SWAP_DATA(s, d, n, bits) {\
++      int entry;\
++      int bit_position;\
++      SQUASHFS_SWAP_START\
++      SQUASHFS_MEMSET(s, d, n * bits / 8);\
++      for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
++                      bits)\
++              SQUASHFS_SWAP(s[entry], d, bit_position, bits);\
++}
++
++#define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n)
++
++#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY
++
++struct squashfs_base_inode_header_1 {
++      unsigned int            inode_type:4;
++      unsigned int            mode:12; /* protection */
++      unsigned int            uid:4; /* index into uid table */
++      unsigned int            guid:4; /* index into guid table */
++} __attribute__ ((packed));
++
++struct squashfs_ipc_inode_header_1 {
++      unsigned int            inode_type:4;
++      unsigned int            mode:12; /* protection */
++      unsigned int            uid:4; /* index into uid table */
++      unsigned int            guid:4; /* index into guid table */
++      unsigned int            type:4;
++      unsigned int            offset:4;
++} __attribute__ ((packed));
++
++struct squashfs_dev_inode_header_1 {
++      unsigned int            inode_type:4;
++      unsigned int            mode:12; /* protection */
++      unsigned int            uid:4; /* index into uid table */
++      unsigned int            guid:4; /* index into guid table */
++      unsigned short          rdev;
++} __attribute__ ((packed));
++      
++struct squashfs_symlink_inode_header_1 {
++      unsigned int            inode_type:4;
++      unsigned int            mode:12; /* protection */
++      unsigned int            uid:4; /* index into uid table */
++      unsigned int            guid:4; /* index into guid table */
++      unsigned short          symlink_size;
++      char                    symlink[0];
++} __attribute__ ((packed));
++
++struct squashfs_reg_inode_header_1 {
++      unsigned int            inode_type:4;
++      unsigned int            mode:12; /* protection */
++      unsigned int            uid:4; /* index into uid table */
++      unsigned int            guid:4; /* index into guid table */
++      unsigned int            mtime;
++      unsigned int            start_block;
++      unsigned int            file_size:32;
++      unsigned short          block_list[0];
++} __attribute__ ((packed));
++
++struct squashfs_dir_inode_header_1 {
++      unsigned int            inode_type:4;
++      unsigned int            mode:12; /* protection */
++      unsigned int            uid:4; /* index into uid table */
++      unsigned int            guid:4; /* index into guid table */
++      unsigned int            file_size:19;
++      unsigned int            offset:13;
++      unsigned int            mtime;
++      unsigned int            start_block:24;
++} __attribute__  ((packed));
++
++#define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \
++      SQUASHFS_MEMSET(s, d, n);\
++      SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\
++      SQUASHFS_SWAP((s)->mode, d, 4, 12);\
++      SQUASHFS_SWAP((s)->uid, d, 16, 4);\
++      SQUASHFS_SWAP((s)->guid, d, 20, 4);
++
++#define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\
++      SQUASHFS_SWAP_START\
++      SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\
++}
++
++#define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\
++      SQUASHFS_SWAP_START\
++      SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
++                      sizeof(struct squashfs_ipc_inode_header_1));\
++      SQUASHFS_SWAP((s)->type, d, 24, 4);\
++      SQUASHFS_SWAP((s)->offset, d, 28, 4);\
++}
++
++#define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\
++      SQUASHFS_SWAP_START\
++      SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
++                      sizeof(struct squashfs_dev_inode_header_1));\
++      SQUASHFS_SWAP((s)->rdev, d, 24, 16);\
++}
++
++#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\
++      SQUASHFS_SWAP_START\
++      SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
++                      sizeof(struct squashfs_symlink_inode_header_1));\
++      SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\
++}
++
++#define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\
++      SQUASHFS_SWAP_START\
++      SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
++                      sizeof(struct squashfs_reg_inode_header_1));\
++      SQUASHFS_SWAP((s)->mtime, d, 24, 32);\
++      SQUASHFS_SWAP((s)->start_block, d, 56, 32);\
++      SQUASHFS_SWAP((s)->file_size, d, 88, 32);\
++}
++
++#define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\
++      SQUASHFS_SWAP_START\
++      SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
++                      sizeof(struct squashfs_dir_inode_header_1));\
++      SQUASHFS_SWAP((s)->file_size, d, 24, 19);\
++      SQUASHFS_SWAP((s)->offset, d, 43, 13);\
++      SQUASHFS_SWAP((s)->mtime, d, 56, 32);\
++      SQUASHFS_SWAP((s)->start_block, d, 88, 24);\
++}
++
++#endif
++
++#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY
++
++struct squashfs_dir_index_2 {
++      unsigned int            index:27;
++      unsigned int            start_block:29;
++      unsigned char           size;
++      unsigned char           name[0];
++} __attribute__ ((packed));
++
++struct squashfs_base_inode_header_2 {
++      unsigned int            inode_type:4;
++      unsigned int            mode:12; /* protection */
++      unsigned int            uid:8; /* index into uid table */
++      unsigned int            guid:8; /* index into guid table */
++} __attribute__ ((packed));
++
++struct squashfs_ipc_inode_header_2 {
++      unsigned int            inode_type:4;
++      unsigned int            mode:12; /* protection */
++      unsigned int            uid:8; /* index into uid table */
++      unsigned int            guid:8; /* index into guid table */
++} __attribute__ ((packed));
++
++struct squashfs_dev_inode_header_2 {
++      unsigned int            inode_type:4;
++      unsigned int            mode:12; /* protection */
++      unsigned int            uid:8; /* index into uid table */
++      unsigned int            guid:8; /* index into guid table */
++      unsigned short          rdev;
++} __attribute__ ((packed));
++      
++struct squashfs_symlink_inode_header_2 {
++      unsigned int            inode_type:4;
++      unsigned int            mode:12; /* protection */
++      unsigned int            uid:8; /* index into uid table */
++      unsigned int            guid:8; /* index into guid table */
++      unsigned short          symlink_size;
++      char                    symlink[0];
++} __attribute__ ((packed));
++
++struct squashfs_reg_inode_header_2 {
++      unsigned int            inode_type:4;
++      unsigned int            mode:12; /* protection */
++      unsigned int            uid:8; /* index into uid table */
++      unsigned int            guid:8; /* index into guid table */
++      unsigned int            mtime;
++      unsigned int            start_block;
++      unsigned int            fragment;
++      unsigned int            offset;
++      unsigned int            file_size:32;
++      unsigned short          block_list[0];
++} __attribute__ ((packed));
++
++struct squashfs_dir_inode_header_2 {
++      unsigned int            inode_type:4;
++      unsigned int            mode:12; /* protection */
++      unsigned int            uid:8; /* index into uid table */
++      unsigned int            guid:8; /* index into guid table */
++      unsigned int            file_size:19;
++      unsigned int            offset:13;
++      unsigned int            mtime;
++      unsigned int            start_block:24;
++} __attribute__  ((packed));
++
++struct squashfs_ldir_inode_header_2 {
++      unsigned int            inode_type:4;
++      unsigned int            mode:12; /* protection */
++      unsigned int            uid:8; /* index into uid table */
++      unsigned int            guid:8; /* index into guid table */
++      unsigned int            file_size:27;
++      unsigned int            offset:13;
++      unsigned int            mtime;
++      unsigned int            start_block:24;
++      unsigned int            i_count:16;
++      struct squashfs_dir_index_2     index[0];
++} __attribute__  ((packed));
++
++union squashfs_inode_header_2 {
++      struct squashfs_base_inode_header_2     base;
++      struct squashfs_dev_inode_header_2      dev;
++      struct squashfs_symlink_inode_header_2  symlink;
++      struct squashfs_reg_inode_header_2      reg;
++      struct squashfs_dir_inode_header_2      dir;
++      struct squashfs_ldir_inode_header_2     ldir;
++      struct squashfs_ipc_inode_header_2      ipc;
++};
++      
++struct squashfs_dir_header_2 {
++      unsigned int            count:8;
++      unsigned int            start_block:24;
++} __attribute__ ((packed));
++
++struct squashfs_dir_entry_2 {
++      unsigned int            offset:13;
++      unsigned int            type:3;
++      unsigned int            size:8;
++      char                    name[0];
++} __attribute__ ((packed));
++
++struct squashfs_fragment_entry_2 {
++      unsigned int            start_block;
++      unsigned int            size;
++} __attribute__ ((packed));
++
++#define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\
++      SQUASHFS_MEMSET(s, d, n);\
++      SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\
++      SQUASHFS_SWAP((s)->mode, d, 4, 12);\
++      SQUASHFS_SWAP((s)->uid, d, 16, 8);\
++      SQUASHFS_SWAP((s)->guid, d, 24, 8);\
++
++#define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\
++      SQUASHFS_SWAP_START\
++      SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\
++}
++
++#define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \
++      SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2))
++
++#define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\
++      SQUASHFS_SWAP_START\
++      SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
++                      sizeof(struct squashfs_dev_inode_header_2)); \
++      SQUASHFS_SWAP((s)->rdev, d, 32, 16);\
++}
++
++#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\
++      SQUASHFS_SWAP_START\
++      SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
++                      sizeof(struct squashfs_symlink_inode_header_2));\
++      SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\
++}
++
++#define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\
++      SQUASHFS_SWAP_START\
++      SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
++                      sizeof(struct squashfs_reg_inode_header_2));\
++      SQUASHFS_SWAP((s)->mtime, d, 32, 32);\
++      SQUASHFS_SWAP((s)->start_block, d, 64, 32);\
++      SQUASHFS_SWAP((s)->fragment, d, 96, 32);\
++      SQUASHFS_SWAP((s)->offset, d, 128, 32);\
++      SQUASHFS_SWAP((s)->file_size, d, 160, 32);\
++}
++
++#define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\
++      SQUASHFS_SWAP_START\
++      SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
++                      sizeof(struct squashfs_dir_inode_header_2));\
++      SQUASHFS_SWAP((s)->file_size, d, 32, 19);\
++      SQUASHFS_SWAP((s)->offset, d, 51, 13);\
++      SQUASHFS_SWAP((s)->mtime, d, 64, 32);\
++      SQUASHFS_SWAP((s)->start_block, d, 96, 24);\
++}
++
++#define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\
++      SQUASHFS_SWAP_START\
++      SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
++                      sizeof(struct squashfs_ldir_inode_header_2));\
++      SQUASHFS_SWAP((s)->file_size, d, 32, 27);\
++      SQUASHFS_SWAP((s)->offset, d, 59, 13);\
++      SQUASHFS_SWAP((s)->mtime, d, 72, 32);\
++      SQUASHFS_SWAP((s)->start_block, d, 104, 24);\
++      SQUASHFS_SWAP((s)->i_count, d, 128, 16);\
++}
++
++#define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\
++      SQUASHFS_SWAP_START\
++      SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\
++      SQUASHFS_SWAP((s)->index, d, 0, 27);\
++      SQUASHFS_SWAP((s)->start_block, d, 27, 29);\
++      SQUASHFS_SWAP((s)->size, d, 56, 8);\
++}
++#define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\
++      SQUASHFS_SWAP_START\
++      SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\
++      SQUASHFS_SWAP((s)->count, d, 0, 8);\
++      SQUASHFS_SWAP((s)->start_block, d, 8, 24);\
++}
++
++#define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\
++      SQUASHFS_SWAP_START\
++      SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\
++      SQUASHFS_SWAP((s)->offset, d, 0, 13);\
++      SQUASHFS_SWAP((s)->type, d, 13, 3);\
++      SQUASHFS_SWAP((s)->size, d, 16, 8);\
++}
++
++#define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\
++      SQUASHFS_SWAP_START\
++      SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\
++      SQUASHFS_SWAP((s)->start_block, d, 0, 32);\
++      SQUASHFS_SWAP((s)->size, d, 32, 32);\
++}
++
++#define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n)
++
++/* fragment and fragment table defines */
++#define SQUASHFS_FRAGMENT_BYTES_2(A)  (A * sizeof(struct squashfs_fragment_entry_2))
++
++#define SQUASHFS_FRAGMENT_INDEX_2(A)  (SQUASHFS_FRAGMENT_BYTES_2(A) / \
++                                      SQUASHFS_METADATA_SIZE)
++
++#define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A)   (SQUASHFS_FRAGMENT_BYTES_2(A) % \
++                                              SQUASHFS_METADATA_SIZE)
++
++#define SQUASHFS_FRAGMENT_INDEXES_2(A)        ((SQUASHFS_FRAGMENT_BYTES_2(A) + \
++                                      SQUASHFS_METADATA_SIZE - 1) / \
++                                      SQUASHFS_METADATA_SIZE)
++
++#define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A)    (SQUASHFS_FRAGMENT_INDEXES_2(A) *\
++                                              sizeof(int))
++
++#endif
++
++#ifdef __KERNEL__
++
++/*
++ * macros used to swap each structure entry, taking into account
++ * bitfields and different bitfield placing conventions on differing
++ * architectures
++ */
++
++#include <asm/byteorder.h>
++
++#ifdef __BIG_ENDIAN
++      /* convert from little endian to big endian */
++#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \
++              tbits, b_pos)
++#else
++      /* convert from big endian to little endian */ 
++#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \
++              tbits, 64 - tbits - b_pos)
++#endif
++
++#define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\
++      b_pos = pos % 8;\
++      val = 0;\
++      s = (unsigned char *)p + (pos / 8);\
++      d = ((unsigned char *) &val) + 7;\
++      for(bits = 0; bits < (tbits + b_pos); bits += 8) \
++              *d-- = *s++;\
++      value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\
++}
++
++#define SQUASHFS_MEMSET(s, d, n)      memset(s, 0, n);
++
++#endif
++#endif
+Index: linux-2.6.22/include/linux/squashfs_fs_i.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/include/linux/squashfs_fs_i.h 2007-08-28 21:56:34.000000000 +0100
+@@ -0,0 +1,45 @@
++#ifndef SQUASHFS_FS_I
++#define SQUASHFS_FS_I
++/*
++ * Squashfs
++ *
++ * 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_fs_i.h
++ */
++
++struct squashfs_inode_info {
++      long long       start_block;
++      unsigned int    offset;
++      union {
++              struct {
++                      long long       fragment_start_block;
++                      unsigned int    fragment_size;
++                      unsigned int    fragment_offset;
++                      long long       block_list_start;
++              } s1;
++              struct {
++                      long long       directory_index_start;
++                      unsigned int    directory_index_offset;
++                      unsigned int    directory_index_count;
++                      unsigned int    parent_inode;
++              } s2;
++      } u;
++      struct inode    vfs_inode;
++};
++#endif
+Index: linux-2.6.22/include/linux/squashfs_fs_sb.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/include/linux/squashfs_fs_sb.h        2007-08-28 21:56:34.000000000 +0100
+@@ -0,0 +1,74 @@
++#ifndef SQUASHFS_FS_SB
++#define SQUASHFS_FS_SB
++/*
++ * Squashfs
++ *
++ * 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_fs_sb.h
++ */
++
++#include <linux/squashfs_fs.h>
++
++struct squashfs_cache {
++      long long       block;
++      int             length;
++      long long       next_index;
++      char            *data;
++};
++
++struct squashfs_fragment_cache {
++      long long       block;
++      int             length;
++      unsigned int    locked;
++      char            *data;
++};
++
++struct squashfs_sb_info {
++      struct squashfs_super_block     sblk;
++      int                     devblksize;
++      int                     devblksize_log2;
++      int                     swap;
++      struct squashfs_cache   *block_cache;
++      struct squashfs_fragment_cache  *fragment;
++      int                     next_cache;
++      int                     next_fragment;
++      int                     next_meta_index;
++      unsigned int            *uid;
++      unsigned int            *guid;
++      long long               *fragment_index;
++      unsigned int            *fragment_index_2;
++      unsigned int            read_size;
++      char                    *read_data;
++      char                    *read_page;
++      struct semaphore        read_data_mutex;
++      struct semaphore        read_page_mutex;
++      struct semaphore        block_cache_mutex;
++      struct semaphore        fragment_mutex;
++      struct semaphore        meta_index_mutex;
++      wait_queue_head_t       waitq;
++      wait_queue_head_t       fragment_wait_queue;
++      struct meta_index       *meta_index;
++      struct inode            *(*iget)(struct super_block *s,  squashfs_inode_t \
++                              inode);
++      long long               (*read_blocklist)(struct inode *inode, int \
++                              index, int readahead_blks, char *block_list, \
++                              unsigned short **block_p, unsigned int *bsize);
++      int                     (*read_fragment_index_table)(struct super_block *s);
++};
++#endif
+Index: linux-2.6.22/init/do_mounts_rd.c
+===================================================================
+--- linux-2.6.22.orig/init/do_mounts_rd.c      2007-08-28 21:54:14.000000000 +0100
++++ linux-2.6.22/init/do_mounts_rd.c   2007-08-28 21:56:34.000000000 +0100
+@@ -5,6 +5,7 @@
+ #include <linux/ext2_fs.h>
+ #include <linux/romfs_fs.h>
+ #include <linux/cramfs_fs.h>
++#include <linux/squashfs_fs.h>
+ #include <linux/initrd.h>
+ #include <linux/string.h>
+@@ -39,6 +40,7 @@ static int __init crd_load(int in_fd, in
+  * numbers could not be found.
+  *
+  * We currently check for the following magic numbers:
++ *      squashfs
+  *    minix
+  *    ext2
+  *    romfs
+@@ -53,6 +55,7 @@ identify_ramdisk_image(int fd, int start
+       struct ext2_super_block *ext2sb;
+       struct romfs_super_block *romfsb;
+       struct cramfs_super *cramfsb;
++      struct squashfs_super_block *squashfsb;
+       int nblocks = -1;
+       unsigned char *buf;
+@@ -64,6 +67,7 @@ identify_ramdisk_image(int fd, int start
+       ext2sb = (struct ext2_super_block *) buf;
+       romfsb = (struct romfs_super_block *) buf;
+       cramfsb = (struct cramfs_super *) buf;
++      squashfsb = (struct squashfs_super_block *) buf;
+       memset(buf, 0xe5, size);
+       /*
+@@ -101,6 +105,15 @@ identify_ramdisk_image(int fd, int start
+               goto done;
+       }
++      /* squashfs is at block zero too */
++      if (squashfsb->s_magic == SQUASHFS_MAGIC) {
++              printk(KERN_NOTICE
++                     "RAMDISK: squashfs filesystem found at block %d\n",
++                     start_block);
++              nblocks = (squashfsb->bytes_used+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS;
++              goto done;
++      }
++
+       /*
+        * Read block 1 to test for minix and ext2 superblock
+        */
diff --git a/packages/kexecboot/linux-kexecboot-2.6.23/tmio-fb-r6-fix-r0.patch b/packages/kexecboot/linux-kexecboot-2.6.23/tmio-fb-r6-fix-r0.patch
new file mode 100644 (file)
index 0000000..eab57c5
--- /dev/null
@@ -0,0 +1,45 @@
+From 302745ce6f3bab7b1a97de32339405ae3fd8eacb Mon Sep 17 00:00:00 2001
+From: Dmitry Baryshkov <dbaryshkov@gmail.com>
+Date: Fri, 19 Oct 2007 00:05:54 +0400
+Subject: [PATCH] tmio-fb-r6.patch fixes
+
+---
+ drivers/video/tmiofb.c |    8 ++++----
+ 1 files changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/video/tmiofb.c b/drivers/video/tmiofb.c
+index 10b0105..72eb76c 100644
+--- a/drivers/video/tmiofb.c
++++ b/drivers/video/tmiofb.c
+@@ -463,8 +463,8 @@ static int tmiofb_vblank (struct fb_info *fbi, struct fb_vblank *vblank)
+ #define FBIO_TMIO_ACC_WRITE   0x7C639300
+ #define FBIO_TMIO_ACC_SYNC    0x7C639301
+-static int tmiofb_ioctl (struct inode *inode, struct file *file,
+-              unsigned int cmd, unsigned long arg, struct fb_info *fbi)
++static int tmiofb_ioctl (struct fb_info *fbi,
++              unsigned int cmd, unsigned long arg)
+ {
+       switch (cmd) {
+               case FBIOGET_VBLANK: {
+@@ -677,7 +677,7 @@ static struct fb_ops tmiofb_ops_acc = {
+  *    2000            0002    display start
+  *    2000            0004    line number match (0x1ff mask???)
+  */
+-static irqreturn_t tmiofb_irq (int irq, void *__fbi, struct pt_regs *r)
++static irqreturn_t tmiofb_irq (int irq, void *__fbi)
+ {
+       struct fb_info*                 fbi     = __fbi;
+       struct tmiofb_par*              par     = fbi->par;
+@@ -762,7 +762,7 @@ static int __init tmiofb_probe (struct device *dev)
+       }
+       fbi->screen_base = par->sram;
+-      retval = request_irq (irq->start, &tmiofb_irq, SA_INTERRUPT,
++      retval = request_irq (irq->start, &tmiofb_irq, IRQF_DISABLED,
+                                                       TMIO_NAME_LCD, fbi);
+       if (retval)
+               goto err_request_irq;
+-- 
+1.4.4.4
+
diff --git a/packages/kexecboot/linux-kexecboot-2.6.23/tmio-nand-r8.patch b/packages/kexecboot/linux-kexecboot-2.6.23/tmio-nand-r8.patch
new file mode 100644 (file)
index 0000000..a71fd11
--- /dev/null
@@ -0,0 +1,594 @@
+ drivers/mtd/nand/Kconfig  |    7 +
+ drivers/mtd/nand/Makefile |    1 +
+ drivers/mtd/nand/tmio.c   |  554 +++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 562 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
+index f1d60b6..b9c8796 100644
+--- a/drivers/mtd/nand/Kconfig
++++ b/drivers/mtd/nand/Kconfig
+@@ -69,6 +69,13 @@ config MTD_NAND_AMS_DELTA
+       help
+         Support for NAND flash on Amstrad E3 (Delta).
++config MTD_NAND_TMIO
++      tristate "NAND Flash device on Toshiba Mobile IO Controller"
++      depends on MTD_NAND && TOSHIBA_TC6393XB
++      help
++        Support for NAND flash connected to a Toshiba Mobile IO
++        Controller in some PDAs, including the Sharp SL6000x.
++
+ config MTD_NAND_TOTO
+       tristate "NAND Flash device on TOTO board"
+       depends on ARCH_OMAP && BROKEN
+diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
+index edba1db..64f24e1 100644
+--- a/drivers/mtd/nand/Makefile
++++ b/drivers/mtd/nand/Makefile
+@@ -27,5 +27,6 @@ obj-$(CONFIG_MTD_NAND_AT91)          += at91_nand.o
+ obj-$(CONFIG_MTD_NAND_CM_X270)                += cmx270_nand.o
+ obj-$(CONFIG_MTD_NAND_BASLER_EXCITE)  += excite_nandflash.o
+ obj-$(CONFIG_MTD_NAND_PLATFORM)               += plat_nand.o
++obj-$(CONFIG_MTD_NAND_TMIO)           += tmio.o
+ nand-objs := nand_base.o nand_bbt.o
+diff --git a/drivers/mtd/nand/tmio.c b/drivers/mtd/nand/tmio.c
+new file mode 100644
+index 0000000..d196553
+--- /dev/null
++++ b/drivers/mtd/nand/tmio.c
+@@ -0,0 +1,554 @@
++/*
++ * A device driver for NAND flash connected to a Toshiba Mobile IO
++ * controller. This is known to work with the following variants:
++ *    TC6393XB revision 3
++ *
++ * Maintainer: Chris Humbert <mahadri+mtd@drigon.com>
++ *
++ * Copyright (C) 2005 Chris Humbert
++ * Copyright (C) 2005 Dirk Opfer
++ * Copyright (C) 2004 SHARP
++ * Copyright (C) 2002 Lineo Japan, Inc.
++ * Copyright (C) Ian Molton and Sebastian Carlier
++ *
++ * Based on Sharp's NAND driver, sharp_sl_tc6393.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/module.h>
++#include <linux/types.h>
++#include <linux/delay.h>
++#include <linux/wait.h>
++#include <linux/ioport.h>
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/nand.h>
++#include <linux/mtd/nand_ecc.h>
++#include <linux/mtd/partitions.h>
++#include <asm/io.h>
++#include <asm/hardware/tmio.h>
++
++#include <linux/interrupt.h>
++
++#define mtd_printk(level, mtd, format, arg...)        \
++      printk (level "%s: " format, mtd->name, ## arg)
++#define mtd_warn(mtd, format, arg...)         \
++      mtd_printk (KERN_WARNING, mtd, format, ## arg)
++
++/*--------------------------------------------------------------------------*/
++
++/* tmio_nfcr.mode Register Command List */
++#define FCR_MODE_DATA         0x94    // Data Data_Mode
++#define FCR_MODE_COMMAND      0x95    // Data Command_Mode
++#define FCR_MODE_ADDRESS      0x96    // Data Address_Mode
++
++#define FCR_MODE_HWECC_CALC   0xB4    // HW-ECC Data
++#define FCR_MODE_HWECC_RESULT 0xD4    // HW-ECC Calculation Result Read_Mode
++#define FCR_MODE_HWECC_RESET  0xF4    // HW-ECC Reset
++
++#define FCR_MODE_POWER_ON     0x0C    // Power Supply ON  to SSFDC card
++#define FCR_MODE_POWER_OFF    0x08    // Power Supply OFF to SSFDC card
++
++#define FCR_MODE_LED_OFF      0x00    // LED OFF
++#define FCR_MODE_LED_ON               0x04    // LED ON
++
++#define FCR_MODE_EJECT_ON     0x68    // Ejection Demand from Penguin is Advanced
++#define FCR_MODE_EJECT_OFF    0x08    // Ejection Demand from Penguin is Not Advanced
++
++#define FCR_MODE_LOCK         0x6C    // Operates By Lock_Mode. Ejection Switch is Invalid
++#define FCR_MODE_UNLOCK               0x0C    // Operates By UnLock_Mode.Ejection Switch is Effective
++
++#define FCR_MODE_CONTROLLER_ID        0x40    // Controller ID Read
++#define FCR_MODE_STANDBY      0x00    // SSFDC card Changes Standby State
++
++#define FCR_MODE_WE           0x80
++#define FCR_MODE_ECC1         0x40
++#define FCR_MODE_ECC0         0x20
++#define FCR_MODE_CE           0x10
++#define FCR_MODE_PCNT1                0x08
++#define FCR_MODE_PCNT0                0x04
++#define FCR_MODE_ALE          0x02
++#define FCR_MODE_CLE          0x01
++
++#define FCR_STATUS_BUSY               0x80
++
++/*
++ * NAND Flash Host Controller Configuration Register
++ */
++struct tmio_nfhccr {
++      u8 x00[4];
++      u16     command;        /* 0x04 Command                         */
++      u8 x01[0x0a];
++      u16     base[2];        /* 0x10 NAND Flash Control Reg Base Addr*/
++      u8 x02[0x29];
++      u8      intp;           /* 0x3d Interrupt Pin                   */
++      u8 x03[0x0a];
++      u8      inte;           /* 0x48 Interrupt Enable                */
++      u8 x04;
++      u8      ec;             /* 0x4a Event Control                   */
++      u8 x05;
++      u8      icc;            /* 0x4c Internal Clock Control          */
++      u8 x06[0x0e];
++      u8      eccc;           /* 0x5b ECC Control                     */
++      u8 x07[4];
++      u8      nftc;           /* 0x60 NAND Flash Transaction Control  */
++      u8      nfm;            /* 0x61 NAND Flash Monitor              */
++      u8      nfpsc;          /* 0x62 NAND Flash Power Supply Control */
++      u8      nfdc;           /* 0x63 NAND Flash Detect Control       */
++      u8 x08[0x9c];
++} __attribute__ ((packed));
++
++/*
++ * NAND Flash Control Register
++ */
++struct tmio_nfcr {
++union {
++      u8      u8;             /* 0x00 Data Register                   */
++      u16     u16;
++      u32     u32;
++} __attribute__ ((packed));
++      u8      mode;           /* 0x04 Mode Register                   */
++      u8      status;         /* 0x05 Status Register                 */
++      u8      isr;            /* 0x06 Interrupt Status Register       */
++      u8      imr;            /* 0x07 Interrupt Mask Register         */
++} __attribute__ ((packed));
++
++struct tmio_nand {
++      struct mtd_info                 mtd;
++      struct nand_chip                chip;
++
++      struct tmio_nfhccr __iomem *    ccr;
++      struct tmio_nfcr __iomem *      fcr;
++
++      unsigned int                    irq;
++
++      /* for tmio_nand_read_byte */
++      u8                              read;
++      unsigned                        read_good:1;
++};
++
++#define mtd_to_tmio(m)                        container_of(m, struct tmio_nand, mtd)
++
++/*--------------------------------------------------------------------------*/
++
++static void tmio_nand_hwcontrol(struct mtd_info *mtd, int cmd,
++                                 unsigned int ctrl)
++{
++      struct tmio_nand *tmio = mtd_to_tmio (mtd);
++      struct tmio_nfcr __iomem *fcr = tmio->fcr;
++      struct nand_chip *chip = mtd->priv;
++
++      if (ctrl & NAND_CTRL_CHANGE) {
++              u8 mode;
++
++              if (ctrl & NAND_NCE) {
++                      mode = FCR_MODE_DATA;
++
++                      if (ctrl & NAND_CLE)
++                              mode |=  FCR_MODE_CLE;
++                      else
++                              mode &= ~FCR_MODE_CLE;
++
++                      if (ctrl & NAND_ALE)
++                              mode |=  FCR_MODE_ALE;
++                      else
++                              mode &= ~FCR_MODE_ALE;
++              } else {
++                      mode = FCR_MODE_STANDBY;
++              }
++
++              iowrite8 (mode, &fcr->mode);
++              tmio->read_good = 0;
++      }
++
++      if (cmd != NAND_CMD_NONE)
++              writeb(cmd, chip->IO_ADDR_W);
++}
++
++static int tmio_nand_dev_ready (struct mtd_info* mtd)
++{
++      struct tmio_nand*               tmio    = mtd_to_tmio (mtd);
++      struct tmio_nfcr __iomem *      fcr     = tmio->fcr;
++
++      return !(ioread8 (&fcr->status) & FCR_STATUS_BUSY);
++}
++
++static irqreturn_t tmio_irq (int irq, void *__tmio)
++{
++      struct tmio_nand*               tmio    = __tmio;
++      struct nand_chip*               this    = &tmio->chip;
++      struct tmio_nfcr __iomem *      fcr     = tmio->fcr;
++
++      /* disable RDYREQ interrupt */
++      iowrite8 (0x00, &fcr->imr);
++
++      if (unlikely (!waitqueue_active (&this->controller->wq)))
++              printk (KERN_WARNING TMIO_NAME_NAND ": spurious interrupt\n");
++
++      wake_up (&this->controller->wq);
++      return IRQ_HANDLED;
++}
++
++/*
++ * The TMIO core has a RDYREQ interrupt on the posedge of #SMRB.
++ * This interrupt is normally disabled, but for long operations like
++ * erase and write, we enable it to wake us up.  The irq handler
++ * disables the interrupt.
++ */
++static int
++tmio_nand_wait (struct mtd_info *mtd, struct nand_chip *this)
++{
++      struct tmio_nand*               tmio    = mtd_to_tmio (mtd);
++      struct tmio_nfcr __iomem *      fcr     = tmio->fcr;
++      long                            timeout;
++
++      /* enable RDYREQ interrupt */
++      iowrite8 (0x0f, &fcr->isr);
++      iowrite8 (0x81, &fcr->imr);
++
++      timeout = wait_event_timeout (this->controller->wq, tmio_nand_dev_ready (mtd),
++                      msecs_to_jiffies (this->state == FL_ERASING ? 400 : 20));
++
++      if (unlikely (!tmio_nand_dev_ready (mtd))) {
++              iowrite8 (0x00, &fcr->imr);
++              mtd_warn (mtd, "still busy with %s after %d ms\n",
++                              this->state == FL_ERASING ? "erase" : "program",
++                              this->state == FL_ERASING ? 400 : 20);
++
++      } else if (unlikely (!timeout)) {
++              iowrite8 (0x00, &fcr->imr);
++              mtd_warn (mtd, "timeout waiting for interrupt\n");
++      }
++
++      this->cmdfunc (mtd, NAND_CMD_STATUS, -1, -1);
++      return this->read_byte (mtd);
++}
++
++/*
++ * The TMIO controller combines two 8-bit data bytes into one 16-bit
++ * word. This function separates them so nand_base.c works as expected,
++ * especially its NAND_CMD_READID routines.
++ *
++ * To prevent stale data from being read, tmio_nand_hwcontrol() clears
++ * tmio->read_good.
++ */
++static u_char tmio_nand_read_byte (struct mtd_info *mtd)
++{
++      struct tmio_nand*               tmio    = mtd_to_tmio (mtd);
++      struct tmio_nfcr __iomem *      fcr     = tmio->fcr;
++      unsigned int                    data;
++
++      if (tmio->read_good--)
++              return tmio->read;
++
++      data            = ioread16 (&fcr->u16);
++      tmio->read      = data >> 8;
++      return data;
++}
++
++/*
++ * The TMIO controller converts an 8-bit NAND interface to a 16-bit
++ * bus interface, so all data reads and writes must be 16-bit wide.
++ * Thus, we implement 16-bit versions of the read, write, and verify
++ * buffer functions.
++ */
++static void
++tmio_nand_write_buf (struct mtd_info *mtd, const u_char *buf, int len)
++{
++      struct tmio_nand*               tmio    = mtd_to_tmio (mtd);
++      struct tmio_nfcr __iomem *      fcr     = tmio->fcr;
++
++      iowrite16_rep (&fcr->u16, buf, len >> 1);
++}
++
++static void tmio_nand_read_buf (struct mtd_info *mtd, u_char *buf, int len)
++{
++      struct tmio_nand*               tmio    = mtd_to_tmio (mtd);
++      struct tmio_nfcr __iomem *      fcr     = tmio->fcr;
++
++      ioread16_rep (&fcr->u16, buf, len >> 1);
++}
++
++static int
++tmio_nand_verify_buf (struct mtd_info *mtd, const u_char *buf, int len)
++{
++      struct tmio_nand*               tmio    = mtd_to_tmio (mtd);
++      struct tmio_nfcr __iomem *      fcr     = tmio->fcr;
++      u16*                            p       = (u16*) buf;
++
++      for (len >>= 1; len; len--)
++              if (*(p++) != ioread16 (&fcr->u16))
++                      return -EFAULT;
++      return 0;
++}
++
++static void tmio_nand_enable_hwecc (struct mtd_info* mtd, int mode)
++{
++      struct tmio_nand*               tmio    = mtd_to_tmio (mtd);
++      struct tmio_nfcr __iomem *      fcr     = tmio->fcr;
++
++      iowrite8 (FCR_MODE_HWECC_RESET, &fcr->mode);
++      ioread8 (&fcr->u8);     /* dummy read */
++      iowrite8 (FCR_MODE_HWECC_CALC, &fcr->mode);
++}
++
++static int tmio_nand_calculate_ecc (struct mtd_info* mtd, const u_char* dat,
++                                                      u_char* ecc_code)
++{
++      struct tmio_nand*               tmio    = mtd_to_tmio (mtd);
++      struct tmio_nfcr __iomem *      fcr     = tmio->fcr;
++      unsigned int                    ecc;
++
++      iowrite8 (FCR_MODE_HWECC_RESULT, &fcr->mode);
++
++      ecc = ioread16 (&fcr->u16);
++      ecc_code[1] = ecc;      // 000-255 LP7-0
++      ecc_code[0] = ecc >> 8; // 000-255 LP15-8
++      ecc = ioread16 (&fcr->u16);
++      ecc_code[2] = ecc;      // 000-255 CP5-0,11b
++      ecc_code[4] = ecc >> 8; // 256-511 LP7-0
++      ecc = ioread16 (&fcr->u16);
++      ecc_code[3] = ecc;      // 256-511 LP15-8
++      ecc_code[5] = ecc >> 8; // 256-511 CP5-0,11b
++
++      iowrite8 (FCR_MODE_DATA, &fcr->mode);
++      return 0;
++}
++
++static void tmio_hw_init (struct device *dev, struct tmio_nand *tmio)
++{
++      struct resource*                nfcr    = tmio_resource_control (dev);
++      struct tmio_device*             tdev    = dev_to_tdev (dev);
++      struct tmio_nfhccr __iomem *    ccr     = tmio->ccr;
++      struct tmio_nfcr __iomem *      fcr     = tmio->fcr;
++      unsigned long                   base;
++
++      /* (89h) SMD Buffer ON By TC6393XB SystemConfig gpibfc1 */
++      tdev->ops->clock (dev, 1);
++      tdev->ops->function (dev, 1);
++
++      /* (4Ch) CLKRUN Enable    1st spcrunc */
++      iowrite8 (0x81,                 &ccr->icc);
++
++      /* (10h)BaseAddress    0x1000 spba.spba2 */
++      base = nfcr->start - tdev->iomem->start;
++      iowrite16 (base,                ccr->base + 0);
++      iowrite16 (base >> 16,          ccr->base + 1);
++
++      /* (04h)Command Register I/O spcmd */
++      iowrite8 (0x02,                 &ccr->command);
++
++      /* (62h) Power Supply Control ssmpwc */
++      /* HardPowerOFF - SuspendOFF - PowerSupplyWait_4MS */
++      iowrite8 (0x02,                 &ccr->nfpsc);
++
++      /* (63h) Detect Control ssmdtc */
++      iowrite8 (0x02,                 &ccr->nfdc);
++
++      /* Interrupt status register clear sintst */
++      iowrite8 (0x0f,                 &fcr->isr);
++
++      /* After power supply, Media are reset smode */
++      iowrite8 (FCR_MODE_POWER_ON,    &fcr->mode);
++      iowrite8 (FCR_MODE_COMMAND,     &fcr->mode);
++      iowrite8 (NAND_CMD_RESET,       &fcr->u8);
++
++      /* Standby Mode smode */
++      iowrite8 (FCR_MODE_STANDBY,     &fcr->mode);
++
++      mdelay (5);
++}
++
++static void tmio_hw_stop (struct device *dev, struct tmio_nand *tmio)
++{
++      struct tmio_device*             tdev    = dev_to_tdev (dev);
++      struct tmio_nfcr __iomem *      fcr     = tmio->fcr;
++
++      iowrite8 (FCR_MODE_POWER_OFF,   &fcr->mode);
++      tdev->ops->function (dev, 0);
++      tdev->ops->clock (dev, 0);
++}
++
++/*--------------------------------------------------------------------------*/
++
++#ifdef CONFIG_MTD_PARTITIONS
++static const char *part_probes[] = { "cmdlinepart", NULL };
++#endif
++
++static int tmio_probe (struct device *dev)
++{
++      struct tmio_device*             tdev    = dev_to_tdev (dev);
++      struct tmio_nand_platform_data* tnpd    = dev->platform_data;
++      struct resource*                ccr     = tmio_resource_config (dev);
++      struct resource*                fcr     = tmio_resource_control (dev);
++      struct resource*                irq     = tmio_resource_irq (dev);
++      struct tmio_nand*               tmio;
++      struct mtd_info*                mtd;
++      struct nand_chip*               this;
++      struct mtd_partition*           parts;
++      int                             nbparts = 0;
++      int                             retval;
++
++      if (!tnpd)
++              return -EINVAL;
++
++      retval = request_resource (tdev->iomem, ccr);
++      if (retval)
++              goto err_request_ccr;
++
++      retval = request_resource (tdev->iomem, fcr);
++      if (retval)
++              goto err_request_fcr;
++
++      tmio = kzalloc (sizeof *tmio, GFP_KERNEL);
++      if (!tmio) {
++              retval = -ENOMEM;
++              goto err_kzalloc;
++      }
++
++      dev_set_drvdata (dev, tmio);
++      mtd             = &tmio->mtd;
++      this            = &tmio->chip;
++      mtd->priv       = this;
++      mtd->name       = TMIO_NAME_NAND;
++
++      tmio->ccr = ioremap (ccr->start, ccr->end - ccr->start + 1);
++      if (!tmio->ccr) {
++              retval = -EIO;
++              goto err_iomap_ccr;
++      }
++
++      tmio->fcr = ioremap (fcr->start, fcr->end - fcr->start + 1);
++      if (!tmio->fcr) {
++              retval = -EIO;
++              goto err_iomap_fcr;
++      }
++
++      tmio_hw_init (dev, tmio);
++
++      /* Set address of NAND IO lines */
++      this->IO_ADDR_R         = tmio->fcr;
++      this->IO_ADDR_W         = tmio->fcr;
++
++      /* Set address of hardware control function */
++      this->cmd_ctrl          = tmio_nand_hwcontrol;
++      this->dev_ready         = tmio_nand_dev_ready;
++      this->read_byte         = tmio_nand_read_byte;
++      this->write_buf         = tmio_nand_write_buf;
++      this->read_buf          = tmio_nand_read_buf;
++      this->verify_buf        = tmio_nand_verify_buf;
++
++      /* set eccmode using hardware ECC */
++      this->ecc.mode          = NAND_ECC_HW;
++      this->ecc.size          = 512;
++      this->ecc.bytes         = 6;
++      this->ecc.hwctl         = tmio_nand_enable_hwecc;
++      this->ecc.calculate     = tmio_nand_calculate_ecc;
++      this->ecc.correct       = nand_correct_data;
++      this->badblock_pattern  = tnpd->badblock_pattern;
++
++      /* 15 us command delay time */
++      this->chip_delay        = 15;
++
++      if (irq->start) {
++              retval = request_irq (irq->start, &tmio_irq,
++                                      IRQF_DISABLED, irq->name, tmio);
++              if (!retval) {
++                      tmio->irq       = irq->start;
++                      this->waitfunc  = tmio_nand_wait;
++              } else
++                      mtd_warn (mtd, "request_irq error %d\n", retval);
++      }
++
++      /* Scan to find existence of the device */
++      if (nand_scan (mtd, 1)) {
++              retval = -ENODEV;
++              goto err_scan;
++      }
++
++      /* Register the partitions */
++#ifdef CONFIG_MTD_PARTITIONS
++      nbparts = parse_mtd_partitions (mtd, part_probes, &parts, 0);
++#endif
++      if (nbparts <= 0) {
++              parts   = tnpd->partition;
++              nbparts = tnpd->num_partitions;
++      }
++
++      add_mtd_partitions (mtd, parts, nbparts);
++      return 0;
++
++err_scan:
++      if (tmio->irq)
++              free_irq (tmio->irq, tmio);
++      tmio_hw_stop (dev, tmio);
++      iounmap (tmio->fcr);
++err_iomap_fcr:
++      iounmap (tmio->ccr);
++err_iomap_ccr:
++      kfree (tmio);
++err_kzalloc:
++      release_resource (fcr);
++err_request_fcr:
++      release_resource (ccr);
++err_request_ccr:
++      return retval;
++}
++
++static int tmio_remove (struct device *dev)
++{
++      struct tmio_nand*               tmio    = dev_get_drvdata (dev);
++
++      nand_release (&tmio->mtd);
++      if (tmio->irq)
++              free_irq (tmio->irq, tmio);
++      tmio_hw_stop (dev, tmio);
++      iounmap (tmio->fcr);
++      iounmap (tmio->ccr);
++      kfree (tmio);
++      release_resource (tmio_resource_control (dev));
++      release_resource (tmio_resource_config (dev));
++      return 0;
++}
++
++#ifdef CONFIG_PM
++static int tmio_suspend (struct device *dev, pm_message_t state)
++{
++      tmio_hw_stop (dev, dev_get_drvdata (dev));
++      return 0;
++}
++
++static int tmio_resume (struct device *dev)
++{
++      tmio_hw_init (dev, dev_get_drvdata (dev));
++      return 0;
++}
++#endif
++
++static struct device_driver tmio_driver = {
++      .name           = TMIO_NAME_NAND,
++      .bus            = &tmio_bus_type,
++      .probe          = tmio_probe,
++      .remove         = tmio_remove,
++#ifdef CONFIG_PM
++      .suspend        = tmio_suspend,
++      .resume         = tmio_resume,
++#endif
++};
++
++static int __init tmio_init (void) {
++      return driver_register (&tmio_driver);
++}
++
++static void __exit tmio_exit (void) {
++      driver_unregister (&tmio_driver);
++}
++
++module_init (tmio_init);
++module_exit (tmio_exit);
++
++MODULE_LICENSE ("GPL");
++MODULE_AUTHOR ("Dirk Opfer, Chris Humbert");
++MODULE_DESCRIPTION ("NAND flash driver on Toshiba Mobile IO controller");
diff --git a/packages/kexecboot/linux-kexecboot-2.6.23/tmio-ohci-r9.patch b/packages/kexecboot/linux-kexecboot-2.6.23/tmio-ohci-r9.patch
new file mode 100644 (file)
index 0000000..9b8434a
--- /dev/null
@@ -0,0 +1,585 @@
+Signed-off-by: Dmitry Baryshkov <dbaryshkov@gmail.com>
+
+Index: linux-2.6.23/drivers/usb/host/ohci-tmio.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.23/drivers/usb/host/ohci-tmio.c  2007-11-14 16:58:47.637707413 +0300
+@@ -0,0 +1,530 @@
++/*
++ * 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 Toshiba Mobile IO(TMIO) Controller's OHCI core
++ *(C) Copyright 2005 Chris Humbert <mahadri-usb@drigon.com>
++ *
++ * This is known to work with the following variants:
++ *    TC6393XB revision 3     (32kB SRAM)
++ *
++ * The TMIO's OHCI core DMAs through a small internal buffer that
++ * is directly addressable by the CPU.  dma_declare_coherent_memory
++ * and DMA bounce buffers allow the higher-level OHCI host driver to
++ * work.  However, the dma API doesn't handle dma mapping failures
++ * well(dma_sg_map() is a prime example), so it is unusable.
++ *
++ * This HC pretends be a PIO-ish controller and uses the kernel's
++ * generic allocator for the entire SRAM.  Using the USB core's
++ * usb_operations, we provide hcd_buffer_alloc/free.  Using the OHCI's
++ * ohci_ops, we provide memory management for OHCI's TDs and EDs.  We
++ * internally queue a URB's TDs until enough dma memory is available
++ * to enqueue them with the HC.
++ *
++ * Written from sparse documentation from Toshiba and Sharp's driver
++ * for the 2.4 kernel,
++ *    usb-ohci-tc6393.c(C) Copyright 2004 Lineo Solutions, 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/fs.h>
++#include <linux/mount.h>
++#include <linux/pagemap.h>
++#include <linux/init.h>
++#include <linux/namei.h>
++#include <linux/sched.h>
++
++#include <linux/genalloc.h>
++#include <asm/hardware/tmio.h>
++#include <linux/dma-mapping.h>
++
++/*-------------------------------------------------------------------------*/
++
++#define MAX_TMIO_USB_PORTS 2
++static bool default_tmio_ports[MAX_TMIO_USB_PORTS];
++module_param_array(default_tmio_ports, bool, NULL, 0644);
++MODULE_PARM_DESC(default_tmio_ports,
++              "disable specified TC6393 usb ports (default: all enabled)");
++
++/*-------------------------------------------------------------------------*/
++
++/*
++ * USB Host Controller Configuration Register
++ */
++struct tmio_uhccr {
++      u8 x00[8];
++      u8      revid;  /* 0x08 Revision ID                             */
++      u8 x01[7];
++      u16     basel;  /* 0x10 USB Control Register Base Address Low   */
++      u16     baseh;  /* 0x12 USB Control Register Base Address High  */
++      u8 x02[0x2c];
++      u8      ilme;   /* 0x40 Internal Local Memory Enable            */
++      u8 x03[0x0b];
++      u16     pm;     /* 0x4c Power Management                        */
++      u8 x04[2];
++      u8      intc;   /* 0x50 INT Control                             */
++      u8 x05[3];
++      u16     lmw1l;  /* 0x54 Local Memory Window 1 LMADRS Low        */
++      u16     lmw1h;  /* 0x56 Local Memory Window 1 LMADRS High       */
++      u16     lmw1bl; /* 0x58 Local Memory Window 1 Base Address Low  */
++      u16     lmw1bh; /* 0x5A Local Memory Window 1 Base Address High */
++      u16     lmw2l;  /* 0x5C Local Memory Window 2 LMADRS Low        */
++      u16     lmw2h;  /* 0x5E Local Memory Window 2 LMADRS High       */
++      u16     lmw2bl; /* 0x60 Local Memory Window 2 Base Address Low  */
++      u16     lmw2bh; /* 0x62 Local Memory Window 2 Base Address High */
++      u8 x06[0x98];
++      u8      misc;   /* 0xFC MISC                                    */
++      u8 x07[3];
++} __attribute__((packed));
++
++union tmio_uhccr_pm {
++      u16             raw;
++struct {
++      unsigned        gcken:1;        /* D0 */
++      unsigned        ckrnen:1;       /* D1 */
++      unsigned        uspw0:1;        /* D2 USB Port 1 Power Disable  */
++      unsigned        uspw1:1;        /* D3 USB Port 2 Power Disable  */
++      unsigned        x00:4;
++      unsigned        pmee:1;         /* D8 */
++      unsigned        x01:6;
++      unsigned        pmes:1;         /* D15 */
++} __attribute__((packed));
++} __attribute__((packed));
++
++/*-------------------------------------------------------------------------*/
++
++struct tmio_hcd {
++      struct tmio_uhccr __iomem *ccr;
++      bool disabled_ports[MAX_TMIO_USB_PORTS];
++};
++
++#define hcd_to_tmio(hcd)      ((struct tmio_hcd *)(hcd_to_ohci(hcd) + 1))
++#define ohci_to_tmio(ohci)    ((struct tmio_hcd *)(ohci + 1))
++
++/*-------------------------------------------------------------------------*/
++
++struct indexed_device_attribute{
++      struct device_attribute dev_attr;
++      int index;
++};
++#define to_indexed_dev_attr(_dev_attr) \
++      container_of(_dev_attr, struct indexed_device_attribute, dev_attr)
++
++#define INDEXED_ATTR(_name, _mode, _show, _store, _index)             \
++      { .dev_attr = __ATTR(_name ## _index, _mode, _show, _store),    \
++        .index = _index }
++
++#define INDEXED_DEVICE_ATTR(_name, _mode, _show, _store, _index)      \
++struct indexed_device_attribute dev_attr_##_name ## _index    \
++      = INDEXED_ATTR(_name, _mode, _show, _store, _index)
++
++/*-------------------------------------------------------------------------*/
++
++
++static void tmio_fill_pm(struct tmio_hcd *tmio, union tmio_uhccr_pm *pm)
++{
++      pm->raw = 0;
++
++      pm->pmee        = 1;
++      pm->pmes        = 1;
++      pm->gcken       = 1;
++      pm->ckrnen      = 1;
++
++      if (tmio->disabled_ports[0])
++              pm->uspw0 = 1;
++      if (tmio->disabled_ports[1])
++              pm->uspw1 = 1;
++}
++
++static void tmio_stop_hc(struct device *dev)
++{
++      struct tmio_device              *tdev   = dev_to_tdev(dev);
++      struct usb_hcd                  *hcd    = dev_get_drvdata(dev);
++      struct tmio_hcd                 *tmio   = hcd_to_tmio(hcd);
++      struct tmio_uhccr __iomem       *ccr    = tmio->ccr;
++      union tmio_uhccr_pm             pm      = {0};
++
++      pm.gcken        = 1;
++      pm.ckrnen       = 1;
++      pm.uspw0        = 1;
++      pm.uspw1        = 1;
++
++      iowrite8(0,             &ccr->intc);
++      iowrite8(0,             &ccr->ilme);
++      iowrite16(0,            &ccr->basel);
++      iowrite16(0,            &ccr->baseh);
++      iowrite16(pm.raw,       &ccr->pm);
++
++      tdev->ops->function(dev, 0);
++      tdev->ops->clock(dev, 0);
++}
++
++static void tmio_start_hc(struct device *dev)
++{
++      struct tmio_device              *tdev   = dev_to_tdev(dev);
++      struct usb_hcd                  *hcd    = dev_get_drvdata(dev);
++      struct tmio_hcd                 *tmio   = hcd_to_tmio(hcd);
++      struct tmio_uhccr __iomem       *ccr    = tmio->ccr;
++      union tmio_uhccr_pm             pm      = {0};
++      unsigned long                   base    = hcd->rsrc_start;
++
++      tmio_fill_pm(tmio, &pm);
++
++      tdev->ops->clock(dev, 1);
++      tdev->ops->function(dev, 1);
++
++      iowrite16(pm.raw,       &ccr->pm);
++      iowrite16(base,         &ccr->basel);
++      iowrite16(base >> 16,   &ccr->baseh);
++      iowrite8(1,             &ccr->ilme);
++      iowrite8(2,             &ccr->intc);
++
++      dev_info(dev, "revision %d @ 0x%08llx, irq %d\n",
++                      ioread8(&ccr->revid), hcd->rsrc_start, hcd->irq);
++}
++
++static ssize_t tmio_disabled_port_show(struct device *dev,
++              struct device_attribute *attr,
++              char *buf)
++{
++      struct usb_hcd          *hcd    = dev_get_drvdata(dev);
++      struct tmio_hcd         *tmio   = hcd_to_tmio(hcd);
++      int                     index   = to_indexed_dev_attr(attr)->index;
++      return snprintf(buf, PAGE_SIZE, "%c",
++                      tmio->disabled_ports[index]? 'Y': 'N');
++}
++
++static ssize_t tmio_disabled_port_store(struct device *dev,
++              struct device_attribute *attr,
++              const char *buf, size_t count)
++{
++      struct usb_hcd          *hcd    = dev_get_drvdata(dev);
++      struct tmio_hcd         *tmio   = hcd_to_tmio(hcd);
++      struct tmio_uhccr __iomem *ccr  = tmio->ccr;
++      union tmio_uhccr_pm     pm      = {0};
++      int                     index   = to_indexed_dev_attr(attr)->index;
++
++      if (!count)
++              return -EINVAL;
++
++      switch (buf[0]) {
++      case 'y': case 'Y': case '1':
++              tmio->disabled_ports[index] = true;
++              break;
++      case 'n': case 'N': case '0':
++              tmio->disabled_ports[index] = false;
++              break;
++      default:
++              return -EINVAL;
++      }
++
++      tmio_fill_pm(tmio, &pm);
++
++      iowrite16(pm.raw,       &ccr->pm);
++
++      return 1;
++}
++
++
++static INDEXED_DEVICE_ATTR(disabled_usb_port, S_IRUGO | S_IWUSR,
++              tmio_disabled_port_show, tmio_disabled_port_store, 0);
++static INDEXED_DEVICE_ATTR(disabled_usb_port, S_IRUGO | S_IWUSR,
++              tmio_disabled_port_show, tmio_disabled_port_store, 1);
++
++static int usb_hcd_tmio_probe(const struct hc_driver *driver,
++              struct device *dev)
++{
++      struct tmio_device      *tdev   = dev_to_tdev(dev);
++      struct resource         *config = tmio_resource_config(dev);
++      struct resource         *regs   = tmio_resource_control(dev);
++      struct resource         *sram   = tmio_resource_mem(dev);
++      struct resource         *irq    = tmio_resource_irq(dev);
++      struct tmio_hcd         *tmio;
++      struct ohci_hcd         *ohci;
++      struct usb_hcd          *hcd;
++      int                     retval;
++
++      if (usb_disabled())
++              return -ENODEV;
++
++      hcd = usb_create_hcd(driver, dev, dev->bus_id);
++      if (!hcd) {
++              retval = -ENOMEM;
++              goto err_usb_create_hcd;
++      }
++
++      retval = request_resource(tdev->iomem, config);
++      if (retval)
++              goto err_request_config_resource;
++
++      retval = request_resource(tdev->iomem, regs);
++      if (retval)
++              goto err_request_regs_resource;
++
++      retval = request_resource(tdev->iomem, sram);
++      if (retval)
++              goto err_request_sram_resource;
++
++      hcd->rsrc_start = regs->start;
++      hcd->rsrc_len   = regs->end - regs->start + 1;
++
++      tmio            = hcd_to_tmio(hcd);
++      memcpy(tmio->disabled_ports,
++                      default_tmio_ports,
++                      sizeof(default_tmio_ports));
++
++      tmio->ccr = ioremap(config->start, config->end - config->start + 1);
++      if (!tmio->ccr) {
++              retval = -ENOMEM;
++              goto err_ioremap_ccr;
++      }
++
++      hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
++      if (!hcd->regs) {
++              retval = -ENOMEM;
++              goto err_ioremap_regs;
++      }
++
++      if (dma_declare_coherent_memory(dev, sram->start,
++                              sram->start,
++                              sram->end - sram->start + 1,
++                              DMA_MEMORY_MAP) != DMA_MEMORY_MAP) {
++              retval = -EBUSY;
++              goto err_dma_declare;
++      }
++
++      retval = dmabounce_register_dev(dev, 512, 4096);
++      if (retval)
++              goto err_dmabounce_register_dev;
++
++      tmio_start_hc(dev);
++      ohci = hcd_to_ohci(hcd);
++      ohci_hcd_init(ohci);
++
++      retval  = device_create_file(dev,
++                      &dev_attr_disabled_usb_port0.dev_attr);
++      retval |= device_create_file(dev,
++                      &dev_attr_disabled_usb_port1.dev_attr);
++
++      if (retval)
++              goto err_create_file;
++
++      retval = usb_add_hcd(hcd, irq->start, IRQF_DISABLED);
++
++      if (retval == 0)
++              return retval;
++
++err_create_file:
++      device_remove_file(dev, &dev_attr_disabled_usb_port1.dev_attr);
++      device_remove_file(dev, &dev_attr_disabled_usb_port0.dev_attr);
++
++      tmio_stop_hc(dev);
++
++      dmabounce_unregister_dev(dev);
++err_dmabounce_register_dev:
++      dma_release_declared_memory(dev);
++err_dma_declare:
++      iounmap(hcd->regs);
++err_ioremap_regs:
++      iounmap(tmio->ccr);
++err_ioremap_ccr:
++      release_resource(sram);
++err_request_sram_resource:
++      release_resource(regs);
++err_request_regs_resource:
++      release_resource(config);
++err_request_config_resource:
++      usb_put_hcd(hcd);
++err_usb_create_hcd:
++
++      return retval;
++}
++
++static void usb_hcd_tmio_remove(struct usb_hcd *hcd, struct device *dev)
++{
++      struct tmio_hcd         *tmio   = hcd_to_tmio(hcd);
++
++      usb_remove_hcd(hcd);
++      device_remove_file(dev, &dev_attr_disabled_usb_port1.dev_attr);
++      device_remove_file(dev, &dev_attr_disabled_usb_port0.dev_attr);
++      tmio_stop_hc(dev);
++      dmabounce_unregister_dev(dev);
++      dma_release_declared_memory(dev);
++      iounmap(hcd->regs);
++      iounmap(tmio->ccr);
++      release_resource(tmio_resource_mem(dev));
++      release_resource(tmio_resource_control(dev));
++      release_resource(tmio_resource_config(dev));
++      usb_put_hcd(hcd);
++}
++
++static int __devinit
++ohci_tmio_start(struct usb_hcd *hcd)
++{
++      struct ohci_hcd         *ohci   = hcd_to_ohci(hcd);
++      int                     retval;
++
++      if ((retval = ohci_init(ohci)) < 0)
++              return retval;
++
++      if ((retval = ohci_run(ohci)) < 0) {
++              err("can't start %s", hcd->self.bus_name);
++              ohci_stop(hcd);
++              return retval;
++      }
++
++      return 0;
++}
++
++static const struct hc_driver ohci_tmio_hc_driver = {
++      .description =          hcd_name,
++      .product_desc =         "TMIO OHCI USB Host Controller",
++      .hcd_priv_size =        sizeof(struct ohci_hcd) + sizeof (struct tmio_hcd),
++
++      /* generic hardware linkage */
++      .irq =                  ohci_irq,
++      .flags =                HCD_USB11 | HCD_MEMORY,
++
++      /* basic lifecycle operations */
++      .start =                ohci_tmio_start,
++      .stop =                 ohci_stop,
++      .shutdown =             ohci_shutdown,
++
++      /* managing i/o requests and associated device resources */
++      .urb_enqueue =          ohci_urb_enqueue,
++      .urb_dequeue =          ohci_urb_dequeue,
++      .endpoint_disable =     ohci_endpoint_disable,
++
++      /* scheduling support */
++      .get_frame_number =     ohci_get_frame,
++
++      /* root hub support */
++      .hub_status_data =      ohci_hub_status_data,
++      .hub_control =          ohci_hub_control,
++      .hub_irq_enable =       ohci_rhsc_enable,
++#ifdef        CONFIG_PM
++      .bus_suspend =          ohci_bus_suspend,
++      .bus_resume =           ohci_bus_resume,
++#endif
++      .start_port_reset =     ohci_start_port_reset,
++};
++
++/*-------------------------------------------------------------------------*/
++static struct device_driver tmio_ohci;
++
++static int
++tmio_dmabounce_check(struct device *dev, dma_addr_t dma, size_t size, void *data)
++{
++      struct resource         *sram   = data;
++#ifdef DEBUG
++      printk(KERN_ERR "tmio_dmabounce_check: %08x %d\n", dma, size);
++#endif
++
++      if (dev->driver != &tmio_ohci)
++              return 0;
++
++      if (sram->start <= dma && dma + size <= sram->end)
++              return 0;
++
++      return 1;
++}
++
++static u64 dma_mask = DMA_32BIT_MASK;
++
++static int ohci_hcd_tmio_drv_probe(struct device *dev)
++{
++      struct resource         *sram   = tmio_resource_mem(dev);
++      int retval;
++
++      dev->dma_mask = &dma_mask;
++      dev->coherent_dma_mask = DMA_32BIT_MASK;
++
++      /* FIXME: move dmabounce checkers to tc6393 core? */
++      dmabounce_register_checker(tmio_dmabounce_check, sram);
++
++      retval = usb_hcd_tmio_probe(&ohci_tmio_hc_driver, dev);
++
++      if (retval == 0)
++              return retval;
++
++      dmabounce_remove_checker(tmio_dmabounce_check, sram);
++
++      return retval;
++}
++
++static int ohci_hcd_tmio_drv_remove(struct device *dev)
++{
++      struct usb_hcd          *hcd    = dev_get_drvdata(dev);
++      struct resource         *sram   = tmio_resource_mem(dev);
++
++      usb_hcd_tmio_remove(hcd, dev);
++
++      dev_set_drvdata(dev, NULL);
++
++      dmabounce_remove_checker(tmio_dmabounce_check, sram);
++
++      return 0;
++}
++
++#ifdef        CONFIG_PM
++static int ohci_hcd_tmio_drv_suspend(struct device *dev, pm_message_t state)
++{
++      struct usb_hcd          *hcd    = dev_get_drvdata(dev);
++      struct ohci_hcd         *ohci   = hcd_to_ohci(hcd);
++
++      if (time_before(jiffies, ohci->next_statechange))
++              msleep(5);
++      ohci->next_statechange = jiffies;
++
++      tmio_stop_hc(dev);
++      hcd->state = HC_STATE_SUSPENDED;
++      dev->power.power_state = PMSG_SUSPEND;
++
++      return 0;
++}
++
++static int ohci_hcd_tmio_drv_resume(struct device *dev)
++{
++      struct usb_hcd          *hcd    = dev_get_drvdata(dev);
++      struct ohci_hcd         *ohci   = hcd_to_ohci(hcd);
++
++      if (time_before(jiffies, ohci->next_statechange))
++              msleep(5);
++      ohci->next_statechange = jiffies;
++
++      tmio_start_hc(dev);
++
++      dev->power.power_state = PMSG_ON;
++      usb_hcd_resume_root_hub(hcd);
++
++      return 0;
++}
++#endif
++
++static void usb_hcd_device_shutdown(struct device *dev)
++{
++      struct usb_hcd *hcd = dev_get_drvdata(dev);
++
++      if (hcd->driver->shutdown)
++              hcd->driver->shutdown(hcd);
++}
++
++static struct device_driver tmio_ohci = {
++      .owner          = THIS_MODULE,
++      .name           = TMIO_NAME_OHCI,
++      .bus            = &tmio_bus_type,
++      .probe          = ohci_hcd_tmio_drv_probe,
++      .remove         = ohci_hcd_tmio_drv_remove,
++      .shutdown       = usb_hcd_device_shutdown,
++#ifdef CONFIG_PM
++      .suspend        = ohci_hcd_tmio_drv_suspend,
++      .resume         = ohci_hcd_tmio_drv_resume,
++#endif
++};
++
+Index: linux-2.6.23/drivers/usb/host/Kconfig
+===================================================================
+--- linux-2.6.23.orig/drivers/usb/host/Kconfig 2007-10-10 00:31:38.000000000 +0400
++++ linux-2.6.23/drivers/usb/host/Kconfig      2007-11-12 13:46:53.086559913 +0300
+@@ -101,6 +101,7 @@
+       depends on USB && USB_ARCH_HAS_OHCI
+       select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3
+       select I2C if ARCH_PNX4008
++      select GENERIC_ALLOCATOR if TOSHIBA_TC6393XB
+       ---help---
+         The Open Host Controller Interface (OHCI) is a standard for accessing
+         USB 1.1 host controller hardware.  It does more in hardware than Intel's
+Index: linux-2.6.23/drivers/usb/host/ohci-hcd.c
+===================================================================
+--- linux-2.6.23.orig/drivers/usb/host/ohci-hcd.c      2007-11-12 13:46:52.894560883 +0300
++++ linux-2.6.23/drivers/usb/host/ohci-hcd.c   2007-11-14 16:44:32.788069355 +0300
+@@ -915,6 +915,10 @@
+ #define PLATFORM_DRIVER               usb_hcd_pnx4008_driver
+ #endif
++#ifdef CONFIG_TOSHIBA_TC6393XB
++#include "ohci-tmio.c"
++#define DEVICE_DRIVER         tmio_ohci
++#endif
+ #ifdef CONFIG_USB_OHCI_HCD_PPC_OF
+ #include "ohci-ppc-of.c"
+Index: linux-2.6.23/drivers/usb/Kconfig
+===================================================================
+--- linux-2.6.23.orig/drivers/usb/Kconfig      2007-10-10 00:31:38.000000000 +0400
++++ linux-2.6.23/drivers/usb/Kconfig   2007-11-12 13:46:53.090570777 +0300
+@@ -42,6 +42,7 @@
+       # MIPS:
+       default y if SOC_AU1X00
+       # more:
++      default y if TOSHIBA_TC6393XB
+       default PCI
+ # some non-PCI hcds implement EHCI
+Index: linux-2.6.23/arch/arm/common/Kconfig
+===================================================================
+--- linux-2.6.23.orig/arch/arm/common/Kconfig  2007-11-12 13:46:48.754297930 +0300
++++ linux-2.6.23/arch/arm/common/Kconfig       2007-11-12 13:46:53.090570777 +0300
+@@ -35,3 +35,4 @@
+ config TOSHIBA_TC6393XB
+       bool
++      select DMABOUNCE
diff --git a/packages/kexecboot/linux-kexecboot-2.6.23/tmio-tc6393-r8.patch b/packages/kexecboot/linux-kexecboot-2.6.23/tmio-tc6393-r8.patch
new file mode 100644 (file)
index 0000000..1bfdc23
--- /dev/null
@@ -0,0 +1,800 @@
+ arch/arm/common/Kconfig         |    3 
+ arch/arm/common/Makefile        |    1 
+ arch/arm/common/tc6393xb.c      |  668 ++++++++++++++++++++++++++++++++++++++++
+ arch/arm/mach-pxa/Kconfig       |    1 
+ include/asm-arm/arch-pxa/irqs.h |   10 
+ include/asm-arm/hardware/tmio.h |   44 ++
+ 6 files changed, 727 insertions(+)
+
+Index: git/arch/arm/common/tc6393xb.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ git/arch/arm/common/tc6393xb.c     2006-11-07 22:14:49.000000000 +0000
+@@ -0,0 +1,668 @@
++/*
++ * Toshiba TC6393XB SoC support
++ *
++ * Maintainer: Chris Humbert <mahadri-kernel@drigon.com>
++ *
++ * Copyright (c) 2005-2006 Chris Humbert
++ * Copyright (c) 2005 Dirk Opfer
++ *
++ * Based on code written by Sharp/Lineo for 2.4 kernels
++ * Based on locomo.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/module.h>
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/delay.h>
++#include <linux/errno.h>
++#include <linux/ioport.h>
++#include <linux/device.h>
++#include <linux/platform_device.h>
++#include <linux/slab.h>
++#include <linux/spinlock.h>
++#include <linux/fb.h>
++
++#include <asm/hardware.h>
++#include <asm/mach-types.h>
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/mach/irq.h>
++#include <asm/arch/irqs.h>
++#include <asm/hardware/tmio.h>
++
++#ifndef TMIO_SOC_TC6393XB
++#error "TC6393XB SoC not configured"
++#endif
++
++/*--------------------------------------------------------------------------*/
++
++/* cell ids must be 0-based because they are used as array indexes. */
++#define       TC6393_CELL_NAND        0
++#define TC6393_CELL_SD                1
++#define       TC6393_CELL_OHCI        2
++#define TC6393_CELL_SERIAL    3
++#define TC6393_CELL_LCD               4
++#define TC6393_NUM_CELLS      5
++
++#define TC6393_RESOURCE(_name, _start, _end, _flags)  \
++      {                                               \
++              .name           = _name,                \
++              .start          = _start,               \
++              .end            = _end,                 \
++              .flags          = _flags,               \
++      }
++
++#define TC6393_MEM(name, start, size) \
++      TC6393_RESOURCE(name, start, (start) + (size) - 1, IORESOURCE_MEM)
++
++#define TC6393_IRQ(name, irq) \
++      TC6393_RESOURCE(name, irq, irq, IORESOURCE_IRQ)
++
++const static struct resource tc6393_NAND_resource[] = {
++      TC6393_MEM (TMIO_NAME_NAND,     0x000100,       0x100),
++      TC6393_MEM (TMIO_NAME_NAND,     0x001000,       0x008),
++      TC6393_MEM (TMIO_NAME_NAND,     0,              0),
++      TC6393_IRQ (TMIO_NAME_NAND,     IRQ_TC6393_NAND),
++};
++
++const static struct resource tc6393_SD_resource[] = {
++      TC6393_MEM (TMIO_NAME_SD,       0x000200,       0x100),
++      TC6393_MEM (TMIO_NAME_SD,       0x002000,       0x200),
++      TC6393_MEM (TMIO_NAME_SD,       0,              0),
++      TC6393_IRQ (TMIO_NAME_SD,       IRQ_TC6393_SD),
++};
++
++const static struct resource tc6393_OHCI_resource[] = {
++      TC6393_MEM (TMIO_NAME_OHCI,     0x000300,       0x100),
++      TC6393_MEM (TMIO_NAME_OHCI,     0x003000,       0x100),
++      TC6393_MEM (TMIO_NAME_OHCI,     0x010000,       32 * 1024),
++      TC6393_IRQ (TMIO_NAME_OHCI,     IRQ_TC6393_OHCI),
++};
++
++const static struct resource tc6393_SERIAL_resource[] = {
++      TC6393_MEM (TMIO_NAME_SERIAL,   0x000400,       0x100),
++      TC6393_MEM (TMIO_NAME_SERIAL,   0x004000,       0x100),
++      TC6393_MEM (TMIO_NAME_SERIAL,   0,              0),
++      TC6393_IRQ (TMIO_NAME_SERIAL,   IRQ_TC6393_SERIAL),
++};
++
++const static struct resource tc6393_LCD_resource[] = {
++      TC6393_MEM (TMIO_NAME_LCD,      0x000500,       0x100),
++      TC6393_MEM (TMIO_NAME_LCD,      0x005000,       0x200),
++      TC6393_MEM (TMIO_NAME_LCD,      0x100000,       1024 * 1024),
++      TC6393_IRQ (TMIO_NAME_LCD,      IRQ_TC6393_LCD),
++};
++
++#define TC6393_CELL(_NAME)                                            \
++      [TC6393_CELL_##_NAME] = {                                       \
++              .name           = TMIO_NAME_##_NAME,                    \
++              .id             = TC6393_CELL_##_NAME,                  \
++              .resource       = tc6393_##_NAME##_resource,            \
++              .num_resources  = ARRAY_SIZE (tc6393_##_NAME##_resource), \
++      }
++
++struct tc6393_cell {
++      const char*             name;
++      unsigned int            id;
++      const struct resource*  resource;
++      unsigned int            num_resources;
++};
++
++const static struct tc6393_cell tc6393_cell [TC6393_NUM_CELLS] = {
++      TC6393_CELL (NAND       ),
++      TC6393_CELL (SD         ),
++      TC6393_CELL (OHCI       ),
++      TC6393_CELL (SERIAL     ),
++      TC6393_CELL (LCD        ),
++};
++
++/*--------------------------------------------------------------------------*/
++
++/*
++ * TC6393 System Configuration Register
++ */
++struct tc6393_scr {
++      u8 x00[8];
++      u8      revid;          /* 0x08 Revision ID                     */
++      u8 x01[0x47];
++      u8      isr;            /* 0x50 Interrupt Status                */
++      u8 x02;
++      u8      imr;            /* 0x52 Interrupt Mask                  */
++      u8 x03;
++      u8      irr;            /* 0x54 Interrupt Routing               */
++      u8 x04[0x0b];
++      u16     gper;           /* 0x60 GP Enable                       */
++      u8 x05[2];
++      u16     gpi_sr[2];      /* 0x64 GPI Status                      */
++      u16     gpi_imr[2];     /* 0x68 GPI INT Mask                    */
++      u16     gpi_eder[2];    /* 0x6c GPI Edge Detect Enable          */
++      u16     gpi_lir[4];     /* 0x70 GPI Level Invert                */
++      u16     gpo_dsr[2];     /* 0x78 GPO Data Set                    */
++      u16     gpo_doecr[2];   /* 0x7c GPO Data OE Control             */
++      u16     gp_iarcr[2];    /* 0x80 GP Internal Active Reg Control  */
++      u16     gp_iarlcr[2];   /* 0x84 GP Internal Active Reg Level Con*/
++      u8      gpi_bcr[4];     /* 0x88 GPI Buffer Control              */
++      u16     gpa_iarcr;      /* 0x8c GPa Internal Active Reg Control */
++      u8 x06[2];
++      u16     gpa_iarlcr;     /* 0x90 GPa Internal Active Reg Level Co*/
++      u8 x07[2];
++      u16     gpa_bcr;        /* 0x94 GPa Buffer Control              */
++      u8 x08[2];
++      u16     ccr;            /* 0x98 Clock Control                   */
++      u16     pll2cr;         /* 0x9a PLL2 Control                    */
++      u16     pll1cr[2];      /* 0x9c PLL1 Control                    */
++      u8      diarcr;         /* 0xa0 Device Internal Active Reg Contr*/
++      u8      dbocr;          /* 0xa1 Device Buffer Off Control       */
++      u8 x09[0x3e];
++      u8      fer;            /* 0xe0 Function Enable                 */
++      u8 x10[3];
++      u16     mcr;            /* 0xe4 Mode Control                    */
++      u8 x11[0x14];
++      u8      config;         /* 0xfc Configuration Control           */
++      u8 x12[2];
++      u8      debug;          /* 0xff Debug                           */
++} __attribute__ ((packed));
++
++union tc6393_scr_fer {
++      u8              raw;
++struct {
++      unsigned        usben:1;        /* D0   USB enable              */
++      unsigned        lcdcven:1;      /* D1   polysylicon TFT enable  */
++      unsigned        slcden:1;       /* D2   SLCD enable             */
++} __attribute__ ((packed));
++} __attribute__ ((packed));
++
++union tc6393_scr_ccr {
++      u16             raw;
++struct {
++      unsigned        ck32ken:1;      /* D0   SD host clock enable    */
++      unsigned        usbcken:1;      /* D1   USB host clock enable   */
++      unsigned        x00:2;
++      unsigned        sharp:1;        /* D4   ??? set in Sharp's code */
++      unsigned        x01:3;
++      enum {                          disable = 0,
++                                      m12MHz  = 1,
++                                      m24MHz  = 2,
++                                      m48MHz  = 3,
++      }               mclksel:3;      /* D10-D8  LCD controller clock */
++      unsigned        x02:1;
++      enum {                          h24MHz  = 0,
++                                      h48MHz  = 1,
++      }               hclksel:2;      /* D13-D12 host bus clock       */
++      unsigned        x03:2;
++} __attribute__ ((packed));
++} __attribute__ ((packed));
++
++/*--------------------------------------------------------------------------*/
++
++struct tc6393 {
++      spinlock_t              lock;   /* read-modify-write lock       */
++      struct device*          dev;    /* TC6393 device                */
++      struct tc6393_scr __iomem *scr; /* system configuration reg     */
++
++      struct resource         rscr;   /* system config reg resource   */
++      struct resource*        iomem;  /* entire TC6393 iomem resource */
++      unsigned int            irq;    /* hardware cascade irq         */
++
++      struct tmio_device      tdev [TC6393_NUM_CELLS];
++};
++
++/*--------------------------------------------------------------------------*/
++
++static u32 tc6393_ioread32 (const void __iomem *addr)
++{
++      return ((u32) ioread16 (addr)) | (((u32) ioread16 (addr + 2)) << 16);
++}
++
++static u32 tc6393_iowrite32 (u32 val, const void __iomem *addr)
++{
++      iowrite16 (val,         addr);
++      iowrite16 (val >> 16,   addr + 2);
++      return val;
++}
++
++u32 get_tc6393_gpio (struct device *dev)
++{
++      struct tc6393*                  tc6393  = dev_get_drvdata (dev);
++      struct tc6393_scr __iomem *     scr     = tc6393->scr;
++
++      return tc6393_ioread32 (scr->gpo_dsr);
++}
++EXPORT_SYMBOL (get_tc6393_gpio);
++
++u32 set_tc6393_gpio (struct device *dev, u32 bits)
++{
++      struct tc6393*                  tc6393  = dev_get_drvdata (dev);
++      struct tc6393_scr __iomem *     scr     = tc6393->scr;
++      unsigned long                   flags;
++      u32                             dsr;
++
++      spin_lock_irqsave (&tc6393->lock, flags);
++      dsr = tc6393_ioread32 (scr->gpo_dsr) | bits;
++      tc6393_iowrite32 (dsr, scr->gpo_dsr);
++      spin_unlock_irqrestore (&tc6393->lock, flags);
++
++      return dsr;
++}
++EXPORT_SYMBOL (set_tc6393_gpio);
++
++u32 reset_tc6393_gpio (struct device *dev, u32 bits)
++{
++      struct tc6393*                  tc6393  = dev_get_drvdata (dev);
++      struct tc6393_scr __iomem *     scr     = tc6393->scr;
++      unsigned long                   flags;
++      u32                             dsr;
++
++      spin_lock_irqsave (&tc6393->lock, flags);
++      dsr = tc6393_ioread32 (scr->gpo_dsr) & ~bits;
++      tc6393_iowrite32 (dsr, scr->gpo_dsr);
++      spin_unlock_irqrestore (&tc6393->lock, flags);
++
++      return dsr;
++}
++EXPORT_SYMBOL (reset_tc6393_gpio);
++
++/*--------------------------------------------------------------------------*/
++
++static void
++tc6393_irq (unsigned int irq, struct irq_desc *desc)
++{
++      struct tc6393*                  tc6393  = get_irq_chip_data (irq);
++      struct tc6393_scr __iomem *     scr     = tc6393->scr;
++      unsigned int                    isr;
++      unsigned int                    bit;
++      unsigned int                    i;
++
++      desc->chip->ack (irq);
++
++      while ((isr = ioread8(&scr->isr) & ~ioread8(&scr->imr)))
++              for (bit = 1, i = IRQ_TC6393_START; i <= IRQ_TC6393_LCD;
++                                                              bit <<= 1, i++)
++                      if (isr & bit)
++                              desc_handle_irq (i, irq_desc + i);
++}
++
++static void tc6393_irq_ack (unsigned int irq)
++{
++}
++
++static void tc6393_irq_mask (unsigned int irq)
++{
++      struct tc6393*                  tc6393  = get_irq_chip_data (irq);
++      struct tc6393_scr __iomem *     scr     = tc6393->scr;
++      unsigned long                   flags;
++
++      spin_lock_irqsave (&tc6393->lock, flags);
++      iowrite8 (ioread8 (&scr->imr) | (1 << (irq - IRQ_TC6393_START)),
++                                                              &scr->imr);
++      spin_unlock_irqrestore (&tc6393->lock, flags);
++}
++
++static void tc6393_irq_unmask (unsigned int irq)
++{
++      struct tc6393*                  tc6393  = get_irq_chip_data (irq);
++      struct tc6393_scr __iomem *     scr     = tc6393->scr;
++      unsigned long                   flags;
++
++      spin_lock_irqsave (&tc6393->lock, flags);
++      iowrite8 (ioread8 (&scr->imr) & ~(1 << (irq - IRQ_TC6393_START)),
++                                                              &scr->imr);
++      spin_unlock_irqrestore (&tc6393->lock, flags);
++}
++
++static struct irq_chip tc6393_chip = {
++      .ack    = tc6393_irq_ack,
++      .mask   = tc6393_irq_mask,
++      .unmask = tc6393_irq_unmask,
++};
++
++static void tc6393_attach_irq (struct tc6393 *tc6393)
++{
++      unsigned int            irq;
++
++      for (irq = IRQ_TC6393_START; irq <= IRQ_TC6393_LCD; irq++) {
++              set_irq_chip    (irq, &tc6393_chip);
++              set_irq_chip_data(irq, tc6393);
++              set_irq_handler (irq, handle_edge_irq);
++              set_irq_flags   (irq, IRQF_VALID | IRQF_PROBE);
++      }
++
++      set_irq_type            (tc6393->irq, IRQT_FALLING);
++      set_irq_chip_data       (tc6393->irq, tc6393);
++      set_irq_chained_handler (tc6393->irq, tc6393_irq);
++}
++
++static void tc6393_detach_irq (struct tc6393 *tc6393)
++{
++      unsigned int            irq;
++
++      set_irq_chained_handler (tc6393->irq, NULL);
++      set_irq_chip_data       (tc6393->irq, NULL);
++
++      for (irq = IRQ_TC6393_START; irq <= IRQ_TC6393_LCD; irq++) {
++              set_irq_flags   (irq, 0);
++              set_irq_chip    (irq, NULL);
++              set_irq_chip_data(irq, NULL);
++      }
++}
++
++/*--------------------------------------------------------------------------*/
++
++static int tc6393_bus_match (struct device *dev, struct device_driver *drv)
++{
++      struct tmio_device*             tdev    = dev_to_tdev (dev);
++      const struct tc6393_cell*       cell    = tdev->soc_data;
++
++      return !strcmp (cell->name, drv->name);
++}
++
++static int tc6393_bus_suspend (struct device *dev, pm_message_t state)
++{
++      struct device_driver*   drv     = dev->driver;
++      return drv && drv->suspend ? drv->suspend (dev, state) : 0;
++}
++
++static int tc6393_bus_resume (struct device *dev)
++{
++      struct device_driver*   drv     = dev->driver;
++      return drv && drv->resume ? drv->resume (dev) : 0;
++}
++
++struct bus_type tc6393_bus_type = {
++      .name           = TMIO_NAME_BUS,
++      .match          = tc6393_bus_match,
++      .suspend        = tc6393_bus_suspend,
++      .resume         = tc6393_bus_resume,
++};
++EXPORT_SYMBOL (tc6393_bus_type);
++
++/*--------------------------------------------------------------------------*/
++
++static void tc6393_cell_clock (struct device *dev, int enable)
++{
++      struct tmio_device*             tdev    = dev_to_tdev (dev);
++      const struct tc6393_cell*       cell    = tdev->soc_data;
++      struct tc6393*                  tc6393  = dev_get_drvdata (dev->parent);
++      struct tc6393_scr __iomem *     scr     = tc6393->scr;
++      union tc6393_scr_ccr            ccr;
++      unsigned long                   flags;
++
++      spin_lock_irqsave (&tc6393->lock, flags);
++      ccr.raw = ioread16 (&scr->ccr);
++
++      switch (cell->id) {
++              case TC6393_CELL_SD:    ccr.ck32ken     = enable;       break;
++              case TC6393_CELL_OHCI:  ccr.usbcken     = enable;       break;
++              case TC6393_CELL_LCD:
++                      ccr.mclksel = enable ? m48MHz : disable;
++                      break;
++      }
++
++      printk (KERN_DEBUG TMIO_NAME_CORE ": scr->ccr = %04x\n", ccr.raw);
++
++      iowrite16(ccr.raw, &scr->ccr);
++      spin_unlock_irqrestore (&tc6393->lock, flags);
++}
++
++static void tc6393_cell_function (struct device *dev, int enable)
++{
++      struct tmio_device*             tdev    = dev_to_tdev (dev);
++      const struct tc6393_cell*       cell    = tdev->soc_data;
++      struct tc6393*                  tc6393  = dev_get_drvdata (dev->parent);
++      struct tc6393_scr __iomem *     scr     = tc6393->scr;
++      union tc6393_scr_fer            fer;
++      unsigned long                   flags;
++
++      if (cell->id == TC6393_CELL_NAND) {
++              if (enable) {
++                      /* SMD buffer on */
++                      printk (KERN_DEBUG TMIO_NAME_CORE ": SMD buffer on\n");
++                      iowrite8 (0xff, scr->gpi_bcr + 1);
++              }
++              return;
++      }
++
++      spin_lock_irqsave (&tc6393->lock, flags);
++      fer.raw = ioread16 (&scr->fer);
++
++      switch (cell->id) {
++              case TC6393_CELL_OHCI:  fer.usben       = enable;       break;
++              case TC6393_CELL_LCD:   fer.slcden      = enable;       break;
++      }
++
++      printk (KERN_DEBUG TMIO_NAME_CORE ": scr->fer = %02x\n", fer.raw);
++
++      iowrite8 (fer.raw, &scr->fer);
++      spin_unlock_irqrestore (&tc6393->lock, flags);
++}
++
++static void
++tc6393_lcd_mode (struct device *dev, const struct fb_videomode *mode)
++{
++      struct tc6393*                  tc6393  = dev_get_drvdata (dev->parent);
++      struct tc6393_scr __iomem *     scr     = tc6393->scr;
++
++      iowrite16 (mode->pixclock,              scr->pll1cr + 0);
++      iowrite16 (mode->pixclock >> 16,        scr->pll1cr + 1);
++}
++
++static struct tmio_cell_ops tc6393_cell_ops = {
++      .clock          = tc6393_cell_clock,
++      .function       = tc6393_cell_function,
++      .lcd_mode       = tc6393_lcd_mode,
++};
++
++static void tc6393_device_release (struct device *dev)
++{
++}
++
++static int
++tc6393_device_register (struct tc6393 *tc6393, struct tmio_cell *tcell)
++{
++      const struct tc6393_cell*       cell;
++      struct tmio_device*             tdev;
++      struct device*                  dev;
++      int                             i;
++
++      for (i = 0; strcmp (tcell->name, tc6393_cell [i].name); )
++              if (++i >= ARRAY_SIZE(tc6393_cell))
++                      return -EINVAL;
++
++      cell                    = tc6393_cell  + i;
++      tdev                    = tc6393->tdev + i;
++      dev                     = &tdev->dev;
++
++      tdev->ops               = &tc6393_cell_ops;
++      tdev->iomem             = tc6393->iomem;
++      tdev->soc_data          = (void*) cell;
++
++      dev->parent             = tc6393->dev;
++      strncpy (dev->bus_id, cell->name, sizeof dev->bus_id);
++      dev->bus                = &tc6393_bus_type;
++      dev->dma_mask           = tc6393->dev->dma_mask;
++      dev->coherent_dma_mask  = tc6393->dev->coherent_dma_mask;
++      dev->release            = tc6393_device_release;
++      dev->platform_data      = tcell->platform_data;
++
++      for (i=0; i < cell->num_resources; i++) {
++              const struct resource*  cr      = cell->resource + i;
++              struct resource*        dr      = tdev->resource + i;
++
++              dr->name        = cr->name;
++              dr->start       = cr->start;
++              dr->end         = cr->end;
++              dr->flags       = cr->flags;
++
++              /* convert memory offsets to absolutes */
++              if (cr->flags & IORESOURCE_MEM) {
++                      dr->start       += tc6393->iomem->start;
++                      dr->end         += tc6393->iomem->start;
++              }
++      }
++
++      return device_register (dev);
++}
++
++/*--------------------------------------------------------------------------*/
++
++static void tc6393_hw_init (struct tc6393 *tc6393)
++{
++      struct tc6393_scr __iomem *     scr     = tc6393->scr;
++      struct tc6393_platform_data*    tcpd    = tc6393->dev->platform_data;
++
++      tcpd->enable (tc6393->dev);
++
++      iowrite8 (0,                            &scr->fer);
++      iowrite16(tcpd->scr_pll2cr,             &scr->pll2cr);
++      iowrite16(tcpd->scr_ccr,                &scr->ccr);
++      iowrite16(tcpd->scr_mcr,                &scr->mcr);
++      iowrite16(tcpd->scr_gper,               &scr->gper);
++      iowrite8 (0,                            &scr->irr);
++      iowrite8 (0xbf,                         &scr->imr);
++      iowrite16(tcpd->scr_gpo_dsr,            scr->gpo_dsr + 0);
++      iowrite16(tcpd->scr_gpo_dsr >> 16,      scr->gpo_dsr + 1);
++      iowrite16(tcpd->scr_gpo_doecr,          scr->gpo_doecr + 0);
++      iowrite16(tcpd->scr_gpo_doecr >> 16,    scr->gpo_doecr + 1);
++}
++
++static int tc6393_probe (struct device *dev)
++{
++      struct platform_device*         pdev    = to_platform_device (dev);
++      struct tc6393_platform_data*    tcpd    = dev->platform_data;
++      struct tc6393*                  tc6393;
++      struct resource*                iomem;
++      struct resource*                rscr;
++      int                             retval;
++      int                             i;
++
++      iomem = platform_get_resource (pdev, IORESOURCE_MEM, 0);
++      if (!iomem)
++              return -EINVAL;
++
++      tc6393 = kzalloc (sizeof *tc6393, GFP_KERNEL);
++      if (!tc6393) {
++              retval = -ENOMEM;
++              goto err_kzalloc;
++      }
++
++      dev_set_drvdata (dev, tc6393);
++      spin_lock_init (&tc6393->lock);
++      tc6393->dev     = dev;
++      tc6393->iomem   = iomem;
++      tc6393->irq     = platform_get_irq (pdev, 0);
++
++      rscr            = &tc6393->rscr;
++      rscr->name      = TMIO_NAME_CORE;
++      rscr->start     = iomem->start;
++      rscr->end       = iomem->start + 0xff;
++      rscr->flags     = IORESOURCE_MEM;
++
++      retval = request_resource (iomem, rscr);
++      if (retval)
++              goto err_request_scr;
++
++      tc6393->scr     = ioremap (rscr->start, rscr->end - rscr->start + 1);
++      if (!tc6393->scr) {
++              retval = -ENOMEM;
++              goto err_ioremap;
++      }
++
++      tc6393_hw_init (tc6393);
++
++      printk (KERN_INFO "Toshiba %s revision %d at 0x%08lx, irq %d\n",
++                      TMIO_SOC_NAME, ioread8 (&tc6393->scr->revid),
++                      iomem->start, tc6393->irq);
++
++      if (tc6393->irq)
++              tc6393_attach_irq (tc6393);
++
++      for (i = 0; i < tcpd->num_cells; i++)
++              tc6393_device_register (tc6393, tcpd->cell + i);
++
++      return 0;
++
++err_ioremap:
++      release_resource (rscr);
++err_request_scr:
++      kfree(tc6393);
++err_kzalloc:
++      release_resource (iomem);
++      return retval;
++}
++
++static int tc6393_dev_remove (struct device *dev, void *data)
++{
++      device_unregister (dev);
++      return 0;
++}
++
++static int tc6393_remove (struct device *dev)
++{
++      struct tc6393*          tc6393  = dev_get_drvdata (dev);
++
++      device_for_each_child (dev, tc6393, tc6393_dev_remove);
++
++      if (tc6393->irq)
++              tc6393_detach_irq (tc6393);
++
++      iounmap (tc6393->scr);
++      release_resource (&tc6393->rscr);
++      release_resource (tc6393->iomem);
++      kfree (tc6393);
++      return 0;
++}
++
++#ifdef CONFIG_PM
++static int tc6393_suspend (struct device *dev, pm_message_t state)
++{
++      struct tc6393_platform_data*    tcpd    = dev->platform_data;
++      tcpd->disable (dev);
++      return 0;
++}
++
++static int tc6393_resume (struct device *dev)
++{
++      struct tc6393*                  tc6393  = dev_get_drvdata (dev);
++      tc6393_hw_init (tc6393);
++      return 0;
++}
++#endif
++
++static struct device_driver tc6393_device_driver = {
++      .name           = TMIO_SOC_NAME,
++      .bus            = &platform_bus_type,
++      .probe          = tc6393_probe,
++      .remove         = tc6393_remove,
++#ifdef CONFIG_PM
++      .suspend        = tc6393_suspend,
++      .resume         = tc6393_resume,
++#endif
++};
++
++/*--------------------------------------------------------------------------*/
++
++static int __init tc6393_init (void)
++{
++      int retval = bus_register (&tc6393_bus_type);
++      if (retval)
++              return retval;
++
++      return driver_register (&tc6393_device_driver);
++}
++
++static void __exit tc6393_exit (void)
++{
++      driver_unregister (&tc6393_device_driver);
++      bus_unregister (&tc6393_bus_type);
++}
++
++module_init (tc6393_init);
++module_exit (tc6393_exit);
++
++MODULE_DESCRIPTION ("TC6393 SoC bus driver");
++MODULE_AUTHOR ("Chris Humbert, Dirk Opfer");
++MODULE_LICENSE ("GPL");
+Index: git/arch/arm/common/Kconfig
+===================================================================
+--- git.orig/arch/arm/common/Kconfig   2006-10-31 16:08:28.000000000 +0000
++++ git/arch/arm/common/Kconfig        2006-11-07 22:13:09.000000000 +0000
+@@ -31,3 +31,6 @@ config SHARPSL_PM
+ config SHARP_SCOOP
+       bool
++
++config TOSHIBA_TC6393XB
++      bool
+Index: git/arch/arm/mach-pxa/Kconfig
+===================================================================
+--- git.orig/arch/arm/mach-pxa/Kconfig 2006-11-07 22:13:06.000000000 +0000
++++ git/arch/arm/mach-pxa/     2006-11-07 23:30:34.000000000 +0000
+@@ -128,6 +128,7 @@ config MACH_BORZOI
+ config MACH_TOSA
+       bool "Enable Sharp SL-6000x (Tosa) Support"
+       depends on PXA_SHARPSL_25x
++      select TOSHIBA_TC6393XB
+ config PXA25x
+       bool
+Index: git/arch/arm/common/Makefile
+===================================================================
+--- git.orig/arch/arm/common/Makefile  2006-10-31 16:08:28.000000000 +0000
++++ git/arch/arm/common/Makefile       2006-11-07 22:13:09.000000000 +0000
+@@ -17,3 +17,4 @@ obj-$(CONFIG_SHARPSL_PM)     += sharpsl_pm.o
+ obj-$(CONFIG_SHARP_SCOOP)     += scoop.o
+ obj-$(CONFIG_ARCH_IXP2000)    += uengine.o
+ obj-$(CONFIG_ARCH_IXP23XX)    += uengine.o
++obj-$(CONFIG_TOSHIBA_TC6393XB)        += tc6393xb.o
+Index: git/include/asm-arm/hardware/tmio.h
+===================================================================
+--- git.orig/include/asm-arm/hardware/tmio.h   2006-11-07 22:13:09.000000000 +0000
++++ git/include/asm-arm/hardware/tmio.h        2006-11-07 22:13:09.000000000 +0000
+@@ -91,6 +91,50 @@ struct tmio_device {
+ /*--------------------------------------------------------------------------*/
++/*
++ * TC6393XB SoC
++ */
++#ifdef CONFIG_TOSHIBA_TC6393XB
++#define TMIO_SOC_TC6393XB
++#define TMIO_SOC_NAME                 "TC6393XB"
++#define TMIO_NAME_BUS                 "tc6393-bus"
++#define TMIO_NAME_CORE                        "tc6393-core"
++#define TMIO_NAME_NAND                        "tc6393-nand"
++#define TMIO_NAME_SD                  "tc6393-sd"
++#define TMIO_NAME_OHCI                        "tc6393-ohci"
++#define TMIO_NAME_SERIAL              "tc6393-serial"
++#define TMIO_NAME_LCD                 "tc6393-lcd"
++#define tmio_bus_type                 tc6393_bus_type
++
++#define TC6393_GPIO(x)                        (1 << (x))
++
++extern struct bus_type tc6393_bus_type;
++
++struct tc6393_platform_data {
++      u16     scr_pll2cr;             /* PLL2 Control                 */
++      u16     scr_ccr;                /* Clock Control                */
++      u16     scr_mcr;                /* Mode Control                 */
++      u16     scr_gper;               /* GP Enable                    */
++      u32     scr_gpo_doecr;          /* GPO Data OE Control          */
++      u32     scr_gpo_dsr;            /* GPO Data Set                 */
++
++      /* cells to register as devices */
++      struct tmio_cell*               cell;
++      unsigned int                    num_cells;
++
++      /* callbacks to enable and disable the TC6393XB's power and clock */
++      void (*enable)  (struct device *dev);
++      void (*disable) (struct device *dev);
++};
++
++u32   get_tc6393_gpio         (struct device *dev);
++u32   set_tc6393_gpio         (struct device *dev, u32 bits);
++u32   reset_tc6393_gpio       (struct device *dev, u32 bits);
++
++/*--------------------------------------------------------------------------*/
++
++#else
+ #error "no TMIO SoC configured"
++#endif
+ #endif
+Index: git/include/asm-arm/arch-pxa/irqs.h
+===================================================================
+--- git.orig/include/asm-arm/arch-pxa/irqs.h   2006-10-31 16:09:33.000000000 +0000
++++ git/include/asm-arm/arch-pxa/irqs.h        2006-11-07 22:13:09.000000000 +0000
+@@ -163,17 +163,27 @@
+ #define IRQ_LOCOMO_SPI_OVRN   (IRQ_BOARD_END + 20)
+ #define IRQ_LOCOMO_SPI_TEND   (IRQ_BOARD_END + 21)
++#define IRQ_TC6393_START      (IRQ_BOARD_END)
++#define IRQ_TC6393_NAND               (IRQ_BOARD_END + 0)
++#define IRQ_TC6393_SD         (IRQ_BOARD_END + 1)
++#define IRQ_TC6393_OHCI               (IRQ_BOARD_END + 2)
++#define IRQ_TC6393_SERIAL     (IRQ_BOARD_END + 3)
++#define IRQ_TC6393_LCD                (IRQ_BOARD_END + 4)
++
+ /*
+  * Figure out the MAX IRQ number.
+  *
+  * If we have an SA1111, the max IRQ is S1_BVD1_STSCHG+1.
+  * If we have an LoCoMo, the max IRQ is IRQ_LOCOMO_SPI_TEND+1
++ * If we have an TC6393XB, the max IRQ is IRQ_TC6393_LCD+1
+  * Otherwise, we have the standard IRQs only.
+  */
+ #ifdef CONFIG_SA1111
+ #define NR_IRQS                       (IRQ_S1_BVD1_STSCHG + 1)
+ #elif defined(CONFIG_SHARP_LOCOMO)
+ #define NR_IRQS                       (IRQ_LOCOMO_SPI_TEND + 1)
++#elif defined(CONFIG_TOSHIBA_TC6393XB)
++#define NR_IRQS                       (IRQ_TC6393_LCD + 1)
+ #elif defined(CONFIG_ARCH_LUBBOCK) || \
+       defined(CONFIG_MACH_LOGICPD_PXA270) || \
+       defined(CONFIG_MACH_MAINSTONE)
diff --git a/packages/kexecboot/linux-kexecboot-2.6.23/tosa-bluetooth-r8.patch b/packages/kexecboot/linux-kexecboot-2.6.23/tosa-bluetooth-r8.patch
new file mode 100644 (file)
index 0000000..7873cff
--- /dev/null
@@ -0,0 +1,194 @@
+Index: linux-2.6.17/arch/arm/mach-pxa/Makefile
+===================================================================
+--- linux-2.6.17.orig/arch/arm/mach-pxa/Makefile       2006-06-20 11:45:51.252467944 +0200
++++ linux-2.6.17/arch/arm/mach-pxa/Makefile    2006-06-20 11:46:33.619027248 +0200
+@@ -16,7 +16,7 @@
+ obj-$(CONFIG_PXA_SHARP_Cxx00) += spitz.o corgi_ssp.o corgi_lcd.o sharpsl_pm.o spitz_pm.o
+ obj-$(CONFIG_MACH_AKITA)      += akita-ioexp.o
+ obj-$(CONFIG_MACH_POODLE)     += poodle.o corgi_ssp.o sharpsl_pm.o poodle_pm.o
+-obj-$(CONFIG_MACH_TOSA)         += tosa.o sharpsl_pm.o tosa_pm.o tosa_lcd.o
++obj-$(CONFIG_MACH_TOSA)         += tosa.o sharpsl_pm.o tosa_pm.o tosa_lcd.o tosa_bt.o
+ obj-$(CONFIG_MACH_EM_X270) += em-x270.o
+ obj-$(CONFIG_MACH_HX2750)     += hx2750.o hx2750_test.o
+Index: linux-2.6.17/arch/arm/mach-pxa/tosa_bt.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.17/arch/arm/mach-pxa/tosa_bt.c   2006-06-20 11:46:08.107905528 +0200
+@@ -0,0 +1,128 @@
++/*
++ *  Bluetooth control code for Sharp SL-6000x (tosa)
++ *
++ *  Copyright (c) 2005                Dirk Opfer
++ *
++ *  This program is free software; you can 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/sched.h>
++#include <linux/slab.h>
++#include <linux/delay.h>
++#include <linux/platform_device.h>
++#include <asm/hardware.h>
++
++#include <asm/hardware/scoop.h>
++#include <asm/arch/tosa.h>
++#include <asm/arch/pxa-regs.h>
++
++
++static int tosa_bluetooth_power(int on)
++{
++      
++      if (!on) { //off
++
++              set_scoop_gpio(&tosascoop_device.dev,TOSA_SCOOP_BT_RESET);
++              pxa_gpio_mode(GPIO42_BTRXD|GPIO_IN);
++              pxa_gpio_mode(GPIO43_BTTXD|GPIO_IN);
++              pxa_gpio_mode(GPIO44_BTCTS|GPIO_IN);
++              pxa_gpio_mode(GPIO45_BTRTS|GPIO_IN);
++              mdelay(10); // wait 10ms
++              reset_scoop_gpio(&tosascoop_device.dev,TOSA_SCOOP_BT_RESET);
++              reset_scoop_gpio(&tosascoop_device.dev,TOSA_SCOOP_BT_PWR_EN);
++              reset_scoop_gpio(&tosascoop_jc_device.dev,TOSA_SCOOP_JC_BT_LED); // turn off BT LED
++
++      } else { // on
++              
++              reset_scoop_gpio(&tosascoop_device.dev,TOSA_SCOOP_BT_RESET);
++              set_scoop_gpio(&tosascoop_device.dev,TOSA_SCOOP_BT_PWR_EN);
++              pxa_gpio_mode(GPIO42_HWRXD_MD);
++              pxa_gpio_mode(GPIO43_HWTXD_MD);
++              pxa_gpio_mode(GPIO44_HWCTS_MD);
++              pxa_gpio_mode(GPIO45_HWRTS_MD);
++
++              set_scoop_gpio(&tosascoop_device.dev,TOSA_SCOOP_BT_RESET);
++              mdelay(20); // wait 20ms
++              reset_scoop_gpio(&tosascoop_device.dev,TOSA_SCOOP_BT_RESET);
++              set_scoop_gpio(&tosascoop_jc_device.dev,TOSA_SCOOP_JC_BT_LED); // turn BT LED on
++      }
++      return 0;
++}
++
++/*
++ *  Support Routines
++ */
++int __init tosa_bluetooth_probe(struct platform_device *dev)
++{
++      int ret = 0;
++      pxa_gpio_mode(GPIO42_BTRXD|GPIO_IN);
++      pxa_gpio_mode(GPIO43_BTTXD|GPIO_IN);
++      pxa_gpio_mode(GPIO44_BTCTS|GPIO_IN);
++      pxa_gpio_mode(GPIO45_BTRTS|GPIO_IN);
++      set_scoop_gpio(&tosascoop_device.dev,TOSA_SCOOP_BT_PWR_EN);
++      mdelay(5);
++
++      if ( (GPLR(GPIO42_BTRXD) & GPIO_bit(GPIO42_BTRXD))==0 &&
++           (GPLR(GPIO44_BTCTS) & GPIO_bit(GPIO44_BTCTS))==0) {
++              printk(KERN_INFO "No Bluetooth Device found!\n");
++              ret = ENODEV; // no bluetooth
++      } else {
++              printk(KERN_INFO "Tosa Bluetooth Device found on ttyS3!\n");
++      }
++      reset_scoop_gpio(&tosascoop_device.dev,TOSA_SCOOP_BT_PWR_EN);
++      
++      tosa_bluetooth_power(1);                // Power on
++      return ret;
++}
++
++static int tosa_bluetooth_remove(struct platform_device *dev)
++{
++      tosa_bluetooth_power(0);                // Power off
++      return 0;
++}
++
++#ifdef CONFIG_PM
++static int tosa_bluetooth_suspend(struct platform_device *dev, pm_message_t state)
++{
++      tosa_bluetooth_power(0);        // Power off
++      return 0;
++}
++
++static int tosa_bluetooth_resume(struct platform_device *dev)
++{
++      tosa_bluetooth_power(1);        // Power on
++      return 0;
++}
++#else
++#define tosa_bluetooth_suspend NULL
++#define tosa_bluetooth_resume NULL
++#endif
++
++static struct platform_driver tosa_bluetooth_driver = {
++      .probe          = tosa_bluetooth_probe,
++      .remove         = tosa_bluetooth_remove,
++      .suspend        = tosa_bluetooth_suspend,
++      .resume         = tosa_bluetooth_resume,
++        .driver         = {
++                          .name   = "tosa-bluetooth",
++      },
++};
++
++int __init tosa_bluetooth_init(void)
++{
++      return platform_driver_register(&tosa_bluetooth_driver);
++}
++
++void __exit tosa_bluetooth_cleanup(void)
++{
++      platform_driver_unregister(&tosa_bluetooth_driver);
++}
++
++module_init(tosa_bluetooth_init);
++module_exit(tosa_bluetooth_cleanup);
+Index: linux-2.6.17/arch/arm/mach-pxa/tosa.c
+===================================================================
+--- linux-2.6.17.orig/arch/arm/mach-pxa/tosa.c 2006-06-20 11:45:51.254467640 +0200
++++ linux-2.6.17/arch/arm/mach-pxa/tosa.c      2006-06-20 11:46:08.112904768 +0200
+@@ -288,7 +288,7 @@
+ static void tosa_tc6393_enable(struct device *dev)
+ {
+-
++      printk("!!tosa_tc6393_enable!!\n");
+       reset_scoop_gpio(&tosascoop_jc_device.dev,TOSA_SCOOP_JC_TC3693_L3V_ON);
+       reset_scoop_gpio(&tosascoop_jc_device.dev,TOSA_SCOOP_JC_TC6393_SUSPEND);
+       reset_scoop_gpio(&tosascoop_device.dev,TOSA_SCOOP_TC6393_REST_IN);      //#PCLR
+@@ -303,7 +303,7 @@
+ static void tosa_tc6393_disable(struct device *dev)
+ {
+-
++      printk("!!tosa_tc6393_disable!!\n");
+       reset_scoop_gpio(&tosascoop_jc_device.dev,TOSA_SCOOP_JC_TC3693_L3V_ON);
+       reset_scoop_gpio(&tosascoop_jc_device.dev,TOSA_SCOOP_JC_TC6393_SUSPEND);
+       reset_scoop_gpio(&tosascoop_device.dev,TOSA_SCOOP_TC6393_REST_IN);      //#PCLR
+@@ -428,6 +428,17 @@
+     },
+ };
++/*
++ * Tosa Blueooth
++ */
++static struct platform_device tosa_bluetooth_device = {
++      .name           = "tosa-bluetooth",
++      .id             = -1,
++      .dev            = {
++              .parent         = &tosascoop_jc_device.dev,
++      },
++};
++
+ static struct platform_device *devices[] __initdata = {
+       &tosascoop_device,
+       &tosascoop_jc_device,
+@@ -435,6 +446,7 @@
+       &tosaled_device,
+       &tc6393_device,
+       &tosalcd_device,
++      &tosa_bluetooth_device,
+ };
+ static void tosa_poweroff(void)
diff --git a/packages/kexecboot/linux-kexecboot-2.6.23/tosa-keyboard-r19.patch b/packages/kexecboot/linux-kexecboot-2.6.23/tosa-keyboard-r19.patch
new file mode 100644 (file)
index 0000000..948c27f
--- /dev/null
@@ -0,0 +1,514 @@
+ drivers/input/keyboard/Kconfig   |   12 -
+ drivers/input/keyboard/Makefile  |    1 
+ drivers/input/keyboard/tosakbd.c |  467 +++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 479 insertions(+), 1 deletion(-)
+
+Index: git/drivers/input/keyboard/Kconfig
+===================================================================
+--- git.orig/drivers/input/keyboard/Kconfig    2006-10-31 16:08:57.000000000 +0000
++++ git/drivers/input/keyboard/Kconfig 2006-11-07 22:13:10.000000000 +0000
+@@ -148,12 +148,22 @@ config KEYBOARD_SPITZ
+       depends on PXA_SHARPSL
+       default y
+       help
+-        Say Y here to enable the keyboard on the Sharp Zaurus SL-C1000,
++        Say Y here to enable the keyboard on the Sharp Zaurus SL-C1000,
+         SL-C3000 and Sl-C3100 series of PDAs.
+         To compile this driver as a module, choose M here: the
+         module will be called spitzkbd.
++config KEYBOARD_TOSA
++      tristate "Tosa keyboard"
++      depends on PXA_SHARPSL
++      default y
++      help
++        Say Y here to enable the keyboard on the Sharp Zaurus SL-6000x (Tosa)
++
++        To compile this driver as a module, choose M here: the
++        module will be called tosakbd.
++
+ config KEYBOARD_AMIGA
+       tristate "Amiga keyboard"
+       depends on AMIGA
+Index: git/drivers/input/keyboard/Makefile
+===================================================================
+--- git.orig/drivers/input/keyboard/Makefile   2006-10-31 16:08:57.000000000 +0000
++++ git/drivers/input/keyboard/Makefile        2006-11-07 22:13:10.000000000 +0000
+@@ -17,3 +17,4 @@ obj-$(CONFIG_KEYBOARD_SPITZ)         += spitzkb
+ obj-$(CONFIG_KEYBOARD_AAED2000)               += aaed2000_kbd.o
+ obj-$(CONFIG_KEYBOARD_GPIO)           += gpio_keys.o
+ obj-$(CONFIG_KEYBOARD_ASIC3)          += asic3_keys.o
++obj-$(CONFIG_KEYBOARD_TOSA)           += tosakbd.o
+Index: git/drivers/input/keyboard/tosakbd.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ git/drivers/input/keyboard/tosakbd.c       2006-11-07 23:27:19.000000000 +0000
+@@ -0,0 +1,467 @@
++/*
++ *  Keyboard driver for Sharp Tosa models (SL-6000x)
++ *
++ *  Copyright (c) 2005 Dirk Opfer
++ *
++ *  Based on xtkbd.c/locomkbd.c/corgikbd.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/delay.h>
++#include <linux/platform_device.h>
++#include <linux/init.h>
++#include <linux/input.h>
++#include <linux/interrupt.h>
++#include <linux/jiffies.h>
++#include <linux/module.h>
++#include <linux/slab.h>
++
++#include <asm/arch/tosa.h>
++#include <asm/arch/hardware.h>
++#include <asm/arch/pxa-regs.h>
++
++
++#define TOSA_KEY_STROBE_NUM   (11)
++#define TOSA_KEY_SENSE_NUM    (7)
++
++#define KEYMASK_ON            (0x1<<0)
++#define KEYMASK_REC           (0x1<<1)
++#define KEYMASK_SYNC          (0x1<<2)
++
++#define KB_ROWS                       7
++#define KB_COLS                       11
++#define KB_ROWMASK(r)         (1 << (r))
++#define SCANCODE(r,c)         ( ((r)<<4) + (c) + 1 )
++#define       NR_SCANCODES            (SCANCODE(KB_ROWS-1,KB_COLS)+1+1) 
++
++#define SCAN_INTERVAL         (HZ/10)
++#define HP_SCAN_INTERVAL      (150) /* ms */
++#define HP_STABLE_COUNT               2
++
++#define TOSA_KEY_CALENDER       KEY_F1
++#define TOSA_KEY_ADDRESS        KEY_F2
++#define TOSA_KEY_FN             KEY_F3
++#define TOSA_KEY_CANCEL               KEY_F4
++#define TOSA_KEY_OFF            KEY_SUSPEND
++#define TOSA_KEY_CENTER         KEY_F5
++#define TOSA_KEY_REC            KEY_F6
++#define TOSA_KEY_LIGHT          KEY_F7
++#define TOSA_KEY_RECORD         KEY_F8
++#define TOSA_KEY_HOME           KEY_F9
++#define TOSA_KEY_MAIL           KEY_F10
++#define TOSA_KEY_OK             KEY_F11
++#define TOSA_KEY_MENU           KEY_F12
++#define TOSA_KEY_SYNC           KEY_F13
++
++#define GET_ROWS_STATUS(c)    ((GPLR2 & TOSA_GPIO_ALL_SENSE_BIT) >> TOSA_GPIO_ALL_SENSE_RSHIFT)
++#define KB_DISCHARGE_DELAY    10
++#define KB_ACTIVATE_DELAY     10
++
++
++static unsigned char tosakbd_keycode[NR_SCANCODES] = {
++      0,                                                                                                                      /* 0 */
++      0, KEY_W, 0, 0, 0, KEY_K, KEY_BACKSPACE, KEY_P, 0, 0, 0, TOSA_KEY_OFF, 0, 0, 0, 0,                                      /*1 - 16*/
++      KEY_Q, KEY_E, KEY_T, KEY_Y, 0, KEY_O, KEY_I, KEY_COMMA, 0, 0, 0, TOSA_KEY_RECORD, 0, 0, 0, 0,                           /*17 - 32*/
++      KEY_A, KEY_D, KEY_G, KEY_U, 0, KEY_L, KEY_ENTER, KEY_DOT, 0, 0, 0, TOSA_KEY_SYNC, 0, 0, 0, 0,                           /*33 - 48*/
++      KEY_Z, KEY_C, KEY_V, KEY_J, TOSA_KEY_ADDRESS, TOSA_KEY_CANCEL, TOSA_KEY_CENTER, TOSA_KEY_OK, KEY_LEFTSHIFT, 0 , 0,0 , 0, 0, 0, 0,       /*49 - 64*/
++      KEY_S, KEY_R, KEY_B, KEY_N, TOSA_KEY_CALENDER, TOSA_KEY_HOME, TOSA_KEY_REC, TOSA_KEY_LIGHT, 0, KEY_RIGHTSHIFT, 0, 0, 0, 0, 0, 0,        /*65 - 80*/
++      KEY_TAB, KEY_SLASH, KEY_H, KEY_M, TOSA_KEY_MENU, 0, KEY_UP, 0, 0, 0, TOSA_KEY_FN, 0, 0, 0, 0, 0,                        /*81 - 96*/
++      KEY_X, KEY_F, KEY_SPACE, KEY_APOSTROPHE, TOSA_KEY_MAIL, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0, 0, 0,                   /*97 - 109*/
++};
++
++struct tosakbd {
++      unsigned char keycode[ARRAY_SIZE(tosakbd_keycode)];
++      struct input_dev *input;
++
++      spinlock_t lock;
++      struct timer_list timer;
++      struct timer_list hptimer;
++
++      int hp_state;
++      int hp_count;
++
++      unsigned int suspended;
++      unsigned long suspend_jiffies;
++};
++
++/* Helper functions for reading the keyboard matrix 
++ * Note: We should really be using pxa_gpio_mode to alter GPDR but it 
++ *       requires a function call per GPIO bit which is excessive
++ *       when we need to access 12 bits at once, multiple times.
++ * These functions must be called within local_irq_save()/local_irq_restore()
++ * or similar. 
++ */
++static inline void tosakbd_discharge_all(void)
++{
++      /* STROBE All HiZ */
++      GPCR1  = TOSA_GPIO_HIGH_STROBE_BIT;
++      GPDR1 &= ~TOSA_GPIO_HIGH_STROBE_BIT;
++      GPCR2  = TOSA_GPIO_LOW_STROBE_BIT;
++      GPDR2 &= ~TOSA_GPIO_LOW_STROBE_BIT;
++}
++
++static inline void tosakbd_activate_all(void)
++{
++      /* STROBE ALL -> High */
++      GPSR1  = TOSA_GPIO_HIGH_STROBE_BIT;
++      GPDR1 |= TOSA_GPIO_HIGH_STROBE_BIT;
++      GPSR2  = TOSA_GPIO_LOW_STROBE_BIT;
++      GPDR2 |= TOSA_GPIO_LOW_STROBE_BIT;
++
++      udelay(KB_DISCHARGE_DELAY);
++
++      /* STATE CLEAR */
++      GEDR2 |= TOSA_GPIO_ALL_SENSE_BIT; 
++}
++
++static inline void tosakbd_activate_col(int col)
++{
++      if (col<=5) {
++              /* STROBE col -> High, not col -> HiZ */
++              GPSR1 = TOSA_GPIO_STROBE_BIT(col);
++              GPDR1 = (GPDR1 & ~TOSA_GPIO_HIGH_STROBE_BIT) | TOSA_GPIO_STROBE_BIT(col);
++      } else {
++              /* STROBE col -> High, not col -> HiZ */
++              GPSR2 = TOSA_GPIO_STROBE_BIT(col);
++              GPDR2 = (GPDR2 & ~TOSA_GPIO_LOW_STROBE_BIT) | TOSA_GPIO_STROBE_BIT(col);
++      } 
++}
++
++static inline void tosakbd_reset_col(int col)
++{
++      if (col<=5) {
++              /* STROBE col -> Low */
++              GPCR1 = TOSA_GPIO_STROBE_BIT(col);
++              /* STROBE col -> out, not col -> HiZ */
++              GPDR1 = (GPDR1 & ~TOSA_GPIO_HIGH_STROBE_BIT) | TOSA_GPIO_STROBE_BIT(col);
++      } else {
++              /* STROBE col -> Low */
++              GPCR2 = TOSA_GPIO_STROBE_BIT(col);
++              /* STROBE col -> out, not col -> HiZ */
++              GPDR2 = (GPDR2 & ~TOSA_GPIO_LOW_STROBE_BIT) | TOSA_GPIO_STROBE_BIT(col);
++      } 
++}
++
++/*
++ * Read the GPIOs for POWER, RECORD and SYNC
++ */
++static int read_port_key_status_raw(void)
++{
++      int val=0;
++
++      /* Power key */
++      if ((GPLR0 & GPIO_bit(TOSA_GPIO_ON_KEY))==0)
++              val |= KEYMASK_ON;
++      /* Record key */
++      if ((GPLR0 & GPIO_bit(TOSA_GPIO_RECORD_BTN))==0)
++              val |= KEYMASK_REC;
++      /* Sync key */
++      if ((GPLR0 & GPIO_bit(TOSA_GPIO_SYNC))==0)
++              val |= KEYMASK_SYNC;
++      return val;
++}
++
++
++/*
++ * The tosa keyboard only generates interrupts when a key is pressed.
++ * So when a key is pressed, we enable a timer.  This timer scans the
++ * keyboard, and this is how we detect when the key is released.
++ */
++
++/* Scan the hardware keyboard and push any changes up through the input layer */
++static void tosakbd_scankeyboard(struct tosakbd *tosakbd_data) 
++{
++      unsigned int row, col, rowd;
++      unsigned long flags;
++      unsigned int num_pressed = 0;
++
++      if (tosakbd_data->suspended)
++              return;
++
++      spin_lock_irqsave(&tosakbd_data->lock, flags);
++
++      for (col = 0; col < KB_COLS; col++) {
++              /*
++               * Discharge the output driver capacitatance
++               * in the keyboard matrix. (Yes it is significant..)
++               */
++              tosakbd_discharge_all();
++              udelay(KB_DISCHARGE_DELAY);
++
++              tosakbd_activate_col( col);
++              udelay(KB_ACTIVATE_DELAY);
++              
++              rowd = GET_ROWS_STATUS(col);
++
++              for (row = 0; row < KB_ROWS; row++) {
++                      unsigned int scancode, pressed;
++                      scancode = SCANCODE(row, col);
++                      pressed = rowd & KB_ROWMASK(row);
++                      input_report_key(tosakbd_data->input, tosakbd_data->keycode[scancode], pressed);
++                      if (pressed)
++                              num_pressed++;
++              }
++
++              tosakbd_reset_col(col);
++      }
++
++      tosakbd_activate_all();
++
++      rowd = read_port_key_status_raw();
++
++      for (row = 0; row < 3; row++ ) {
++              unsigned int scancode, pressed;
++              scancode = SCANCODE(row, KB_COLS);
++              pressed = rowd & KB_ROWMASK(row);
++              input_report_key(tosakbd_data->input, tosakbd_data->keycode[scancode], pressed);
++              if (pressed)
++                      num_pressed++;
++
++              if (pressed && (tosakbd_data->keycode[scancode] == TOSA_KEY_OFF)
++                                                              && time_after(jiffies, tosakbd_data->suspend_jiffies + msecs_to_jiffies(1000))) {
++                      input_event(tosakbd_data->input, EV_PWR, TOSA_KEY_OFF, 1);
++                      tosakbd_data->suspend_jiffies = jiffies;
++              }
++      }
++      
++      input_sync(tosakbd_data->input);
++
++      /* if any keys are pressed, enable the timer */
++      if (num_pressed)
++              mod_timer(&tosakbd_data->timer, jiffies + SCAN_INTERVAL);
++
++      spin_unlock_irqrestore(&tosakbd_data->lock, flags);
++}
++
++/* 
++ * tosa keyboard interrupt handler.
++ */
++static irqreturn_t tosakbd_interrupt(int irq, void *dev_id)
++{
++      struct tosakbd *tosakbd_data = dev_id;
++
++      if (!timer_pending(&tosakbd_data->timer)) 
++      {
++              /** wait chattering delay **/
++              udelay(20);
++              tosakbd_scankeyboard(tosakbd_data);
++      }
++
++      return IRQ_HANDLED;
++}
++
++/*
++ * tosa timer checking for released keys
++ */
++static void tosakbd_timer_callback(unsigned long data)
++{
++      struct tosakbd *tosakbd_data = (struct tosakbd *) data;
++      tosakbd_scankeyboard(tosakbd_data);
++}
++
++/*
++ * The headphone generates an interrupt.
++ * We debounce the switche and pass them to the input system.
++ */
++
++static irqreturn_t tosakbd_hp_isr(int irq, void *dev_id)
++{
++      struct tosakbd *tosakbd_data = dev_id;
++
++      if (!timer_pending(&tosakbd_data->hptimer))
++              mod_timer(&tosakbd_data->hptimer, jiffies + msecs_to_jiffies(HP_SCAN_INTERVAL));
++
++      return IRQ_HANDLED;
++}
++
++static void tosakbd_hp_timer(unsigned long data)
++{
++      struct tosakbd *tosakbd_data = (struct tosakbd *) data;
++      unsigned long state;
++      unsigned long flags;
++
++      state = (GPLR(TOSA_GPIO_EAR_IN) & GPIO_bit(TOSA_GPIO_EAR_IN));
++      if (state != tosakbd_data->hp_state) {
++              tosakbd_data->hp_count = 0;
++              tosakbd_data->hp_state = state;
++      } else if (tosakbd_data->hp_count < HP_STABLE_COUNT) {
++              tosakbd_data->hp_count++;
++      }
++
++      if (tosakbd_data->hp_count >= HP_STABLE_COUNT) {
++              spin_lock_irqsave(&tosakbd_data->lock, flags);
++
++              input_report_switch(tosakbd_data->input, SW_HEADPHONE_INSERT, ((GPLR(TOSA_GPIO_EAR_IN) & GPIO_bit(TOSA_GPIO_EAR_IN)) == 0));
++              input_sync(tosakbd_data->input);
++
++              spin_unlock_irqrestore(&tosakbd_data->lock, flags);
++      } else {
++              mod_timer(&tosakbd_data->hptimer, jiffies + msecs_to_jiffies(HP_SCAN_INTERVAL));
++      }
++}
++
++#ifdef CONFIG_PM
++static int tosakbd_suspend(struct platform_device *dev, pm_message_t state)
++{
++      struct tosakbd *tosakbd = platform_get_drvdata(dev);
++
++      tosakbd->suspended = 1;
++
++      return 0;
++}
++
++static int tosakbd_resume(struct platform_device *dev)
++{
++      struct tosakbd *tosakbd = platform_get_drvdata(dev);
++
++      /* Upon resume, ignore the suspend key for a short while */
++      tosakbd->suspend_jiffies = jiffies;
++      tosakbd->suspended = 0;
++
++      return 0;
++}
++#else
++#define tosakbd_suspend               NULL
++#define tosakbd_resume                NULL
++#endif
++
++static int __init tosakbd_probe(struct platform_device *pdev) {
++
++      int i;
++      struct tosakbd *tosakbd;
++      struct input_dev *input_dev;
++
++      tosakbd = kzalloc(sizeof(struct tosakbd), GFP_KERNEL);
++      if (!tosakbd)
++              return -ENOMEM;
++
++      input_dev = input_allocate_device();
++      if (!input_dev) {
++              kfree(tosakbd);
++              return -ENOMEM;
++      }
++
++      platform_set_drvdata(pdev,tosakbd);
++
++      spin_lock_init(&tosakbd->lock);
++
++      /* Init Keyboard rescan timer */
++      init_timer(&tosakbd->timer);
++      tosakbd->timer.function = tosakbd_timer_callback;
++      tosakbd->timer.data = (unsigned long) tosakbd;
++
++      /* Init Headphone Timer */
++      init_timer(&tosakbd->hptimer);
++      tosakbd->hptimer.function = tosakbd_hp_timer;
++      tosakbd->hptimer.data = (unsigned long) tosakbd;
++
++      tosakbd->suspend_jiffies = jiffies;
++
++      tosakbd->input = input_dev;
++
++      input_dev->private = tosakbd;
++      input_dev->name = "Tosa Keyboard";
++      input_dev->phys = "tosakbd/input0";
++      input_dev->cdev.dev = &pdev->dev;
++
++      input_dev->id.bustype = BUS_HOST;
++      input_dev->id.vendor = 0x0001;
++      input_dev->id.product = 0x0001;
++      input_dev->id.version = 0x0100;
++
++      input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_PWR) | BIT(EV_SW);
++      input_dev->keycode = tosakbd->keycode;
++      input_dev->keycodesize = sizeof(unsigned char);
++      input_dev->keycodemax = ARRAY_SIZE(tosakbd_keycode);
++
++      memcpy(tosakbd->keycode, tosakbd_keycode, sizeof(tosakbd->keycode));
++      for (i = 0; i < ARRAY_SIZE(tosakbd_keycode); i++)
++              set_bit(tosakbd->keycode[i], input_dev->keybit);
++      clear_bit(0, input_dev->keybit);
++      set_bit(SW_HEADPHONE_INSERT, input_dev->swbit);
++
++      input_register_device(tosakbd->input);
++
++      /* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */
++      for (i = 0; i < TOSA_KEY_SENSE_NUM; i++) {
++              pxa_gpio_mode( TOSA_GPIO_KEY_SENSE(i) | GPIO_IN);       
++              if (request_irq(TOSA_IRQ_GPIO_KEY_SENSE(i), tosakbd_interrupt,
++                                              IRQF_DISABLED | IRQF_TRIGGER_RISING, "tosakbd", tosakbd)) {
++                      printk("tosakbd: Can't get IRQ: %d !\n", i);
++              }
++      }
++      
++      /* Set Strobe lines as outputs - set high */
++      for (i = 0; i < TOSA_KEY_STROBE_NUM; i++) {
++              pxa_gpio_mode( TOSA_GPIO_KEY_STROBE(i) | GPIO_OUT | GPIO_DFLT_HIGH);    
++      }
++
++      // Power&Rec Button
++      pxa_gpio_mode( TOSA_GPIO_ON_KEY | GPIO_IN);     
++      pxa_gpio_mode( TOSA_GPIO_RECORD_BTN | GPIO_IN); 
++      pxa_gpio_mode( TOSA_GPIO_SYNC | GPIO_IN);
++      pxa_gpio_mode( TOSA_GPIO_EAR_IN | GPIO_IN);
++
++      if (request_irq(TOSA_IRQ_GPIO_ON_KEY, tosakbd_interrupt, IRQF_DISABLED | IRQF_TRIGGER_FALLING, "On key", tosakbd) ||
++          request_irq(TOSA_IRQ_GPIO_RECORD_BTN, tosakbd_interrupt, IRQF_DISABLED | IRQF_TRIGGER_FALLING, "Record key", tosakbd) ||
++          request_irq(TOSA_IRQ_GPIO_SYNC, tosakbd_interrupt, IRQF_DISABLED | IRQF_TRIGGER_FALLING, "Sync key", tosakbd) ||
++          request_irq(TOSA_IRQ_GPIO_EAR_IN, tosakbd_hp_isr, IRQF_DISABLED | IRQF_TRIGGER_FALLING, "HP in", tosakbd)) {
++              printk("Could not allocate KEYBD IRQ!\n");
++      }
++
++      printk(KERN_INFO "input: Tosa Keyboard Registered\n");
++
++      return 0;
++}
++
++static int tosakbd_remove(struct platform_device *dev) {
++      
++      int i;
++      struct tosakbd *tosakbd = platform_get_drvdata(dev);
++      
++      for (i = 0; i < TOSA_KEY_SENSE_NUM; i++)
++              free_irq(TOSA_IRQ_GPIO_KEY_SENSE(i),tosakbd); 
++      
++      free_irq(TOSA_IRQ_GPIO_ON_KEY,tosakbd); 
++      free_irq(TOSA_IRQ_GPIO_RECORD_BTN,tosakbd); 
++      free_irq(TOSA_IRQ_GPIO_SYNC,tosakbd); 
++
++      del_timer_sync(&tosakbd->timer);
++
++      input_unregister_device(tosakbd->input);
++      
++      kfree(tosakbd);
++      
++      return 0;
++}
++
++static struct platform_driver tosakbd_driver = {
++      .probe          = tosakbd_probe,
++      .remove         = tosakbd_remove,
++      .suspend        = tosakbd_suspend,
++      .resume         = tosakbd_resume,
++      .driver         = {
++              .name   = "tosa-keyboard",
++      },
++};
++
++static int __devinit tosakbd_init(void)
++{
++      return platform_driver_register(&tosakbd_driver);
++}
++
++static void __exit tosakbd_exit(void)
++{
++      platform_driver_unregister(&tosakbd_driver);
++}
++
++module_init(tosakbd_init);
++module_exit(tosakbd_exit);
++
++MODULE_AUTHOR("Dirk Opfer <Dirk@Opfer-Online.de>");
++MODULE_DESCRIPTION("Tosa Keyboard Driver");
++MODULE_LICENSE("GPLv2");
diff --git a/packages/kexecboot/linux-kexecboot-2.6.23/tosa-lcdnoise-r1-fix-r0.patch b/packages/kexecboot/linux-kexecboot-2.6.23/tosa-lcdnoise-r1-fix-r0.patch
new file mode 100644 (file)
index 0000000..93a9c18
--- /dev/null
@@ -0,0 +1,135 @@
+From eada869814636157956641ba1503f0d6cc04e2b7 Mon Sep 17 00:00:00 2001
+From: Dmitry Baryshkov <dbaryshkov@gmail.com>
+Date: Fri, 19 Oct 2007 17:43:51 +0400
+Subject: [PATCH] tosa-lcdnoise-r1.patch fixes
+
+---
+ arch/arm/mach-pxa/tosa_lcd.c        |   34 ++++++++++++++++++++++++++++++++++
+ drivers/input/touchscreen/tosa_ts.c |    9 +--------
+ include/asm-arm/arch-pxa/tosa.h     |    5 +++++
+ 3 files changed, 40 insertions(+), 8 deletions(-)
+
+diff --git a/arch/arm/mach-pxa/tosa_lcd.c b/arch/arm/mach-pxa/tosa_lcd.c
+index d52f63f..447ca86 100644
+--- a/arch/arm/mach-pxa/tosa_lcd.c
++++ b/arch/arm/mach-pxa/tosa_lcd.c
+@@ -59,6 +59,8 @@ static int bl_intensity;
+ static struct ssp_dev tosa_nssp_dev;
+ static struct ssp_state tosa_nssp_state;
+ static spinlock_t tosa_nssp_lock;
++static int blanked;
++static unsigned long hsync_time;
+ static unsigned short normal_i2c[] = {
+       DAC_BASE,
+@@ -130,6 +132,17 @@ static void tosa_lcd_tg_init(struct device *dev)
+       pxa_nssp_output(TG_GPOSR,0x02);         /* GPOS0=powercontrol, GPOS1=GPIO, GPOS2=TCTL */
+ }
++static unsigned long calc_hsync_time(const struct fb_videomode *mode) {
++    /* The 25 and 44 'magic numbers' are from Sharp's 2.4 patches */
++    if (mode->yres == 640) {
++        return 25;
++    }
++    if (mode->yres == 320) {
++        return 44;
++    }
++    return 0;
++}
++
+ static void tosa_lcd_tg_on(struct device *dev, const struct fb_videomode *mode)
+ {
+       const int value = TG_REG0_COLOR | TG_REG0_UD | TG_REG0_LR;
+@@ -154,6 +167,8 @@ static void tosa_lcd_tg_on(struct device *dev, const struct fb_videomode *mode)
+               /* set common voltage */
+               i2c_smbus_write_byte_data(tosa_i2c_dac, DAC_CH1, comadj);
++    blanked = 0;
++    hsync_time = calc_hsync_time(mode);
+ }
+ static void tosa_lcd_tg_off(struct device *dev)
+@@ -172,6 +187,8 @@ static void tosa_lcd_tg_off(struct device *dev)
+       
+       /* L3V Off */
+       reset_scoop_gpio( &tosascoop_jc_device.dev,TOSA_SCOOP_JC_TC3693_L3V_ON); 
++
++    blanked = 1;
+ }
+ static int tosa_detect_client(struct i2c_adapter* adapter, int address, int kind) {
+@@ -238,6 +255,23 @@ static int tosa_detach_client(struct i2c_client* client) {
+       return 0;
+ }
++unsigned long tosa_lcd_get_hsync_time(void)
++{
++/* This method should eventually contain the correct algorithm for calculating
++   the hsync_time */
++    if (blanked)
++        return 0;
++    else
++        return hsync_time;
++}
++
++void tosa_lcd_wait_hsync(void)
++{
++    /* Waits for a rising edge on the VGA line */
++    while((GPLR(TOSA_GPIO_VGA_LINE) & GPIO_bit(TOSA_GPIO_VGA_LINE)) == 0);
++    while((GPLR(TOSA_GPIO_VGA_LINE) & GPIO_bit(TOSA_GPIO_VGA_LINE)) != 0);
++}
++
+ static struct i2c_driver tosa_driver={
+       .id             = TOSA_LCD_I2C_DEVICEID,
+       .attach_adapter = tosa_attach_adapter,
+diff --git a/drivers/input/touchscreen/tosa_ts.c b/drivers/input/touchscreen/tosa_ts.c
+index bc733e9..134f8ce 100644
+--- a/drivers/input/touchscreen/tosa_ts.c
++++ b/drivers/input/touchscreen/tosa_ts.c
+@@ -25,13 +25,6 @@
+ #define CCNT_ON()   asm("mcr p14, 0, %0, C0, C0, 0" : : "r"(1))
+ #define CCNT_OFF()  asm("mcr p14, 0, %0, C0, C0, 0" : : "r"(1))
+-static inline void tosa_lcd_wait_hsync(void)
+-{
+-      /* Waits for a rising edge on the VGA line */
+-      while((GPLR(TOSA_GPIO_VGA_LINE) & GPIO_bit(TOSA_GPIO_VGA_LINE)) == 0);
+-      while((GPLR(TOSA_GPIO_VGA_LINE) & GPIO_bit(TOSA_GPIO_VGA_LINE)) != 0);
+-}
+-
+ /* On the Sharp SL-6000 (Tosa), due to a noisy LCD, we need to perform a wait
+  * before sampling the Y axis of the touchscreen */
+ void tosa_lcd_sync_on(int adcsel) {
+@@ -54,7 +47,7 @@ void tosa_lcd_sync_on(int adcsel) {
+       }
+ }
+-void tosa_lcd_sync_off(void) {
++void tosa_lcd_sync_off(int adcsel) {
+       CCNT_OFF();
+ }
+diff --git a/include/asm-arm/arch-pxa/tosa.h b/include/asm-arm/arch-pxa/tosa.h
+index ce7322d..7f446fd 100644
+--- a/include/asm-arm/arch-pxa/tosa.h
++++ b/include/asm-arm/arch-pxa/tosa.h
+@@ -1,6 +1,7 @@
+ /*
+  * Hardware specific definitions for Sharp SL-C6000x series of PDAs
+  *
++ * Copyright (c) 2006 Wolfson Microelectronics PLC.
+  * Copyright (c) 2005 Dirk Opfer
+  *
+  * Based on Sharp's 2.4 kernel patches
+@@ -187,4 +188,8 @@
+ extern struct platform_device tosascoop_jc_device;
+ extern struct platform_device tosascoop_device;
+ extern struct platform_device tc6393_device;
++
++unsigned long tosa_lcd_get_hsync_time(void);
++void tosa_lcd_wait_hsync(void);
++
+ #endif /* _ASM_ARCH_TOSA_H_ */
+-- 
+1.4.4.4
+
diff --git a/packages/kexecboot/linux-kexecboot-2.6.23/tosa-lcdnoise-r1.patch b/packages/kexecboot/linux-kexecboot-2.6.23/tosa-lcdnoise-r1.patch
new file mode 100644 (file)
index 0000000..21f3cf6
--- /dev/null
@@ -0,0 +1,158 @@
+From 564b757ba44b517ac6d693b94a177708bb5d3887 Mon Sep 17 00:00:00 2001
+From: Dmitry Baryshkov <dbaryshkov@gmail.com>
+Date: Fri, 19 Oct 2007 17:30:30 +0400
+Subject: [PATCH] tosa-lcdnoise-r1.patch
+
+---
+ drivers/input/touchscreen/Kconfig   |   13 +++++
+ drivers/input/touchscreen/Makefile  |    1 +
+ drivers/input/touchscreen/tosa_ts.c |  102 +++++++++++++++++++++++++++++++++++
+ 3 files changed, 116 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
+index 3ac01b4..6862e8f 100644
+--- a/drivers/input/touchscreen/Kconfig
++++ b/drivers/input/touchscreen/Kconfig
+@@ -219,6 +219,19 @@ config TOUCHSCREEN_USB_DMC_TSC10
+       bool "DMC TSC-10/25 device support" if EMBEDDED
+       depends on TOUCHSCREEN_USB_COMPOSITE
++config TOUCHSCREEN_TOSA
++    tristate "Sharp Tosa touchscreen driver"
++    depends on TOUCHSCREEN_WM97XX && MACH_TOSA
++    default n
++    help
++      Say Y here to enable the driver for the touchscreen on the
++      Sharp Tosa PDA.
++      depends on TOUCHSCREEN_WM97XX && MACH_TOSA
++      If unsure, say N.
++
++      To compile this driver as a module, choose M here: the
++      module will be called tosa_ts.
++
+ config TOUCHSCREEN_TSC2101
+       tristate "TI TSC2101 touchscreen input driver"
+       depends on MACH_HX2750 && INPUT && INPUT_TOUCHSCREEN
+diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
+index f64d1a5..4fc0e17 100644
+--- a/drivers/input/touchscreen/Makefile
++++ b/drivers/input/touchscreen/Makefile
+@@ -22,6 +22,7 @@ obj-$(CONFIG_TOUCHSCREEN_UCB1400)    += ucb1400_ts.o
+ obj-$(CONFIG_TOUCHSCREEN_TSC2101)     += tsc2101_ts.o
+ obj-$(CONFIG_TOUCHSCREEN_WM97XX)      += wm97xx-ts.o
+ obj-$(CONFIG_TOUCHSCREEN_WM97XX_PXA)    += pxa-wm97xx.o
++obj-$(CONFIG_TOUCHSCREEN_TOSA)                += tosa_ts.o
+ ifeq ($(CONFIG_TOUCHSCREEN_WM9713),y)
+ wm97xx-ts-objs += wm9713.o
+diff --git a/drivers/input/touchscreen/tosa_ts.c b/drivers/input/touchscreen/tosa_ts.c
+new file mode 100644
+index 0000000..bc733e9
+--- /dev/null
++++ b/drivers/input/touchscreen/tosa_ts.c
+@@ -0,0 +1,102 @@
++/*
++ * tosa_ts.c  --  Touchscreen driver for Sharp SL-6000 (Tosa).
++ *
++ * Copyright 2006 Wolfson Microelectronics PLC.
++ * Author: Mike Arthur
++ *         linux@wolfsonmicro.com
++ *
++ *  This program is free software; you can redistribute  it and/or modify it
++ *  under  the terms of  the GNU General  Public License as published by the
++ *  Free Software Foundation;  either version 2 of the  License, or (at your
++ *  option) any later version.
++ *
++ *  Revision history
++ *     1st Sep 2006  Initial version.
++ *
++ */
++
++#include <linux/wm97xx.h>
++#include <asm/arch/tosa.h>
++#include <asm/arch/hardware.h>
++#include <asm/arch/pxa-regs.h>
++
++/* Taken from the Sharp 2.4 kernel code */
++#define CCNT(a)     asm volatile ("mrc p14, 0, %0, C1, C1, 0" : "=r"(a))
++#define CCNT_ON()   asm("mcr p14, 0, %0, C0, C0, 0" : : "r"(1))
++#define CCNT_OFF()  asm("mcr p14, 0, %0, C0, C0, 0" : : "r"(1))
++
++static inline void tosa_lcd_wait_hsync(void)
++{
++      /* Waits for a rising edge on the VGA line */
++      while((GPLR(TOSA_GPIO_VGA_LINE) & GPIO_bit(TOSA_GPIO_VGA_LINE)) == 0);
++      while((GPLR(TOSA_GPIO_VGA_LINE) & GPIO_bit(TOSA_GPIO_VGA_LINE)) != 0);
++}
++
++/* On the Sharp SL-6000 (Tosa), due to a noisy LCD, we need to perform a wait
++ * before sampling the Y axis of the touchscreen */
++void tosa_lcd_sync_on(int adcsel) {
++      unsigned long timer1 = 0, timer2 = 0, wait_time = 0;
++      if (adcsel == WM97XX_ADCSEL_Y) {
++              wait_time = tosa_lcd_get_hsync_time();
++              CCNT_ON();
++
++              if (wait_time) {
++                      /* wait for LCD rising edge */
++                      tosa_lcd_wait_hsync();
++                      /* get clock */
++                      CCNT(timer1);
++                      CCNT(timer2);
++
++                      while ((timer2 - timer1) < wait_time) {
++                              CCNT(timer2);
++                      }
++              }
++      }
++}
++
++void tosa_lcd_sync_off(void) {
++      CCNT_OFF();
++}
++
++static struct wm97xx_mach_ops tosa_mach_ops = {
++      .pre_sample =  tosa_lcd_sync_on,
++      .post_sample = tosa_lcd_sync_off,
++};
++
++int tosa_ts_probe(struct device *dev) {
++      struct wm97xx *wm = dev->driver_data;
++      return wm97xx_register_mach_ops (wm, &tosa_mach_ops);
++}
++
++
++int tosa_ts_remove(struct device *dev) {
++      struct wm97xx *wm = dev->driver_data;
++      wm97xx_unregister_mach_ops (wm);
++      return 0;
++}
++
++static struct device_driver tosa_ts_driver = {
++      .name = "wm97xx-touchscreen",
++      .bus = &wm97xx_bus_type,
++      .owner = THIS_MODULE,
++      .probe = tosa_ts_probe,
++      .remove = tosa_ts_remove,
++};
++
++static int __init tosa_ts_init(void)
++{
++      return driver_register(&tosa_ts_driver);
++}
++
++static void __exit tosa_ts_exit(void)
++{
++      driver_unregister(&tosa_ts_driver);
++}
++
++module_init(tosa_ts_init);
++module_exit(tosa_ts_exit);
++
++/* Module information */
++MODULE_AUTHOR("Mike Arthur, mike@mikearthur.co.uk, www.wolfsonmicro.com");
++MODULE_DESCRIPTION("Sharp SL6000 Tosa Touch Screen Driver");
++MODULE_LICENSE("GPL");
+-- 
+1.4.4.4
+
diff --git a/packages/kexecboot/linux-kexecboot-2.6.23/tosa-power-r18-fix-r0.patch b/packages/kexecboot/linux-kexecboot-2.6.23/tosa-power-r18-fix-r0.patch
new file mode 100644 (file)
index 0000000..8899ae2
--- /dev/null
@@ -0,0 +1,59 @@
+From 24813da9b0aac0e92635d7307837d89a9f4a1ee7 Mon Sep 17 00:00:00 2001
+From: Dmitry Baryshkov <dbaryshkov@gmail.com>
+Date: Fri, 19 Oct 2007 16:47:15 +0400
+Subject: [PATCH] tosa-power-r18.patch fixes
+
+---
+ arch/arm/mach-pxa/tosa_pm.c |    9 +++++----
+ 1 files changed, 5 insertions(+), 4 deletions(-)
+
+diff --git a/arch/arm/mach-pxa/tosa_pm.c b/arch/arm/mach-pxa/tosa_pm.c
+index 1eab1af..2df75f0 100644
+--- a/arch/arm/mach-pxa/tosa_pm.c
++++ b/arch/arm/mach-pxa/tosa_pm.c
+@@ -17,9 +17,9 @@
+ #include <linux/interrupt.h>
+ #include <linux/platform_device.h>
+ #include <linux/pm.h>
++#include <linux/apm-emulation.h>
+ #include <linux/wm97xx.h>
+-#include <asm/apm.h>
+ #include <asm/irq.h>
+ #include <asm/mach-types.h>
+ #include <asm/hardware.h>
+@@ -144,7 +144,7 @@ static int tosa_ac97_init(void)
+       pxa_gpio_mode(GPIO29_SDATA_IN_AC97_MD);
+       pxa_gpio_mode(GPIO20_DREQ0_MD);
+       
+-      pxa_set_cken(CKEN2_AC97, 1);
++      pxa_set_cken(CKEN_AC97, 1);
+       /* AC97 power on sequense */
+       while ( 1 ) {
+               GCR = 0;
+@@ -184,11 +184,12 @@ static int tosa_ac97_init(void)
+       pxa_gpio_mode(GPIO32_SDATA_IN1_AC97_MD);
+       ad_polling = 1;
+       printk("tosa_ac97_init\n");
++      return 0;
+ }
+ void tosa_ac97_exit(void)
+ {
+-      if (!(CKEN & CKEN2_AC97))
++      if (!(CKEN & CKEN_AC97))
+               return;
+       
+       // power down the whole chip
+@@ -197,7 +198,7 @@ void tosa_ac97_exit(void)
+ //       GCR &= ~(GCR_CDONE_IE | GCR_SDONE_IE | GCR_SECRDY_IEN | GCR_PRIRDY_IEN | GCR_SECRES_IEN | GCR_PRIRES_IEN);
+ //        GSR = GSR;
+ //    GCR = GCR_ACLINK_OFF;
+-      pxa_set_cken(CKEN2_AC97, 0);
++      pxa_set_cken(CKEN_AC97, 0);
+       /* switch back to irq driver */
+       ad_polling = 0;
+       printk("tosa_ac97_exit\n");
+-- 
+1.4.4.4
+
diff --git a/packages/kexecboot/linux-kexecboot-2.6.23/tosa-power-r18.patch b/packages/kexecboot/linux-kexecboot-2.6.23/tosa-power-r18.patch
new file mode 100644 (file)
index 0000000..ca703cb
--- /dev/null
@@ -0,0 +1,691 @@
+Index: linux-2.6.17/arch/arm/mach-pxa/Makefile
+===================================================================
+--- linux-2.6.17.orig/arch/arm/mach-pxa/Makefile       2006-09-19 20:51:33.984424500 +0200
++++ linux-2.6.17/arch/arm/mach-pxa/Makefile    2006-09-19 21:08:04.922354250 +0200
+@@ -16,7 +16,7 @@ obj-$(CONFIG_PXA_SHARP_C7xx) += corgi.o 
+ obj-$(CONFIG_PXA_SHARP_Cxx00) += spitz.o corgi_ssp.o corgi_lcd.o sharpsl_pm.o spitz_pm.o
+ obj-$(CONFIG_MACH_AKITA)      += akita-ioexp.o
+ obj-$(CONFIG_MACH_POODLE)     += poodle.o corgi_ssp.o sharpsl_pm.o poodle_pm.o
+-obj-$(CONFIG_MACH_TOSA)         += tosa.o
++obj-$(CONFIG_MACH_TOSA)         += tosa.o sharpsl_pm.o tosa_pm.o
+ obj-$(CONFIG_MACH_EM_X270) += em-x270.o
+ obj-$(CONFIG_MACH_HX2750)     += hx2750.o hx2750_test.o
+Index: linux-2.6.17/arch/arm/mach-pxa/tosa_pm.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.17/arch/arm/mach-pxa/tosa_pm.c   2006-09-19 21:08:34.476201250 +0200
+@@ -0,0 +1,661 @@
++/*
++ * Battery and Power Management code for the Sharp SL-6000x
++ *
++ * Copyright (c) 2005 Dirk Opfer
++ *
++ * This program is free software; you can 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/stat.h>
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/delay.h>
++#include <linux/interrupt.h>
++#include <linux/platform_device.h>
++#include <linux/pm.h>
++#include <linux/wm97xx.h>
++
++#include <asm/apm.h>
++#include <asm/irq.h>
++#include <asm/mach-types.h>
++#include <asm/hardware.h>
++#include <asm/hardware/scoop.h>
++#include <asm/hardware/tmio.h>
++
++#include <asm/arch/sharpsl.h>
++#include <asm/arch/tosa.h>
++#include <asm/arch/pxa-regs.h>
++#include <sound/soc.h>
++#include <sound/ac97_codec.h>
++#include "sharpsl.h"
++
++extern int tosa_bl_intensity(void);
++volatile static int ad_polling;
++static int tosa_pm_driver_probe(struct device *dev);
++static int tosa_pm_driver_remove(struct device *dev);
++static struct wm97xx *wm9712;
++
++/************************************************************
++ * AC97 functions
++ ************************************************************/
++#define AC97_TIMEOUT_VAL      0x1000000
++
++#define AC97_MISC_MODEM_STAT  0x0056
++#define AC97_GPIO_CONFIG      0x004C
++
++static u16 tosa_ac97_read(unsigned short reg)
++{
++      volatile u32 *reg_addr;
++      volatile int timeout;
++      unsigned short data;
++
++      if (CAR & CAR_CAIP) {
++              printk(KERN_CRIT ": CAR_CAIP already set\n");
++              return 0;       
++      }
++
++      if (reg == AC97_GPIO_STATUS)
++              reg_addr = &PMC_REG_BASE;
++      else
++              reg_addr = &PAC_REG_BASE;
++
++      reg_addr += (reg >> 1);
++
++      data=0;
++      GSR = GSR_CDONE | GSR_SDONE;
++
++      data = *reg_addr;
++      timeout = 0;
++
++      while(((GSR & GSR_SDONE)) == 0 && (timeout++ < AC97_TIMEOUT_VAL));
++
++      if ((timeout >= AC97_TIMEOUT_VAL)) {
++              GSR = GSR;
++              printk(KERN_CRIT ": AC97 is busy1.\n");
++              return data;
++      }
++
++      // actual read
++      GSR = GSR_CDONE | GSR_SDONE;
++      data = *reg_addr;
++
++      timeout = 0;
++      while(((GSR & GSR_SDONE) == 0) && (timeout++<AC97_TIMEOUT_VAL));
++      if ((timeout >= AC97_TIMEOUT_VAL)) {
++              GSR = GSR;
++              printk(KERN_CRIT ": AC97 is busy2.\n");
++              return data;
++      }
++
++      return data;
++}
++
++static void tosa_ac97_write(unsigned short reg, unsigned short val)
++{
++      volatile u32 *reg_addr;
++      volatile int timeout=0;
++
++      if (CAR & CAR_CAIP) {
++              printk(KERN_CRIT ": CAR_CAIP already set\n");
++              return; 
++      }
++
++      GSR = GSR_CDONE | GSR_SDONE;
++      if (reg == AC97_GPIO_STATUS)
++              reg_addr = &PMC_REG_BASE;
++      else
++              reg_addr = &PAC_REG_BASE;
++
++      reg_addr += (reg >> 1);
++
++      *reg_addr = val;
++      while(((GSR & GSR_CDONE) == 0) && (timeout++ < AC97_TIMEOUT_VAL));
++      if (timeout >= AC97_TIMEOUT_VAL) {
++              printk(KERN_CRIT ": AC97 is busy.\n");
++      }
++}
++
++static void tosa_ac97_bit_clear(u8 reg, u16 val)
++{
++      unsigned short dat = tosa_ac97_read(reg);
++      dat &= ~val;
++      tosa_ac97_write(reg, dat);
++}
++
++static void tosa_ac97_bit_set(u8 reg, u16 val)
++{
++      unsigned short dat = tosa_ac97_read(reg);
++      dat |= val;
++      tosa_ac97_write(reg, dat);
++}
++
++
++static int tosa_ac97_init(void)
++{
++      int timeo;
++      
++      pxa_gpio_mode(GPIO31_SYNC_AC97_MD);
++      pxa_gpio_mode(GPIO30_SDATA_OUT_AC97_MD);
++      pxa_gpio_mode(GPIO28_BITCLK_AC97_MD);
++      pxa_gpio_mode(GPIO29_SDATA_IN_AC97_MD);
++      pxa_gpio_mode(GPIO20_DREQ0_MD);
++      
++      pxa_set_cken(CKEN2_AC97, 1);
++      /* AC97 power on sequense */
++      while ( 1 ) {
++              GCR = 0;
++              udelay(100);
++              GCR |= GCR_COLD_RST;
++              udelay(5);
++              GCR |= GCR_WARM_RST;
++              udelay(5);
++              for ( timeo = 0x10000; timeo > 0; timeo-- ) {
++                      if ( GSR & GSR_PCR ) break;
++                      mdelay(5);
++              }
++              if( timeo > 0 ) break;
++              printk(KERN_WARNING "AC97 power on retry!!\n");
++      }
++
++      tosa_ac97_write(AC97_EXTENDED_STATUS, 1);
++      /*
++      * Setting AC97 GPIO
++      *       i/o     function
++      *       GPIO1:   input   EAR_IN signal
++      *       GPIO2:   output  IRQ signal
++      *       GPIO3:   output  PENDOWN signal
++      *       GPIO4:   input   MASK signal
++      *       GPIO5:   input   DETECT MIC signal
++      */                      
++      //     AC97_GPIO_FUNC AC97_MISC_MODEM_STAT
++
++      tosa_ac97_bit_clear(AC97_MISC_MODEM_STAT,
++                      ((1<<2)|(1<<3)|(1<<4)|(1<<5)));
++      tosa_ac97_bit_clear(AC97_GPIO_CONFIG,(1<<2)|(1<<3));
++      tosa_ac97_bit_set(AC97_GPIO_CONFIG, (1<<1)|(1<<4)|(1<<5));
++
++      tosa_ac97_write(AC97_WM97XX_DIGITISER2, 0xc009);
++      tosa_ac97_write(AC97_WM97XX_DIGITISER1, 0x0030 | WM97XX_DELAY(4));
++
++      pxa_gpio_mode(GPIO32_SDATA_IN1_AC97_MD);
++      ad_polling = 1;
++      printk("tosa_ac97_init\n");
++}
++
++void tosa_ac97_exit(void)
++{
++      if (!(CKEN & CKEN2_AC97))
++              return;
++      
++      // power down the whole chip
++      tosa_ac97_write(AC97_POWERDOWN, 0x7fff);
++
++//       GCR &= ~(GCR_CDONE_IE | GCR_SDONE_IE | GCR_SECRDY_IEN | GCR_PRIRDY_IEN | GCR_SECRES_IEN | GCR_PRIRES_IEN);
++//        GSR = GSR;
++//    GCR = GCR_ACLINK_OFF;
++      pxa_set_cken(CKEN2_AC97, 0);
++      /* switch back to irq driver */
++      ad_polling = 0;
++      printk("tosa_ac97_exit\n");
++}
++
++int ac97_ad_input(u16 adcsel)
++{
++      unsigned short val = 0;
++      unsigned long timeout;
++
++      // prepare
++      tosa_ac97_read(AC97_WM97XX_DIGITISER_RD);
++      
++      if (adcsel & 0x8000)
++              adcsel = ((adcsel & 0x7fff) + 3) << 12;
++              
++      /* Conversion start */
++      tosa_ac97_write(AC97_WM97XX_DIGITISER1, (adcsel | WM97XX_POLL |  WM97XX_DELAY(4)));
++      timeout = 0x1000;
++      /* wait for POLL to go low */
++      while ((tosa_ac97_read(AC97_WM97XX_DIGITISER1) & WM97XX_POLL) && timeout) {
++              udelay(100);
++              timeout--;
++      }
++
++      val = tosa_ac97_read(AC97_WM97XX_DIGITISER_RD);
++      
++      val &= 0xFFF ;
++  
++      return val;
++}
++
++
++int tosa_read_aux_adc(u16 adcsel)  
++{
++      if (ad_polling)
++              return (ac97_ad_input(adcsel));
++      else
++              return (wm97xx_read_aux_adc(wm9712, adcsel));
++}
++
++static struct device_driver tosa_pm_driver = {
++    .name = "wm97xx-battery",
++    .bus = &wm97xx_bus_type,
++    .owner = THIS_MODULE,
++    .probe = tosa_pm_driver_probe,
++    .remove = tosa_pm_driver_remove,
++};
++
++#if 0
++#define TOSA_TEMP_READ_WAIT_TIME              (5)    // 5msec [Fix]
++int tosa_read_battery(struct wm97xx* wm, int channel)
++{
++      //return sprintf(buf, "%d\n", wm97xx_read_aux_adc(wm, input));
++
++      int wm_aux,i;
++      int value = 0;
++      int clear_mux;
++
++      switch(channel) {
++
++              case 0: // Main
++
++                      set_tc6393_gpio(&tc6393_device.dev,TOSA_TC6393_BAT0_V_ON);
++                      reset_tc6393_gpio(&tc6393_device.dev,TOSA_TC6393_BAT1_V_ON | TOSA_TC6393_BAT_SW_ON);
++                      wm_aux = WM97XX_AUX_ID3;
++                      break;
++
++              case 1: // Jacket
++
++                      set_tc6393_gpio(&tc6393_device.dev,TOSA_TC6393_BAT1_V_ON);
++                      reset_tc6393_gpio(&tc6393_device.dev,TOSA_TC6393_BAT0_V_ON | TOSA_TC6393_BAT_SW_ON);
++                      wm_aux = WM97XX_AUX_ID3;
++                      break;
++
++              case 2:  // BU
++                      set_tc6393_gpio(&tc6393_device.dev,TOSA_TC6393_BU_CHRG_ON);
++                      wm_aux = WM97XX_AUX_ID4;
++                      break;
++
++              case 3:  // Main Temp
++                      set_tc6393_gpio(&tc6393_device.dev,TOSA_TC6393_BAT1_TH_ON);
++                      reset_tc6393_gpio(&tc6393_device.dev,TOSA_TC6393_BAT0_TH_ON);
++                      wm_aux = WM97XX_AUX_ID2;
++                      break;
++
++              case 4:  // Jacket Temp
++                      set_tc6393_gpio(&tc6393_device.dev,TOSA_TC6393_BAT0_TH_ON);
++                      reset_tc6393_gpio(&tc6393_device.dev,TOSA_TC6393_BAT1_TH_ON);
++                      wm_aux = WM97XX_AUX_ID2;
++                      break;
++
++              default:
++                      return -1;
++      }
++      
++      mdelay(TOSA_TEMP_READ_WAIT_TIME);
++      for(i=0;i<4;i++)
++      {
++              if (wm9712)
++                      value += wm97xx_read_aux_adc(wm, wm_aux);
++              else
++                      value += ac97_ad_input(wm, wm_aux);
++      }
++
++      value>>=2;
++      // reset the multiplexer
++      clear_mux = TOSA_TC6393_BAT0_V_ON  | TOSA_TC6393_BAT1_V_ON | TOSA_TC6393_BAT_SW_ON | TOSA_TC6393_BAT0_TH_ON | TOSA_TC6393_BAT1_TH_ON | TOSA_TC6393_BU_CHRG_ON;
++
++      return value;
++
++}
++#endif
++
++/* BL 5-3 */
++struct battery_thresh tosa_battery_levels_bl[] = {
++      { 1663, 100 },
++      { 1605,  75 },
++      { 1564,  50 },
++      { 1510,  25 },
++      { 1435,   5 },
++      {   0,    0 },
++};
++
++/* BL 2-0 */
++struct battery_thresh tosa_battery_levels[] = {
++      { 1679, 100 },
++      { 1617,  75 },
++      { 1576,  50 },
++      { 1530,  25 },
++      { 1448,   5 },
++      {   0,    0 },
++};
++
++struct pm_devices {
++      const char * name;
++      struct bus_type *bus;
++      struct device_driver *driver;
++      struct device * dev;
++      int (*resume)(struct device *dev, void * data); //      int (*resume)(struct device *dev);
++      int (*suspend)(struct device *dev, void * data);//      int (*suspend)(struct device *dev, pm_message_t state);
++};
++
++/* Ugly
++   We need the following devices to measure the battery and control the charger:
++   Also we need access to these before we sleep and immediatly after we resume so we can't
++   control their pm via the kernel device manager. To access their pm functions we will backup
++   the suspend and resume handler and clear these pointers.
++   After that we can suspend and resume these devices.
++
++   Don't change the order of this table!!!!!
++*/
++static struct pm_devices dev_table[] = {
++      [0] = {
++              .name   = TMIO_SOC_NAME,
++              .bus    = &platform_bus_type,
++      },
++};
++
++static int tosa_pm_driver_probe(struct device *dev)
++{
++      wm9712 = dev->driver_data;
++      ad_polling = 0;
++      return 0;
++}
++
++static int tosa_pm_driver_remove(struct device *dev)
++{
++    wm9712 = NULL;
++    return 0;
++}
++
++
++static void tosa_charger_init(void)
++{
++    int i;
++
++    /* If this driver doesn't register, bad things will happen, Tosa won't boot,
++       and the world will possibly explode */
++    i = driver_register(&tosa_pm_driver);
++    if (i < 0)
++        panic("Cannot register the tosa_pm driver on the wm97xx bus. Halting.");
++
++      for(i=0;i<ARRAY_SIZE(dev_table);i++)
++      {
++              dev_table[i].driver = driver_find(dev_table[i].name, dev_table[i].bus);
++              if (dev_table[i].driver)
++              {
++                      dev_table[i].resume = dev_table[i].driver->resume;
++                      dev_table[i].suspend = dev_table[i].driver->suspend;
++                      dev_table[i].driver->resume = NULL;
++                      dev_table[i].driver->suspend = NULL;
++              }
++      }
++      
++      pxa_gpio_mode(TOSA_GPIO_AC_IN | GPIO_IN);
++      pxa_gpio_mode(TOSA_GPIO_BAT0_CRG | GPIO_IN);
++      pxa_gpio_mode(TOSA_GPIO_BAT1_CRG | GPIO_IN);
++      pxa_gpio_mode(TOSA_GPIO_BAT0_LOW | GPIO_IN);
++      pxa_gpio_mode(TOSA_GPIO_BAT1_LOW | GPIO_IN);
++
++      pxa_gpio_mode(TOSA_GPIO_JACKET_DETECT | GPIO_IN);
++      pxa_gpio_mode(TOSA_GPIO_POWERON | GPIO_IN);
++      sharpsl_pm_pxa_init();
++}
++
++
++static void tosa_measure_temp(int on)
++{
++      reset_tc6393_gpio(&tc6393_device.dev,TOSA_TC6393_BAT0_TH_ON | TOSA_TC6393_BAT1_TH_ON);
++
++      if (on)
++              set_tc6393_gpio(&tc6393_device.dev,TOSA_TC6393_BAT1_TH_ON);
++
++}
++
++static void tosa_charge(int on)
++{
++      if(on)
++              reset_tc6393_gpio(&tc6393_device.dev,TOSA_TC6393_CHARGE_OFF);
++      else
++              set_tc6393_gpio(&tc6393_device.dev,TOSA_TC6393_CHARGE_OFF);
++}
++
++static void tosa_discharge1(int on)
++{
++}
++
++static void tosa_discharge(int on)
++{
++}
++
++
++static void tosa_presuspend(void)
++{
++      int i;
++      unsigned long wakeup_mask;
++      
++      // put remaining devices into sleep
++      for(i=0;i<ARRAY_SIZE(dev_table);i++)
++      {
++              if(dev_table[i].suspend)
++                      driver_for_each_device(dev_table[i].driver, NULL, 
++                         (void*)&PMSG_SUSPEND, dev_table[i].suspend);
++      }
++      
++      tosa_ac97_exit();
++      
++      wakeup_mask = GPIO_bit(TOSA_GPIO_POWERON) | GPIO_bit(TOSA_GPIO_ON_KEY) | GPIO_bit(TOSA_GPIO_AC_IN);
++
++      wakeup_mask |= GPIO_bit(TOSA_GPIO_BAT0_LOW);
++      PWER = wakeup_mask | PWER_RTC;
++
++      PRER = wakeup_mask;
++      PFER = wakeup_mask;
++
++      for (i = 0; i <=15; i++) {
++              if (PRER & PFER & GPIO_bit(i)) {
++                      if (GPLR0 & GPIO_bit(i) )
++                              PRER &= ~GPIO_bit(i);
++                      else
++                              PFER &= ~GPIO_bit(i);
++              }
++      }
++      
++      /* Clear reset status */
++      RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR;
++
++      /* Stop 3.6MHz and drive HIGH to PCMCIA and CS */
++      PCFR = PCFR_OPDE;
++      
++      /* Resume on keyboard power key */
++      PGSR1 = (PGSR1 & ~TOSA_GPIO_LOW_STROBE_BIT);
++      PGSR2 = (PGSR2 & ~TOSA_GPIO_HIGH_STROBE_BIT); 
++      
++      GPDR0 = 0xC3810940;
++      GPDR1 = 0xFCFFAB82;
++      GPDR2 = 0x000F501f;
++//    write_scoop_reg(&tosascoop_device.dev,SCOOP_GPWR,0);
++// only debug
++reset_scoop_gpio(&tosascoop_jc_device.dev, TOSA_SCOOP_JC_NOTE_LED);
++}
++
++void tosa_postsuspend(void)
++{
++      int i;
++// only debug
++set_scoop_gpio(&tosascoop_jc_device.dev, TOSA_SCOOP_JC_NOTE_LED);
++
++      for(i=ARRAY_SIZE(dev_table);i;i--)
++      {
++              if(dev_table[i-1].resume)
++                      driver_for_each_device(dev_table[i-1].driver, NULL, 
++                         NULL, dev_table[i-1].resume);
++      }
++      tosa_ac97_init();
++      PMCR = 0x01;
++}
++
++void tosa_postresume(void)
++{
++      tosa_ac97_exit();
++}
++
++/*
++ * Check what brought us out of the suspend.
++ * Return: 0 to sleep, otherwise wake
++ */
++static int tosa_should_wakeup(unsigned int resume_on_alarm)
++{
++      int is_resume = 0;
++
++      dev_dbg(sharpsl_pm.dev, "GPLR0 = %x,%x\n", GPLR0, PEDR);
++
++      if ((PEDR & GPIO_bit(TOSA_GPIO_AC_IN))) {
++              if (sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN)) {
++                      /* charge on */
++                      dev_dbg(sharpsl_pm.dev, "ac insert\n");
++                      sharpsl_pm.flags |= SHARPSL_DO_OFFLINE_CHRG;
++              } else {
++                      /* charge off */
++                      dev_dbg(sharpsl_pm.dev, "ac remove\n");
++                      sharpsl_pm_led(SHARPSL_LED_OFF);
++                      sharpsl_pm.machinfo->charge(0);
++                      sharpsl_pm.charge_mode = CHRG_OFF;
++              }
++      }
++
++      if ((PEDR & GPIO_bit(GPIO_bit(TOSA_GPIO_BAT0_CRG))))
++              dev_dbg(sharpsl_pm.dev, "Charge full interrupt\n");
++
++      if (PEDR & GPIO_bit(TOSA_GPIO_POWERON))
++              is_resume |= GPIO_bit(TOSA_GPIO_POWERON);
++
++      if (PEDR & GPIO_bit(TOSA_GPIO_ON_KEY))
++              is_resume |= GPIO_bit(TOSA_GPIO_ON_KEY);
++
++      if (resume_on_alarm && (PEDR & PWER_RTC))
++              is_resume |= PWER_RTC;
++
++      return is_resume;
++}
++
++static unsigned long tosa_charger_wakeup(void)
++{
++//    return ~GPLR0 & ( GPIO_bit(TOSA_GPIO_AC_IN) | GPIO_bit(TOSA_GPIO_POWERON) | GPIO_bit(TOSA_GPIO_ON_KEY) );
++      return (~GPLR0 & ( GPIO_bit(TOSA_GPIO_POWERON) | GPIO_bit(TOSA_GPIO_ON_KEY) )) | (GPLR0 & GPIO_bit(TOSA_GPIO_AC_IN));
++}
++
++unsigned long tosa_read_bat(void)
++{
++      unsigned long value;
++      reset_tc6393_gpio(&tc6393_device.dev,TOSA_TC6393_BAT0_V_ON | TOSA_TC6393_BAT1_V_ON | TOSA_TC6393_BAT_SW_ON);
++      mdelay(5);
++      value = tosa_read_aux_adc(WM97XX_AUX_ID3);
++      set_tc6393_gpio(&tc6393_device.dev,TOSA_TC6393_BAT0_V_ON);
++      return value;
++}
++
++unsigned long tosapm_read_devdata(int type)
++{
++      switch(type) {
++      case SHARPSL_STATUS_ACIN:
++              return ((GPLR(TOSA_GPIO_AC_IN) & GPIO_bit(TOSA_GPIO_AC_IN)) == 0);              
++      case SHARPSL_STATUS_LOCK:
++              return READ_GPIO_BIT(sharpsl_pm.machinfo->gpio_batlock);
++      case SHARPSL_STATUS_CHRGFULL:
++              return READ_GPIO_BIT(sharpsl_pm.machinfo->gpio_batfull);
++      case SHARPSL_STATUS_FATAL:
++              return READ_GPIO_BIT(sharpsl_pm.machinfo->gpio_fatal);
++      case SHARPSL_ACIN_VOLT:
++              return 1000;    // not used on tosa
++      case SHARPSL_BATT_TEMP:
++              return tosa_read_aux_adc(WM97XX_AUX_ID2);
++      case SHARPSL_BATT_VOLT:
++              return tosa_read_bat();
++      default:
++              return tosa_read_bat();
++      }
++}
++
++static struct sharpsl_charger_machinfo tosa_pm_machinfo = {
++      .init            = tosa_charger_init,
++      .exit            = sharpsl_pm_pxa_remove,
++      .gpio_batlock    = TOSA_GPIO_BAT_LOCKED,
++      .gpio_acin       = TOSA_GPIO_AC_IN,
++      .gpio_batfull    = TOSA_GPIO_BAT0_CRG,
++      .batfull_irq     = 0,
++      .discharge       = tosa_discharge,
++      .discharge1      = tosa_discharge1,
++      .charge          = tosa_charge,
++      .measure_temp    = tosa_measure_temp,
++      .presuspend      = tosa_presuspend,
++      .postsuspend     = tosa_postsuspend,
++      .postresume      = tosa_postresume,
++      .read_devdata    = tosapm_read_devdata,
++      .charger_wakeup  = tosa_charger_wakeup,
++      .should_wakeup   = tosa_should_wakeup,
++        .backlight_limit = corgibl_limit_intensity,
++      .backlight_get_status= tosa_bl_intensity,
++      .bat_levels      = 6,
++      .bat_levels_noac = tosa_battery_levels,
++      .bat_levels_acin = tosa_battery_levels,
++      .bat_levels_noac_bl = tosa_battery_levels_bl,
++      .bat_levels_acin_bl = tosa_battery_levels_bl,
++      .charge_on_volt   = 1200,       // 2.9V TOSA_MAIN_BATTERY_ERR_THRESH voltage < 1200 -> error
++      .charge_on_temp   = 3600,       // --   TOSA_MAIN_BATTERY_EXIST_THRESH temp > 3600 -> error, no battery
++      .charge_acin_high = 1500,       // not used default value
++      .charge_acin_low  = 500,        // not used default value
++      .fatal_acin_volt  = 1572,       // 3.8V
++      .fatal_noacin_volt= 1551,       // 3.75V
++      .status_high_acin = 1564,       // 3.78V
++      .status_low_acin  = 1510,       // 3.65V
++      .status_high_noac = 1564,       // 3.78V
++      .status_low_noac  = 1510,       // 3.65V
++};
++
++static struct platform_device *tosapm_device;
++
++static int __devinit tosapm_init(void)
++{
++      int ret;
++
++      tosapm_device = platform_device_alloc("sharpsl-pm", -1);
++      if (!tosapm_device)
++              return -ENOMEM;
++
++      tosapm_device->dev.platform_data = &tosa_pm_machinfo;
++      ret = platform_device_add(tosapm_device);
++
++      if (ret)
++              platform_device_put(tosapm_device);
++
++      return ret;
++}
++
++static void tosapm_exit(void)
++{
++      int i;
++
++      // restore the resume / suspend handler
++      for(i=0;i<ARRAY_SIZE(dev_table);i++)
++      {
++              if (dev_table[i].driver)
++              {
++                      dev_table[i].driver->resume = dev_table[i].resume;
++                      dev_table[i].driver->suspend = dev_table[i].suspend;
++                      dev_table[i].resume = NULL;
++                      dev_table[i].suspend = NULL;
++                      put_driver(dev_table[i].driver);
++              }
++      }
++
++      if (wm9712)
++              driver_unregister(&tosa_pm_driver);
++
++      platform_device_unregister(tosapm_device);
++}
++
++module_init(tosapm_init);
++module_exit(tosapm_exit);
+Index: linux-2.6.17/arch/arm/mach-pxa/Kconfig
+===================================================================
+--- linux-2.6.17.orig/arch/arm/mach-pxa/Kconfig        2006-09-19 20:51:40.160810500 +0200
++++ linux-2.6.17/arch/arm/mach-pxa/Kconfig     2006-09-19 21:08:04.926354500 +0200
+@@ -110,6 +110,7 @@ config MACH_TOSA
+       bool "Enable Sharp SL-6000x (Tosa) Support"
+       depends PXA_SHARPSL_25x
+       select TOSHIBA_TC6393XB
++      select SHARPSL_PM       
+ config PXA25x
+       bool
diff --git a/packages/kexecboot/linux-kexecboot-2.6.23/tosa-pxaac97-r6-fix-r0.patch b/packages/kexecboot/linux-kexecboot-2.6.23/tosa-pxaac97-r6-fix-r0.patch
new file mode 100644 (file)
index 0000000..9c18aae
--- /dev/null
@@ -0,0 +1,29 @@
+From 005693333f4b3e0495bb80cc3cfd812e3e6f0a30 Mon Sep 17 00:00:00 2001
+From: Dmitry Baryshkov <dbaryshkov@gmail.com>
+Date: Fri, 19 Oct 2007 00:48:42 +0400
+Subject: [PATCH] tosa-pxaac97-r6.patch fixes
+
+---
+ arch/arm/mach-pxa/tosa.c |    4 ++--
+ 1 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c
+index 059fa07..61536d4 100644
+--- a/arch/arm/mach-pxa/tosa.c
++++ b/arch/arm/mach-pxa/tosa.c
+@@ -310,10 +310,10 @@ static void __init tosa_init(void)
+       PMCR = 0x01;
+         // AC97 Disable all IRQ's
+-        pxa_set_cken(CKEN2_AC97, 1);
++        pxa_set_cken(CKEN_AC97, 1);
+         GCR &= ~(GCR_CDONE_IE | GCR_SDONE_IE | GCR_SECRDY_IEN | GCR_PRIRDY_IEN | GCR_SECRES_IEN | GCR_PRIRES_IEN);
+         GSR = GSR;
+-      pxa_set_cken(CKEN2_AC97, 0);
++      pxa_set_cken(CKEN_AC97, 0);
+                                                                       
+       pxa_set_mci_info(&tosa_mci_platform_data);
+       pxa_set_udc_info(&udc_info);
+-- 
+1.4.4.4
+
diff --git a/packages/kexecboot/linux-kexecboot-2.6.23/tosa-tmio-lcd-r10-fix-r0.patch b/packages/kexecboot/linux-kexecboot-2.6.23/tosa-tmio-lcd-r10-fix-r0.patch
new file mode 100644 (file)
index 0000000..a2e2bee
--- /dev/null
@@ -0,0 +1,35 @@
+From bb3ed6577c592d86f0976a92978c9454bbdfbe59 Mon Sep 17 00:00:00 2001
+From: Dmitry Baryshkov <dbaryshkov@gmail.com>
+Date: Fri, 19 Oct 2007 02:01:23 +0400
+Subject: [PATCH] tosa-tmio-lcd-r10.patch fixes
+
+---
+ arch/arm/mach-pxa/tosa_lcd.c |    5 +++--
+ 1 files changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/arch/arm/mach-pxa/tosa_lcd.c b/arch/arm/mach-pxa/tosa_lcd.c
+index eeeee3e..d52f63f 100644
+--- a/arch/arm/mach-pxa/tosa_lcd.c
++++ b/arch/arm/mach-pxa/tosa_lcd.c
+@@ -66,7 +66,7 @@ static unsigned short normal_i2c[] = {
+ };
+ I2C_CLIENT_INSMOD;
+-static struct corgibl_machinfo tosa_bl_machinfo = {
++static struct generic_bl_info tosa_bl_machinfo = {
+       .max_intensity = 255,
+       .default_intensity = 68,
+       .limit_mask = 0x0b,
+@@ -80,7 +80,8 @@ int tosa_bl_intensity(void)
+ static void pxa_nssp_output(unsigned char reg, unsigned char data)
+ {
+-      unsigned long flag, dummy;
++      unsigned long flag;
++      u32 dummy;
+       u32 dat = ( ((reg << 5) & 0xe0) | (data & 0x1f) );
+       spin_lock_irqsave(&tosa_nssp_lock, flag);
+-- 
+1.4.4.4
+
diff --git a/packages/kexecboot/linux-kexecboot-2.6.23/tosa-tmio-lcd-r10.patch b/packages/kexecboot/linux-kexecboot-2.6.23/tosa-tmio-lcd-r10.patch
new file mode 100644 (file)
index 0000000..fe5c45d
--- /dev/null
@@ -0,0 +1,464 @@
+ arch/arm/mach-pxa/Kconfig    |    5 
+ arch/arm/mach-pxa/Makefile   |    2 
+ arch/arm/mach-pxa/tosa.c     |   49 +++++-
+ arch/arm/mach-pxa/tosa_lcd.c |  344 +++++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 396 insertions(+), 4 deletions(-)
+
+Index: git/arch/arm/mach-pxa/Makefile
+===================================================================
+--- git.orig/arch/arm/mach-pxa/Makefile        2006-11-07 22:13:10.000000000 +0000
++++ git/arch/arm/mach-pxa/Makefile     2006-11-07 23:29:38.000000000 +0000
+@@ -17,7 +17,7 @@ obj-$(CONFIG_PXA_SHARP_C7xx) += corgi.o 
+ obj-$(CONFIG_PXA_SHARP_Cxx00) += spitz.o corgi_ssp.o corgi_lcd.o sharpsl_pm.o spitz_pm.o
+ obj-$(CONFIG_MACH_AKITA)      += akita-ioexp.o
+ obj-$(CONFIG_MACH_POODLE)     += poodle.o corgi_ssp.o sharpsl_pm.o poodle_pm.o
+-obj-$(CONFIG_MACH_TOSA)         += tosa.o sharpsl_pm.o tosa_pm.o
++obj-$(CONFIG_MACH_TOSA)         += tosa.o sharpsl_pm.o tosa_pm.o tosa_lcd.o
+ obj-$(CONFIG_MACH_EM_X270) += em-x270.o
+ obj-$(CONFIG_MACH_HX2750)     += hx2750.o hx2750_test.o
+Index: git/arch/arm/mach-pxa/tosa_lcd.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ git/arch/arm/mach-pxa/tosa_lcd.c   2006-11-07 23:29:25.000000000 +0000
+@@ -0,0 +1,344 @@
++/*
++ *  LCD / Backlight control code for Sharp SL-6000x (tosa)
++ *
++ *  Copyright (c) 2005                Dirk Opfer
++ *
++ *  This program is free software; you can 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/sched.h>
++#include <linux/slab.h>
++#include <linux/delay.h>
++#include <linux/platform_device.h>
++#include <linux/i2c.h>
++#include <linux/fb.h>
++
++#include <asm/mach/sharpsl_param.h>
++#include <asm/hardware.h>
++#include <asm/hardware/scoop.h>
++#include <asm/hardware/tmio.h>
++#include <asm/arch/ssp.h>
++#include <asm/arch/sharpsl.h>
++#include <asm/arch/tosa.h>
++#include <asm/arch/pxa-regs.h>
++
++#define       DAC_BASE        0x4e
++#define DAC_CH1               0
++#define DAC_CH2               1
++
++#define TG_REG0_VQV   0x0001
++#define TG_REG0_COLOR 0x0002
++#define TG_REG0_UD    0x0004
++#define TG_REG0_LR    0x0008
++#define COMADJ_DEFAULT        97
++#define TOSA_LCD_I2C_DEVICEID 0x4711                  // Fixme: new value
++
++static void tosa_lcd_tg_init(struct device *dev);
++static void tosa_lcd_tg_on(struct device *dev, const struct fb_videomode *mode);
++static void tosa_lcd_tg_off(struct device *dev);
++static void tosa_set_backlight(int intensity);
++
++const static struct tmio_lcd_ops tosa_tc6393_lcd_ops = {
++      .init = tosa_lcd_tg_init,
++      .tg_on = tosa_lcd_tg_on,
++      .tg_off = tosa_lcd_tg_off,
++};
++
++static struct platform_device *tosabl_device;
++static struct i2c_driver tosa_driver;
++static struct i2c_client* tosa_i2c_dac;
++static int initialised;
++static int comadj;
++static int bl_intensity;
++static struct ssp_dev tosa_nssp_dev;
++static struct ssp_state tosa_nssp_state;
++static spinlock_t tosa_nssp_lock;
++
++static unsigned short normal_i2c[] = {
++      DAC_BASE,
++      I2C_CLIENT_END 
++};
++I2C_CLIENT_INSMOD;
++
++static struct corgibl_machinfo tosa_bl_machinfo = {
++      .max_intensity = 255,
++      .default_intensity = 68,
++      .limit_mask = 0x0b,
++      .set_bl_intensity = tosa_set_backlight,
++};
++
++int tosa_bl_intensity(void)
++{
++      return bl_intensity;
++}
++
++static void pxa_nssp_output(unsigned char reg, unsigned char data)
++{
++      unsigned long flag, dummy;
++      u32 dat = ( ((reg << 5) & 0xe0) | (data & 0x1f) );
++      spin_lock_irqsave(&tosa_nssp_lock, flag);
++
++      ssp_config(&tosa_nssp_dev, (SSCR0_Motorola | (SSCR0_DSS & 0x07 )), 0, 0, SSCR0_SerClkDiv(128));
++      ssp_enable(&tosa_nssp_dev);
++
++      ssp_write_word(&tosa_nssp_dev,dat);
++
++      /* Read null data back from device to prevent SSP overflow */
++      ssp_read_word(&tosa_nssp_dev, &dummy);
++      ssp_disable(&tosa_nssp_dev);
++      spin_unlock_irqrestore(&tosa_nssp_lock, flag);
++
++}
++
++static void tosa_set_backlight(int intensity)
++{
++      if (!tosa_i2c_dac)
++              return;
++
++      bl_intensity = intensity;
++      /* SetBacklightDuty */
++      i2c_smbus_write_byte_data(tosa_i2c_dac, DAC_CH2, (unsigned char)intensity);
++
++      /* SetBacklightVR */
++      if (intensity)
++              set_tc6393_gpio(&tc6393_device.dev,TOSA_TC6393_BL_C20MA);
++      else
++              reset_tc6393_gpio(&tc6393_device.dev,TOSA_TC6393_BL_C20MA);
++
++      /* bl_enable GP04=1 otherwise GP04=0*/
++      pxa_nssp_output(TG_GPODR2, intensity ? 0x01 : 0x00);    
++}
++
++static void tosa_lcd_tg_init(struct device *dev)
++{
++      /* L3V On */
++      set_scoop_gpio( &tosascoop_jc_device.dev,TOSA_SCOOP_JC_TC3693_L3V_ON); 
++      mdelay(60);
++
++      /* TG On */
++      reset_tc6393_gpio(&tc6393_device.dev,TOSA_TC6393_TG_ON);
++      mdelay(60);
++
++      pxa_nssp_output(TG_TPOSCTL,0x00);       /* delayed 0clk TCTL signal for VGA */
++      pxa_nssp_output(TG_GPOSR,0x02);         /* GPOS0=powercontrol, GPOS1=GPIO, GPOS2=TCTL */
++}
++
++static void tosa_lcd_tg_on(struct device *dev, const struct fb_videomode *mode)
++{
++      const int value = TG_REG0_COLOR | TG_REG0_UD | TG_REG0_LR;
++      pxa_nssp_output(TG_PNLCTL, value | (mode->yres == 320 ? 0 :  TG_REG0_VQV));
++
++      /* TG LCD pannel power up */
++      pxa_nssp_output(TG_PINICTL,0x4);
++      mdelay(50);
++
++      /* TG LCD GVSS */
++      pxa_nssp_output(TG_PINICTL,0x0);
++
++      if (!initialised)
++      {
++              /* after the pannel is powered up the first time, we can access the i2c bus */
++              /* so probe for the DAC */
++              i2c_add_driver(&tosa_driver);
++              initialised = 1;
++              mdelay(50);
++      }
++      if (tosa_i2c_dac)
++              /* set common voltage */
++              i2c_smbus_write_byte_data(tosa_i2c_dac, DAC_CH1, comadj);
++
++}
++
++static void tosa_lcd_tg_off(struct device *dev)
++{
++      /* TG LCD VHSA off */
++      pxa_nssp_output(TG_PINICTL,0x4);
++      mdelay(50);
++      
++      /* TG LCD signal off */
++      pxa_nssp_output(TG_PINICTL,0x6);
++      mdelay(50);
++      
++      /* TG Off */
++      set_tc6393_gpio(&tc6393_device.dev, TOSA_TC6393_TG_ON);
++      mdelay(100);
++      
++      /* L3V Off */
++      reset_scoop_gpio( &tosascoop_jc_device.dev,TOSA_SCOOP_JC_TC3693_L3V_ON); 
++}
++
++static int tosa_detect_client(struct i2c_adapter* adapter, int address, int kind) {
++      int err = 0;
++
++      printk("Tosa-LCD: DAC detected address:0x%2.2x\n",address);
++      if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA ))
++              goto ERROR0;
++
++      if (!(tosa_i2c_dac = (struct i2c_client*)kzalloc(sizeof(*tosa_i2c_dac), GFP_KERNEL))) {
++              err = -ENOMEM;
++              goto ERROR0;
++      }
++
++      //i2c_set_clientdata(tosa_i2c_dac, data);
++      tosa_i2c_dac->addr = address;
++      tosa_i2c_dac->adapter = adapter;
++      tosa_i2c_dac->driver = &tosa_driver;
++      tosa_i2c_dac->dev.parent = &tc6393_device.dev;
++      strcpy(tosa_i2c_dac->name, "tosa lcd");
++      if ((err = i2c_attach_client(tosa_i2c_dac)))
++              goto ERROR3;
++
++      /* Now i2c is ready, allocate the backlight device*/
++      tosabl_device = platform_device_alloc("corgi-bl", -1);
++      if (!tosabl_device) {
++              err = -ENOMEM;
++              goto ERROR4;
++      }
++
++      /* set parent device */
++      tosabl_device->dev.parent = &tosa_i2c_dac->dev;
++      tosabl_device->dev.platform_data  = &tosa_bl_machinfo;
++
++      err = platform_device_add(tosabl_device);
++
++      if (err)
++              platform_device_put(tosabl_device);
++
++      /* set common voltage */
++      i2c_smbus_write_byte_data(tosa_i2c_dac, DAC_CH1, comadj);
++
++      return 0;
++ERROR4:
++      i2c_detach_client(tosa_i2c_dac);
++ERROR3:
++      kfree(tosa_i2c_dac);
++ERROR0:
++      return err;
++}
++
++static int tosa_attach_adapter(struct i2c_adapter* adapter) {
++      return i2c_probe(adapter, &addr_data, &tosa_detect_client);
++}
++
++static int tosa_detach_client(struct i2c_client* client) {
++      int err;
++
++      if ((err = i2c_detach_client(client))) {
++              printk(KERN_ERR "tosa: Cannot deregister client\n");
++              return err;
++      }
++      kfree(client);
++      return 0;
++}
++
++static struct i2c_driver tosa_driver={
++      .id             = TOSA_LCD_I2C_DEVICEID,
++      .attach_adapter = tosa_attach_adapter,
++      .detach_client  = tosa_detach_client,
++};
++
++static int __init tosa_lcd_probe(struct platform_device *pdev)
++{
++      int ret;
++      spin_lock_init(&tosa_nssp_lock);
++
++      if (!pdev->dev.platform_data)
++              return -EINVAL;
++
++      /* Set Common Voltage */
++      comadj = sharpsl_param.comadj == -1 ? COMADJ_DEFAULT : sharpsl_param.comadj;
++
++      ret=ssp_init(&tosa_nssp_dev,2,0);
++
++      /* initialize SSP */
++      pxa_gpio_mode(GPIO83_NSSP_TX);
++      pxa_gpio_mode(GPIO81_NSSP_CLK_OUT);
++      pxa_gpio_mode(GPIO82_NSSP_FRM_OUT);
++
++      if (ret) 
++              printk(KERN_ERR "Unable to register NSSP handler!\n");
++      else {
++              struct tmio_lcd_ops* *tmio_ops = pdev->dev.platform_data;
++              ssp_disable(&tosa_nssp_dev);
++              initialised = 0;
++
++              /* Set the lcd functions */
++              *tmio_ops = (struct tmio_lcd_ops*) &tosa_tc6393_lcd_ops;
++      }
++
++      return ret;
++}
++
++static int tosa_lcd_remove(struct platform_device *pdev)
++{
++      /* delete the lcd functions */
++      struct tmio_lcd_ops* *tmio_ops = pdev->dev.platform_data;
++      *tmio_ops = NULL;
++      
++      ssp_exit(&tosa_nssp_dev);
++      
++      if (tosa_i2c_dac) {
++              i2c_detach_client(tosa_i2c_dac);
++              kfree(tosa_i2c_dac);
++      }
++
++      return 0;
++}
++
++#ifdef CONFIG_PM 
++
++static int tosa_lcd_suspend(struct platform_device *pdev, pm_message_t state)
++{
++      ssp_flush(&tosa_nssp_dev);
++      ssp_save_state(&tosa_nssp_dev,&tosa_nssp_state);
++      return 0;
++}
++
++static int tosa_lcd_resume(struct platform_device *pdev)
++{
++      printk("tosa_lcd_resume\n");
++      ssp_restore_state(&tosa_nssp_dev,&tosa_nssp_state);
++      ssp_enable(&tosa_nssp_dev);
++      printk("tosa_lcd_resume ok\n"); 
++      return 0;
++}
++#else
++
++#define tosa_lcd_suspend NULL
++#define tosa_lcd_resume NULL
++
++#endif
++
++
++static struct platform_driver tosalcd_driver = {
++      .probe          = tosa_lcd_probe,
++      .remove         = tosa_lcd_remove,
++      .suspend        = tosa_lcd_suspend,
++      .resume         = tosa_lcd_resume,
++      .driver         = {
++              .name           = "tosa-lcd",
++      },
++};
++
++static int __init tosa_lcd_init(void)
++{
++      return platform_driver_register(&tosalcd_driver);
++}
++
++static void __exit tosa_lcd_cleanup (void)
++{
++      platform_driver_unregister (&tosalcd_driver);
++}
++
++device_initcall(tosa_lcd_init);
++module_exit (tosa_lcd_cleanup);
++
++MODULE_DESCRIPTION ("Tosa LCD device");
++MODULE_AUTHOR ("Dirk Opfer");
++MODULE_LICENSE ("GPL v2");
+Index: git/arch/arm/mach-pxa/tosa.c
+===================================================================
+--- git.orig/arch/arm/mach-pxa/tosa.c  2006-11-07 22:13:10.000000000 +0000
++++ git/arch/arm/mach-pxa/tosa.c       2006-11-07 23:29:38.000000000 +0000
+@@ -24,6 +24,7 @@
+ #include <linux/mtd/partitions.h>
+ #include <linux/pm.h>
+ #include <linux/delay.h>
++#include <linux/fb.h>
+ #include <asm/setup.h>
+ #include <asm/memory.h>
+@@ -345,7 +345,38 @@ static struct tmio_nand_platform_data to
+       .badblock_pattern = &tosa_tc6393_nand_bbt,
+ };
+-extern struct tmio_lcd_platform_data tosa_tc6393_lcd_platform_data;
++static struct fb_videomode tosa_tc6393_lcd_mode[] = {
++    {
++        .xres = 480,
++        .yres = 640,
++        .pixclock = 0x002cdf00,/* PLL divisor */
++        .left_margin = 0x004c,
++        .right_margin = 0x005b,
++        .upper_margin = 0x0001,
++        .lower_margin = 0x000d,
++        .hsync_len = 0x0002,
++        .vsync_len = 0x0001,
++        .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
++        .vmode = FB_VMODE_NONINTERLACED,
++    },{
++      .xres = 240,
++      .yres = 320,
++      .pixclock = 0x00e7f203,/* PLL divisor */
++      .left_margin = 0x0024,
++      .right_margin = 0x002f,
++      .upper_margin = 0x0001,
++      .lower_margin = 0x000d,
++      .hsync_len = 0x0002,
++      .vsync_len = 0x0001,
++      .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
++      .vmode = FB_VMODE_NONINTERLACED,
++}};
++
++struct tmio_lcd_platform_data tosa_tc6393_lcd_platform_data = {
++    .ops = NULL,
++    .modelist = tosa_tc6393_lcd_mode,
++    .num_modes = ARRAY_SIZE(tosa_tc6393_lcd_mode),
++};
+ static struct tmio_cell tosa_tc6393_cells[] = {
+       {
+@@ -384,6 +415,19 @@ struct platform_device tc6393_device = {
+       .num_resources  = ARRAY_SIZE(tc6393_resources),
+       .resource       = tc6393_resources,
+ };
++EXPORT_SYMBOL (tc6393_device);
++
++/*
++ * Tosa LCD / Backlight stuff
++ */
++static struct platform_device tosalcd_device = {
++    .name     = "tosa-lcd",
++    .id               = -1,
++    .dev      = {
++      .parent = &tc6393_device.dev,
++      .platform_data = &tosa_tc6393_lcd_platform_data.ops,
++    },
++};
+ static struct platform_device *devices[] __initdata = {
+       &tosascoop_device,
+@@ -391,6 +435,7 @@ static struct platform_device *devices[]
+       &tosakbd_device,
+       &tosaled_device,
+       &tc6393_device,
++      &tosalcd_device,
+ };
+ static void tosa_poweroff(void)
+Index: git/arch/arm/mach-pxa/Kconfig
+===================================================================
+--- git.orig/arch/arm/mach-pxa/Kconfig 2006-11-07 22:13:10.000000000 +0000
++++ git/arch/arm/mach-pxa/Kconfig      2006-11-07 22:13:10.000000000 +0000
+@@ -129,7 +129,10 @@ config MACH_TOSA
+       bool "Enable Sharp SL-6000x (Tosa) Support"
+       depends PXA_SHARPSL_25x
+       select TOSHIBA_TC6393XB
+-      select SHARPSL_PM       
++      select I2C
++      select I2C_PXA
++      select SHARPSL_PM
++      select PXA_SSP
+ config PXA25x
+       bool
diff --git a/packages/kexecboot/linux-kexecboot-2.6.23/tosa/defconfig b/packages/kexecboot/linux-kexecboot-2.6.23/tosa/defconfig
new file mode 100644 (file)
index 0000000..d005193
--- /dev/null
@@ -0,0 +1,1665 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.16-rc5-git5
+# Tue Mar 14 09:05:26 2006
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ARCH_MTD_XIP=y
+
+#
+# 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 is not set
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG 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_FUTEX=y
+CONFIG_EPOLL=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_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=y
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=m
+CONFIG_IOSCHED_CFQ=m
+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_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=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_MAINSTONE is not set
+# CONFIG_ARCH_PXA_IDP is not set
+CONFIG_PXA_SHARPSL=y
+# CONFIG_MACH_HX2750 is not set
+CONFIG_PXA_SHARPSL_25x=y
+# CONFIG_PXA_SHARPSL_27x is not set
+# CONFIG_MACH_POODLE is not set
+# CONFIG_MACH_CORGI is not set
+# CONFIG_MACH_SHEPHERD is not set
+# CONFIG_MACH_HUSKY is not set
+CONFIG_MACH_TOSA=y
+CONFIG_PXA25x=y
+# CONFIG_PXA_KEYS is not set
+
+#
+# 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
+CONFIG_KEXEC=y
+CONFIG_ATAGS_PROC=y
+CONFIG_SHARP_PARAM=y
+CONFIG_SHARPSL_PM=y
+CONFIG_SHARP_SCOOP=y
+CONFIG_TOSHIBA_TC6393XB=y
+
+#
+# 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_PCMCIA_PXA2XX=y
+
+#
+# Kernel Features
+#
+CONFIG_PREEMPT=y
+CONFIG_NO_IDLE_HZ=y
+# 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_XIP_KERNEL is not set
+
+#
+# CPU Frequency scaling
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+# CONFIG_CPU_FREQ_DEBUG is not set
+CONFIG_CPU_FREQ_STAT=y
+# CONFIG_CPU_FREQ_STAT_DETAILS is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=m
+CONFIG_CPU_FREQ_GOV_USERSPACE=m
+CONFIG_CPU_FREQ_GOV_ONDEMAND=m
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m
+CONFIG_CPU_FREQ_PXA25x=y
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_AOUT=m
+CONFIG_BINFMT_MISC=m
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+CONFIG_APM=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=m
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+CONFIG_NET_KEY=m
+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=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK is not set
+# CONFIG_NF_CONNTRACK_ENABLED is not set
+# CONFIG_NF_CONNTRACK is not set
+
+CONFIG_NETFILTER_XTABLES=m
+# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
+# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
+# CONFIG_NETFILTER_XT_TARGET_MARK is not set
+# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
+# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
+# CONFIG_NETFILTER_XT_TARGET_TRACE is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
+# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
+# CONFIG_NETFILTER_XT_MATCH_ESP is not set
+# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
+# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_MAC is not set
+# CONFIG_NETFILTER_XT_MATCH_MARK is not set
+# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
+# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
+# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
+# CONFIG_NETFILTER_XT_MATCH_REALM is not set
+# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
+# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
+# CONFIG_NETFILTER_XT_MATCH_STRING is not set
+# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_U32 is not set
+# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=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_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=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 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=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 is not set
+# CONFIG_IRDA_FAST_RR is not set
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+# CONFIG_IRTTY_SIR is not set
+
+#
+# Dongle support
+#
+
+#
+# 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=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_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIUSB=m
+# CONFIG_BT_HCIUSB_SCO is not set
+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
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=m
+# 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 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=y
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_SHARP_SL=y
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_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
+
+#
+# NAND Flash Device Drivers
+#
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_VERIFY_WRITE=y
+# CONFIG_MTD_NAND_H1900 is not set
+CONFIG_MTD_NAND_TMIO=y
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP 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=m
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+# 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_IDECS=y
+# 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 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=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 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=y
+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_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=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
+
+#
+# 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=m
+# CONFIG_AIRO_CS is not set
+# CONFIG_PCMCIA_WL3501 is not set
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+# CONFIG_HOSTAP_FIRMWARE_NVRAM is not set
+CONFIG_HOSTAP_CS=m
+CONFIG_NET_WIRELESS=y
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+# CONFIG_PCMCIA_3C589 is not set
+# CONFIG_PCMCIA_3C574 is not set
+# CONFIG_PCMCIA_FMVJ18X is not set
+CONFIG_PCMCIA_PCNET=m
+# CONFIG_PCMCIA_NMCLAN is not set
+# CONFIG_PCMCIA_SMC91C92 is not set
+# CONFIG_PCMCIA_XIRC2PS is not set
+# CONFIG_PCMCIA_AXNET is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+# CONFIG_PPP_MPPE is not set
+# 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=m
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=480
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=640
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+CONFIG_INPUT_POWER=y
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_CORGI is not set
+# CONFIG_KEYBOARD_SPITZ is not set
+CONFIG_KEYBOARD_TOSA=y
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_CORGI 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_TOUCHSCREEN_WM97XX=y
+# CONFIG_TOUCHSCREEN_WM9705 is not set
+CONFIG_TOUCHSCREEN_WM9712=y
+CONFIG_TOUCHSCREEN_TOSA=y
+# CONFIG_TOUCHSCREEN_WM9713 is not set
+# CONFIG_TOUCHSCREEN_WM97XX_PXA is not set
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=m
+
+#
+# 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=m
+CONFIG_SERIAL_8250_CS=m
+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_PXA=y
+CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_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 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_PXA=y
+# CONFIG_I2C_PXA_SLAVE 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
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia Capabilities Port drivers
+#
+
+#
+# Multi-Function Devices
+#
+
+#
+# LED devices
+#
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TOSA=y
+CONFIG_LEDS_TRIGGER_TIMER=m
+CONFIG_LEDS_TRIGGER_IDE_DISK=y
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_VIDEO_V4L2=y
+
+#
+# Video For Linux
+#
+
+#
+# Video Adapters
+#
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_TUNER_3036 is not set
+# CONFIG_VIDEO_EM28XX is not set
+# CONFIG_VIDEO_OVCAMCHIP is not set
+# CONFIG_VIDEO_AUDIO_DECODER is not set
+# CONFIG_VIDEO_DECODER is not set
+
+#
+# Radio Adapters
+#
+# CONFIG_RADIO_MAESTRO is not set
+
+#
+# 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_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_PXA is not set
+# CONFIG_FB_W100 is not set
+CONFIG_FB_TMIO=y
+# 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=y
+CONFIG_FONT_8x8=y
+# CONFIG_FONT_8x16 is not set
+# 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 is not set
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_DEVICE=y
+# CONFIG_LCD_CLASS_DEVICE is not set
+CONFIG_BACKLIGHT_CORGI=y
+# CONFIG_BACKLIGHT_HP680 is not set
+
+#
+# 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 is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+# CONFIG_SND_DYNAMIC_MINORS is not set
+# CONFIG_SND_SUPPORT_OLD_API is not set
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+CONFIG_AC97_BUS=y
+CONFIG_SND_DUMMY=m
+# 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_AC97 is not set
+
+#
+# USB devices
+#
+CONFIG_SND_USB_AUDIO=m
+
+#
+# PCMCIA devices
+#
+
+#
+# SoC audio support
+#
+CONFIG_SND_SOC=y
+
+#
+# Soc Platforms
+#
+
+#
+# SoC Audio for the Intel PXA2xx
+#
+CONFIG_SND_PXA2XX_SOC=y
+CONFIG_SND_PXA2XX_SOC_AC97=y
+# CONFIG_SND_PXA2XX_SOC_MAINSTONE is not set
+# CONFIG_SND_PXA2XX_SOC_MAINSTONE_WM8753 is not set
+# CONFIG_SND_PXA2XX_SOC_MAINSTONE_WM9713 is not set
+# CONFIG_SND_PXA2XX_SOC_MAINSTONE_WM9712 is not set
+# CONFIG_SND_PXA2XX_SOC_CORGI is not set
+# CONFIG_SND_PXA2XX_SOC_SPITZ is not set
+CONFIG_SND_PXA2XX_SOC_TOSA=y
+
+#
+# Soc Codecs
+#
+# CONFIG_SND_SOC_AC97_CODEC is not set
+# CONFIG_SND_SOC_WM8731 is not set
+# CONFIG_SND_SOC_WM8750 is not set
+# CONFIG_SND_SOC_WM8753 is not set
+# CONFIG_SND_SOC_WM8772 is not set
+# CONFIG_SND_SOC_WM8971 is not set
+# CONFIG_SND_SOC_WM9713 is not set
+CONFIG_SND_SOC_WM9712=y
+# CONFIG_SND_SOC_UDA1380 is not set
+# CONFIG_SND_SOC_AK4535 is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=m
+
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_SL811_HCD=m
+CONFIG_USB_SL811_CS=m
+
+#
+# USB Device Class drivers
+#
+# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_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=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_MTOUCH=m
+# CONFIG_USB_ITMTOUCH is not set
+CONFIG_USB_EGALAX=m
+# 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 Multimedia devices
+#
+CONFIG_USB_DABUSB=m
+CONFIG_USB_VICAM=m
+CONFIG_USB_DSBR=m
+# CONFIG_USB_ET61X251 is not set
+CONFIG_USB_IBMCAM=m
+CONFIG_USB_KONICAWC=m
+CONFIG_USB_OV511=m
+CONFIG_USB_SE401=m
+CONFIG_USB_SN9C102=m
+CONFIG_USB_STV680=m
+# CONFIG_USB_PWC is not set
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET=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 is not set
+# CONFIG_USB_NET_CDC_SUBSET is not set
+# CONFIG_USB_NET_ZAURUS is not set
+# 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=m
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+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_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 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_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_TI=m
+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=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_CYTHERM=m
+CONFIG_USB_PHIDGETKIT=m
+CONFIG_USB_PHIDGETSERVO=m
+CONFIG_USB_IDMOUSE=m
+# 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=y
+# CONFIG_USB_PXA2XX_SMALL is not set
+# CONFIG_USB_GADGET_PXA27X is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+# CONFIG_USB_GADGET_DUALSPEED is not set
+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=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_PXA=y
+CONFIG_MMC_UNSAFE_RESUME=y
+
+#
+# Real Time Clock
+#
+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_SA1100=y
+# CONFIG_RTC_DRV_TEST 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=m
+# 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=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+# 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_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_RAMFS is not set
+# CONFIG_RELAYFS_FS is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+CONFIG_JFFS2_RUBIN=y
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+CONFIG_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 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=y
+# 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_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+CONFIG_SMB_NLS_DEFAULT=y
+CONFIG_SMB_NLS_REMOTE="cp437"
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_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 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="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_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+CONFIG_TIMER_STATS=y
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_PREEMPT is not set
+# 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 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_FORCED_INLINING is not set
+# 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_ALGAPI=m
+CONFIG_CRYPTO_HMAC=m
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+# CONFIG_CRYPTO_TGR192 is not set
+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=m
+
+#
+# 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
+CONFIG_GENERIC_ALLOCATOR=y
+# CONFIG_SHARPSL_RC is not set
diff --git a/packages/kexecboot/linux-kexecboot-2.6.23/tosa_udc_use_gpio_vbus.patch b/packages/kexecboot/linux-kexecboot-2.6.23/tosa_udc_use_gpio_vbus.patch
new file mode 100644 (file)
index 0000000..ca98926
--- /dev/null
@@ -0,0 +1,100 @@
+From dbaryshkov@gmail.com Fri Dec  7 00:07:07 2007
+Return-Path: <SRS0=x/UTRF0x=Q6=lists.arm.linux.org.uk=linux-arm-kernel-bounces+openembedded=haerwu.biz@haerwu.biz>
+X-Spam-Checker-Version: SpamAssassin 3.1.7 (2006-10-05) on 3073.s.tld.pl
+X-Spam-Level: 
+X-Spam-Status: No, score=-1.5 required=5.0 tests=BAYES_00,SPF_FAIL 
+       autolearn=disabled version=3.1.7
+Delivered-To: haerwu.biz-marcin@haerwu.biz
+Received: (qmail 27813 invoked by uid 813007); 7 Dec 2007 00:02:29 -0000
+Delivered-To: haerwu.biz-openembedded@haerwu.biz
+Received: (qmail 27803 invoked by uid 813007); 7 Dec 2007 00:02:28 -0000
+X-clamdmail: clamdmail 0.18a
+Received: from zeniv.linux.org.uk (195.92.253.2)
+  by smtp.host4.kei.pl with SMTP; 7 Dec 2007 00:02:28 -0000
+Received: from [2002:4e20:1eda:1:201:3dff:fe00:156] (helo=lists.arm.linux.org.uk)
+       by ZenIV.linux.org.uk with esmtpsa (Exim 4.63 #1 (Red Hat Linux))
+       id 1J0Q9g-0005Vf-7a; Thu, 06 Dec 2007 23:29:23 +0000
+Received: from localhost ([127.0.0.1] helo=lists.arm.linux.org.uk)
+       by lists.arm.linux.org.uk with esmtp (Exim 4.50)
+       id 1J0Pvo-0000d6-NY; Thu, 06 Dec 2007 23:15:02 +0000
+Received: from ug-out-1314.google.com ([66.249.92.171])
+       by lists.arm.linux.org.uk with esmtp (Exim 4.50) id 1J0PoR-0000bz-SM
+       for linux-arm-kernel@lists.arm.linux.org.uk;
+       Thu, 06 Dec 2007 23:10:07 +0000
+Received: by ug-out-1314.google.com with SMTP id 29so955850ugc
+       for <linux-arm-kernel@lists.arm.linux.org.uk>;
+       Thu, 06 Dec 2007 15:07:14 -0800 (PST)
+DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma;
+       h=domainkey-signature:received:received:date:to:subject:message-id:mime-version:content-type:content-disposition:user-agent:from;
+       bh=kjQKYxTmbZXtFO0UaAnYmPE6Fk1iyXNHPNOw6H2kP6U=;
+       b=vpDrUZqfbWhRrhxvozaHlI9ZC2UwfZvkqIrEeyX5rmqM9rXJTkm1fQQUJvaw43KzvEmxqPXYvpvHQ663HaRRVtN08xB0t2NcDpTm20QUwznzUbze+c4FPTP+86FQbsfhCck86qmrvfBUoDVD1xS2eVR+MxwI63D3rapCtUNpvvo=
+DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma;
+       h=date:to:subject:message-id:mime-version:content-type:content-disposition:user-agent:from;
+       b=D4Cx347bDXn3mf7g77jwn0W3XSXIZh+CiEev1FGhlTeKRZhnM7x1ht4Z+57AiD/dMCrCq8lHqE8Gy0Rv7x7krF2bmUJaiO7HXfxmLWY+msGF2nTymkr1NKsqipQRIVCcEf0ZBKcIrT0dK94QhuP4Ea4Sb/YOfb2YwrJPyNWsISo=
+Received: by 10.78.165.16 with SMTP id n16mr3075565hue.1196982433587;
+       Thu, 06 Dec 2007 15:07:13 -0800 (PST)
+Received: from doriath.ww600.siemens.net ( [91.122.9.34])
+       by mx.google.com with ESMTPS id k5sm5631nfh.2007.12.06.15.07.12
+       (version=SSLv3 cipher=OTHER); Thu, 06 Dec 2007 15:07:12 -0800 (PST)
+Date: Fri, 7 Dec 2007 02:07:07 +0300
+To: linux-arm-kernel@lists.arm.linux.org.uk
+Message-ID: <20071206230707.GA13639@doriath.ww600.siemens.net>
+MIME-Version: 1.0
+Content-Type: text/plain;
+  charset=us-ascii
+Content-Disposition: inline
+User-Agent: Mutt/1.5.17 (2007-11-01)
+From: Dmitry Baryshkov <dbaryshkov@gmail.com>
+Subject: [PATCH 2/2] tosa_udc_use_gpio_vbus.patch
+X-BeenThere: linux-arm-kernel@lists.arm.linux.org.uk
+X-Mailman-Version: 2.1.5
+Precedence: list
+List-Id: ARM Linux kernel discussions <linux-arm-kernel.lists.arm.linux.org.uk>
+List-Unsubscribe: <http://lists.arm.linux.org.uk/mailman/listinfo/linux-arm-kernel>,
+       <mailto:linux-arm-kernel-request@lists.arm.linux.org.uk?subject=unsubscribe>
+List-Archive: <http://lists.arm.linux.org.uk/pipermail/linux-arm-kernel>
+List-Post: <mailto:linux-arm-kernel@lists.arm.linux.org.uk>
+List-Help: <mailto:linux-arm-kernel-request@lists.arm.linux.org.uk?subject=help>
+List-Subscribe: <http://lists.arm.linux.org.uk/mailman/listinfo/linux-arm-kernel>,
+       <mailto:linux-arm-kernel-request@lists.arm.linux.org.uk?subject=subscribe>
+Sender: linux-arm-kernel-bounces@lists.arm.linux.org.uk
+Errors-To: linux-arm-kernel-bounces+openembedded=haerwu.biz+openembedded=haerwu.biz@lists.arm.linux.org.uk
+X-Length: 4865
+Status: R
+X-Status: NC
+X-KMail-EncryptionState:  
+X-KMail-SignatureState:  
+X-KMail-MDN-Sent:  
+
+Use gpio_vbus instead of udc_is_connected for udc on tosa.
+
+Signed-off-by: Dmitry Baryshkov <dbaryshkov@gmail.com>
+
+Index: linux-test/arch/arm/mach-pxa/tosa.c
+===================================================================
+--- linux-test.orig/arch/arm/mach-pxa/tosa.c   2007-12-06 12:43:04.301350179 +0300
++++ linux-test/arch/arm/mach-pxa/tosa.c        2007-12-06 12:47:50.881381650 +0300
+@@ -165,15 +165,10 @@ static void tosa_udc_command(int cmd)
+       }
+ }
+-static int tosa_udc_is_connected(void)
+-{
+-      return ((GPLR(TOSA_GPIO_USB_IN) & GPIO_bit(TOSA_GPIO_USB_IN)) == 0);
+-}
+-
+-
+ static struct pxa2xx_udc_mach_info udc_info __initdata = {
+       .udc_command            = tosa_udc_command,
+-      .udc_is_connected       = tosa_udc_is_connected,
++      .gpio_vbus              = TOSA_GPIO_USB_IN,
++      .gpio_vbus_inverted     = 1,
+ };
+ /*
+
+-------------------------------------------------------------------
+List admin: http://lists.arm.linux.org.uk/mailman/listinfo/linux-arm-kernel
+FAQ:        http://www.arm.linux.org.uk/mailinglists/faq.php
+Etiquette:  http://www.arm.linux.org.uk/mailinglists/etiquette.php
+
diff --git a/packages/kexecboot/linux-kexecboot-2.6.23/usb-ohci-hooks-r3.patch b/packages/kexecboot/linux-kexecboot-2.6.23/usb-ohci-hooks-r3.patch
new file mode 100644 (file)
index 0000000..08f4f15
--- /dev/null
@@ -0,0 +1,47 @@
+Signed-off-by: Dmitry Baryshkov <dbaryshkov@gmail.com>
+Index: linux-2.6.23/drivers/usb/host/ohci-hcd.c
+===================================================================
+--- linux-2.6.23.orig/drivers/usb/host/ohci-hcd.c      2007-11-12 12:36:12.598560065 +0300
++++ linux-2.6.23/drivers/usb/host/ohci-hcd.c   2007-11-12 12:36:16.614310504 +0300
+@@ -930,6 +930,7 @@
+       !defined(PLATFORM_DRIVER) &&    \
+       !defined(OF_PLATFORM_DRIVER) && \
+       !defined(SA1111_DRIVER) &&      \
++      !defined(DEVICE_DRIVER) &&      \
+       !defined(PS3_SYSTEM_BUS_DRIVER)
+ #error "missing bus glue for ohci-hcd"
+ #endif
+@@ -969,6 +970,12 @@
+               goto error_sa1111;
+ #endif
++#ifdef DEVICE_DRIVER
++      retval = driver_register(&DEVICE_DRIVER);
++      if (retval < 0)
++              goto error_device;
++#endif
++
+ #ifdef PCI_DRIVER
+       retval = pci_register_driver(&PCI_DRIVER);
+       if (retval < 0)
+@@ -981,6 +988,10 @@
+ #ifdef PCI_DRIVER
+  error_pci:
+ #endif
++#ifdef DEVICE_DRIVER
++ error_device:
++      driver_unregister(&DEVICE_DRIVER);
++#endif
+ #ifdef SA1111_DRIVER
+       sa1111_driver_unregister(&SA1111_DRIVER);
+  error_sa1111:
+@@ -1006,6 +1017,9 @@
+ #ifdef PCI_DRIVER
+       pci_unregister_driver(&PCI_DRIVER);
+ #endif
++#ifdef DEVICE_DRIVER
++      driver_unregister(&DEVICE_DRIVER);
++#endif
+ #ifdef SA1111_DRIVER
+       sa1111_driver_unregister(&SA1111_DRIVER);
+ #endif
diff --git a/packages/kexecboot/linux-kexecboot-2.6.23/uvesafb-0.1-rc3-2.6.22.patch b/packages/kexecboot/linux-kexecboot-2.6.23/uvesafb-0.1-rc3-2.6.22.patch
new file mode 100644 (file)
index 0000000..7113751
--- /dev/null
@@ -0,0 +1,2590 @@
+---
+ Documentation/fb/uvesafb.txt |  188 +++
+ drivers/video/Kconfig        |   18 
+ drivers/video/Makefile       |    1 
+ drivers/video/modedb.c       |   28 
+ drivers/video/uvesafb.c      | 2058 +++++++++++++++++++++++++++++++++++++++++++
+ include/linux/connector.h    |    7 
+ include/video/Kbuild         |    2 
+ include/video/uvesafb.h      |  193 ++++
+ 8 files changed, 2479 insertions(+), 16 deletions(-)
+
+Index: linux-2.6.22/Documentation/fb/uvesafb.txt
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/Documentation/fb/uvesafb.txt  2007-08-28 21:56:34.000000000 +0100
+@@ -0,0 +1,188 @@
++
++uvesafb - A Generic Driver for VBE2+ compliant video cards
++==========================================================
++
++1. Requirements
++---------------
++
++uvesafb should work with any video card that has a Video BIOS compliant
++with the VBE 2.0 standard.
++
++Unlike other drivers, uvesafb makes use of a userspace helper called
++v86d.  v86d is used to run the x86 Video BIOS code in a simulated and
++controlled environment.  This allows uvesafb to function on arches other
++than x86.  Check the v86d documentation for a list of currently supported
++arches.
++
++v86d source code can be downloaded from the following website:
++  http://dev.gentoo.org/~spock/projects/uvesafb
++
++Please refer to the v86d documentation for detailed configuration and
++installation instructions.
++
++Note that the v86d userspace helper has to be available at all times in
++order for uvesafb to work properly.  If you want to use uvesafb during
++early boot, you will have to include v86d into an initramfs image, and
++either compile it into the kernel or use it as an initrd.
++
++2. Caveats and limitations
++--------------------------
++
++uvesafb is a _generic_ driver which supports a wide variety of video
++cards, but which is ultimately limited by the Video BIOS interface.
++The most important limitations are:
++
++- Lack of any type of acceleration.
++- A strict and limited set of supported video modes.  Often the native
++  or most optimal resolution/refresh rate for your setup will not work
++  with uvesafb, simply because the Video BIOS doesn't support the
++  video mode you want to use.  This can be especially painful with
++  widescreen panels, where native video modes don't have the 4:3 aspect
++  ratio, which is what most BIOS-es are limited to.
++- Adjusting the refresh rate is only possible with a VBE 3.0 compliant
++  Video BIOS.  Note that many nVidia Video BIOS-es claim to be VBE 3.0
++  compliant, while they simply ignore any refresh rate settings.
++
++3. Configuration
++----------------
++
++uvesafb can be compiled either as a module, or directly into the kernel.
++In both cases it supports the same set of configuration options, which
++are either given on the kernel command line or as module parameters, e.g.:
++
++ video=uvesafb:1024x768-32,mtrr:3,ywrap (compiled into the kernel)
++
++ # modprobe uvesafb mode=1024x768-32 mtrr=3 scroll=ywrap  (module)
++
++Accepted options:
++
++ypan    Enable display panning using the VESA protected mode
++        interface.  The visible screen is just a window of the
++        video memory, console scrolling is done by changing the
++        start of the window.  Available on x86 only.
++
++ywrap   Same as ypan, but assumes your gfx board can wrap-around
++        the video memory (i.e. starts reading from top if it
++        reaches the end of video memory).  Faster than ypan.
++              Available on x86 only.
++
++redraw  Scroll by redrawing the affected part of the screen, this
++        is the safe (and slow) default.
++
++(If you're using uvesafb as a module, the above three options are
++ used a parameter of the scroll option, e.g. scroll=ypan.)
++
++vgapal  Use the standard VGA registers for palette changes.
++
++pmipal  Use the protected mode interface for palette changes.
++        This is the default if the protected mode interface is
++        available.  Available on x86 only.
++
++mtrr:n  Setup memory type range registers for the framebuffer
++        where n:
++              0 - disabled (equivalent to nomtrr) (default)
++              1 - uncachable
++              2 - write-back
++              3 - write-combining
++              4 - write-through
++
++        If you see the following in dmesg, choose the type that matches
++        the old one.  In this example, use "mtrr:2".
++...
++mtrr: type mismatch for e0000000,8000000 old: write-back new: write-combining
++...
++
++nomtrr  Do not use memory type range registers.
++
++vremap:n
++        Remap 'n' MiB of video RAM.  If 0 or not specified, remap memory
++        according to video mode.
++
++vtotal:n
++        If the video BIOS of your card incorrectly determines the total
++        amount of video RAM, use this option to override the BIOS (in MiB).
++
++<mode>  The mode you want to set, in the standard modedb format.  Refer to
++        modedb.txt for a detailed description.  When uvesafb is compiled as
++        a module, the mode string should be provided as a value of the
++        'mode' option.
++
++vbemode:x
++        Force the use of VBE mode x.  The mode will only be set if it's
++        found in the VBE-provided list of supported modes.
++        NOTE: The mode number 'x' should be specified in VESA mode number
++        notation, not the Linux kernel one (eg. 257 instead of 769).
++        HINT: If you use this option because normal <mode> parameter does
++        not work for you and you use a X server, you'll probably want to
++        set the 'nocrtc' option to ensure that the video mode is properly
++        restored after console <-> X switches.
++
++nocrtc  Do not use CRTC timings while setting the video mode.  This option
++        has any effect only if the Video BIOS is VBE 3.0 compliant.  Use it
++        if you have problems with modes set the standard way.  Note that
++        using this option implies that any refresh rate adjustments will
++        be ignored and the refresh rate will stay at your BIOS default (60 Hz).
++
++noedid  Do not try to fetch and use EDID-provided modes.
++
++noblank Disable hardware blanking.
++
++v86d:path
++        Set path to the v86d executable. This option is only available as
++        a module parameter, and not as a part of the video= string.  If you
++        need to use it and have uvesafb built into the kernel, use
++        uvesafb.v86d="path".
++
++Additionally, the following parameters may be provided.  They all override the
++EDID-provided values and BIOS defaults.  Refer to your monitor's specs to get
++the correct values for maxhf, maxvf and maxclk for your hardware.
++
++maxhf:n     Maximum horizontal frequency (in kHz).
++maxvf:n     Maximum vertical frequency (in Hz).
++maxclk:n    Maximum pixel clock (in MHz).
++
++4. The sysfs interface
++----------------------
++
++uvesafb provides several sysfs nodes for configurable parameters and
++additional information.
++
++Driver attributes:
++
++/sys/bus/platform/drivers/uvesafb
++  - v86d (default: /sbin/v86d)
++    Path to the v86d executable. v86d is started by uvesafb
++    if an instance of the daemon isn't already running.
++
++Device attributes:
++
++/sys/bus/platform/drivers/uvesafb/uvesafb.0
++  - nocrtc
++    Use the default refresh rate (60 Hz) if set to 1.
++
++  - oem_product_name
++  - oem_product_rev
++  - oem_string
++  - oem_vendor
++    Information about the card and its maker.
++
++  - vbe_modes
++    A list of video modes supported by the Video BIOS along with their
++    VBE mode numbers in hex.
++
++  - vbe_version
++    A BCD value indicating the implemented VBE standard.
++
++5. Miscellaneous
++----------------
++
++Uvesafb will set a video mode with the default refresh rate and timings
++from the Video BIOS if you set pixclock to 0 in fb_var_screeninfo.
++
++
++--
++ Michal Januszewski <spock@gentoo.org>
++ Last updated: 2007-06-16
++
++ Documentation of the uvesafb options is loosely based on vesafb.txt.
++
+Index: linux-2.6.22/drivers/video/Kconfig
+===================================================================
+--- linux-2.6.22.orig/drivers/video/Kconfig    2007-08-28 21:56:33.000000000 +0100
++++ linux-2.6.22/drivers/video/Kconfig 2007-08-28 21:56:34.000000000 +0100
+@@ -592,6 +592,24 @@ config FB_TGA
+         Say Y if you have one of those.
++config FB_UVESA
++      tristate "Userspace VESA VGA graphics support"
++      depends on FB && CONNECTOR
++      select FB_CFB_FILLRECT
++      select FB_CFB_COPYAREA
++      select FB_CFB_IMAGEBLIT
++      select FB_MODE_HELPERS
++      help
++        This is the frame buffer driver for generic VBE 2.0 compliant
++        graphic cards. It can also take advantage of VBE 3.0 features,
++        such as refresh rate adjustment.
++
++        This driver generally provides more features than vesafb but
++        requires a userspace helper application called 'v86d'. See
++        <file:Documentation/fb/uvesafb.txt> for more information.
++
++        If unsure, say N.
++
+ config FB_VESA
+       bool "VESA VGA graphics support"
+       depends on (FB = y) && X86
+Index: linux-2.6.22/drivers/video/Makefile
+===================================================================
+--- linux-2.6.22.orig/drivers/video/Makefile   2007-08-28 21:56:33.000000000 +0100
++++ linux-2.6.22/drivers/video/Makefile        2007-08-28 21:56:34.000000000 +0100
+@@ -116,6 +116,7 @@ obj-$(CONFIG_FB_XILINX)           += xil
+ obj-$(CONFIG_FB_OMAP)             += omap/
+ # Platform or fallback drivers go here
++obj-$(CONFIG_FB_UVESA)            += uvesafb.o
+ obj-$(CONFIG_FB_VESA)             += vesafb.o
+ obj-$(CONFIG_FB_IMAC)             += imacfb.o
+ obj-$(CONFIG_FB_VGA16)            += vga16fb.o
+Index: linux-2.6.22/drivers/video/modedb.c
+===================================================================
+--- linux-2.6.22.orig/drivers/video/modedb.c   2007-08-28 21:54:13.000000000 +0100
++++ linux-2.6.22/drivers/video/modedb.c        2007-08-28 21:56:34.000000000 +0100
+@@ -606,26 +606,29 @@ done:
+       DPRINTK("Trying specified video mode%s %ix%i\n",
+           refresh_specified ? "" : " (ignoring refresh rate)", xres, yres);
+-      diff = refresh;
++      if (!refresh_specified)
++              diff = 0;
++      else
++              diff = refresh;
++
+       best = -1;
+       for (i = 0; i < dbsize; i++) {
+-              if (name_matches(db[i], name, namelen) ||
+-                  (res_specified && res_matches(db[i], xres, yres))) {
+-                      if(!fb_try_mode(var, info, &db[i], bpp)) {
+-                              if(!refresh_specified || db[i].refresh == refresh)
+-                                      return 1;
+-                              else {
+-                                      if(diff > abs(db[i].refresh - refresh)) {
+-                                              diff = abs(db[i].refresh - refresh);
+-                                              best = i;
+-                                      }
++              if ((name_matches(db[i], name, namelen) ||
++                  (res_specified && res_matches(db[i], xres, yres))) &&
++                  !fb_try_mode(var, info, &db[i], bpp)) {
++                      if (refresh_specified && db[i].refresh == refresh) {
++                              return 1;
++                      } else {
++                              if (diff < db[i].refresh) {
++                                      diff = db[i].refresh;
++                                      best = i;
+                               }
+                       }
+               }
+       }
+       if (best != -1) {
+               fb_try_mode(var, info, &db[best], bpp);
+-              return 2;
++              return (refresh_specified) ? 2 : 1;
+       }
+       diff = xres + yres;
+@@ -938,6 +941,7 @@ void fb_destroy_modelist(struct list_hea
+               kfree(pos);
+       }
+ }
++EXPORT_SYMBOL_GPL(fb_destroy_modelist);
+ /**
+  * fb_videomode_to_modelist: convert mode array to mode list
+Index: linux-2.6.22/drivers/video/uvesafb.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/drivers/video/uvesafb.c       2007-08-28 21:56:34.000000000 +0100
+@@ -0,0 +1,2058 @@
++/*
++ * A framebuffer driver for VBE 2.0+ compliant video cards
++ *
++ * (c) 2007 Michal Januszewski <spock@gentoo.org>
++ *     Loosely based upon the vesafb driver.
++ *
++ */
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/skbuff.h>
++#include <linux/timer.h>
++#include <linux/completion.h>
++#include <linux/connector.h>
++#include <linux/random.h>
++#include <linux/platform_device.h>
++#include <linux/limits.h>
++#include <linux/fb.h>
++#include <linux/io.h>
++#include <linux/mutex.h>
++#include <video/edid.h>
++#include <video/vga.h>
++#include <video/uvesafb.h>
++#ifdef CONFIG_MTRR
++#include <asm/mtrr.h>
++#endif
++#include "edid.h"
++
++static struct cb_id uvesafb_cn_id = {
++      .idx = CN_IDX_V86D,
++      .val = CN_VAL_V86D_UVESAFB
++};
++static char v86d_path[PATH_MAX] = "/sbin/v86d";
++static char v86d_started;     /* has v86d been started by uvesafb? */
++
++static struct fb_fix_screeninfo uvesafb_fix __devinitdata = {
++      .id     = "VESA VGA",
++      .type   = FB_TYPE_PACKED_PIXELS,
++      .accel  = FB_ACCEL_NONE,
++      .visual = FB_VISUAL_TRUECOLOR,
++};
++
++static int mtrr               __devinitdata = 3; /* enable mtrr by default */
++static int blank      __devinitdata = 1; /* enable blanking by default */
++static int ypan               __devinitdata = 1; /* 0: scroll, 1: ypan, 2: ywrap */
++static int pmi_setpal __devinitdata = 1; /* use PMI for palette changes */
++static int nocrtc     __devinitdata; /* ignore CRTC settings */
++static int noedid     __devinitdata; /* don't try DDC transfers */
++static int vram_remap __devinitdata; /* set amt. of memory to be used */
++static int vram_total __devinitdata; /* set total amount of memory */
++static u16 maxclk     __devinitdata; /* maximum pixel clock */
++static u16 maxvf      __devinitdata; /* maximum vertical frequency */
++static u16 maxhf      __devinitdata; /* maximum horizontal frequency */
++static u16 vbemode    __devinitdata; /* force use of a specific VBE mode */
++static char *mode_option __devinitdata;
++
++static struct uvesafb_ktask *uvfb_tasks[UVESAFB_TASKS_MAX];
++static DEFINE_MUTEX(uvfb_lock);
++
++/*
++ * A handler for replies from userspace.
++ *
++ * Make sure each message passes consistency checks and if it does,
++ * find the kernel part of the task struct, copy the registers and
++ * the buffer contents and then complete the task.
++ */
++static void uvesafb_cn_callback(void *data)
++{
++      struct cn_msg *msg = data;
++      struct uvesafb_task *utask;
++      struct uvesafb_ktask *task;
++
++      if (msg->seq >= UVESAFB_TASKS_MAX)
++              return;
++
++      mutex_lock(&uvfb_lock);
++      task = uvfb_tasks[msg->seq];
++
++      if (!task || msg->ack != task->ack) {
++              mutex_unlock(&uvfb_lock);
++              return;
++      }
++
++      utask = (struct uvesafb_task *)msg->data;
++
++      /* Sanity checks for the buffer length. */
++      if (task->t.buf_len < utask->buf_len ||
++          utask->buf_len > msg->len - sizeof(*utask)) {
++              mutex_unlock(&uvfb_lock);
++              return;
++      }
++
++      uvfb_tasks[msg->seq] = NULL;
++      mutex_unlock(&uvfb_lock);
++
++      memcpy(&task->t, utask, sizeof(*utask));
++
++      if (task->t.buf_len && task->buf)
++              memcpy(task->buf, utask + 1, task->t.buf_len);
++
++      complete(task->done);
++      return;
++}
++
++static int uvesafb_helper_start(void)
++{
++      char *envp[] = {
++              "HOME=/",
++              "PATH=/sbin:/bin",
++              NULL,
++      };
++
++      char *argv[] = {
++              v86d_path,
++              NULL,
++      };
++
++      return call_usermodehelper(v86d_path, argv, envp, 1);
++}
++
++/*
++ * Execute a uvesafb task.
++ *
++ * Returns 0 if the task is executed successfully.
++ *
++ * A message sent to the userspace consists of the uvesafb_task
++ * struct and (optionally) a buffer. The uvesafb_task struct is
++ * a simplified version of uvesafb_ktask (its kernel counterpart)
++ * containing only the register values, flags and the length of
++ * the buffer.
++ *
++ * Each message is assigned a sequence number (increased linearly)
++ * and a random ack number. The sequence number is used as a key
++ * for the uvfb_tasks array which holds pointers to uvesafb_ktask
++ * structs for all requests.
++ */
++static int uvesafb_exec(struct uvesafb_ktask *task)
++{
++      static int seq;
++      struct cn_msg *m;
++      int err;
++      int len = sizeof(task->t) + task->t.buf_len;
++
++      /*
++       * Check whether the message isn't longer than the maximum
++       * allowed by connector.
++       */
++      if (sizeof(*m) + len > CONNECTOR_MAX_MSG_SIZE) {
++              printk(KERN_WARNING "uvesafb: message too long (%d), "
++                      "can't execute task\n", (int)(sizeof(*m) + len));
++              return -E2BIG;
++      }
++
++      m = kzalloc(sizeof(*m) + len, GFP_KERNEL);
++      if (!m)
++              return -ENOMEM;
++
++      init_completion(task->done);
++
++      memcpy(&m->id, &uvesafb_cn_id, sizeof(m->id));
++      m->seq = seq;
++      m->len = len;
++      m->ack = random32();
++
++      /* uvesafb_task structure */
++      memcpy(m + 1, &task->t, sizeof(task->t));
++
++      /* Buffer */
++      memcpy((u8 *)(m + 1) + sizeof(task->t), task->buf, task->t.buf_len);
++
++      /*
++       * Save the message ack number so that we can find the kernel
++       * part of this task when a reply is received from userspace.
++       */
++      task->ack = m->ack;
++
++      mutex_lock(&uvfb_lock);
++
++      /* If all slots are taken -- bail out. */
++      if (uvfb_tasks[seq]) {
++              mutex_unlock(&uvfb_lock);
++              return -EBUSY;
++      }
++
++      /* Save a pointer to the kernel part of the task struct. */
++      uvfb_tasks[seq] = task;
++      mutex_unlock(&uvfb_lock);
++
++      err = cn_netlink_send(m, 0, gfp_any());
++      if (err == -ESRCH) {
++              /*
++               * Try to start the userspace helper if sending
++               * the request failed the first time.
++               */
++              err = uvesafb_helper_start();
++              if (err) {
++                      printk(KERN_ERR "uvesafb: failed to execute %s\n",
++                                      v86d_path);
++                      printk(KERN_ERR "uvesafb: make sure that the v86d "
++                                      "helper is installed and executable\n");
++              } else {
++                      v86d_started = 1;
++                      err = cn_netlink_send(m, 0, gfp_any());
++              }
++      }
++      kfree(m);
++
++      if (!err && !(task->t.flags & TF_EXIT))
++              err = !wait_for_completion_timeout(task->done,
++                              msecs_to_jiffies(UVESAFB_TIMEOUT));
++
++      mutex_lock(&uvfb_lock);
++      uvfb_tasks[seq] = NULL;
++      mutex_unlock(&uvfb_lock);
++
++      seq++;
++      if (seq >= UVESAFB_TASKS_MAX)
++              seq = 0;
++
++      return err;
++}
++
++/*
++ * Free a uvesafb_ktask struct.
++ */
++static void uvesafb_free(struct uvesafb_ktask *task)
++{
++      if (task) {
++              if (task->done)
++                      kfree(task->done);
++              kfree(task);
++      }
++}
++
++/*
++ * Prepare a uvesafb_ktask struct to be used again.
++ */
++static void uvesafb_reset(struct uvesafb_ktask *task)
++{
++      struct completion *cpl = task->done;
++
++      memset(task, 0, sizeof(*task));
++      task->done = cpl;
++}
++
++/*
++ * Allocate and prepare a uvesafb_ktask struct.
++ */
++static struct uvesafb_ktask *uvesafb_prep(void)
++{
++      struct uvesafb_ktask *task;
++
++      task = kzalloc(sizeof(*task), GFP_KERNEL);
++      if (task) {
++              task->done = kzalloc(sizeof(*task->done), GFP_KERNEL);
++              if (!task->done) {
++                      kfree(task);
++                      task = NULL;
++              }
++      }
++      return task;
++}
++
++static void uvesafb_setup_var(struct fb_var_screeninfo *var,
++              struct fb_info *info, struct vbe_mode_ib *mode)
++{
++      struct uvesafb_par *par = info->par;
++
++      var->vmode = FB_VMODE_NONINTERLACED;
++      var->sync = FB_SYNC_VERT_HIGH_ACT;
++
++      var->xres = mode->x_res;
++      var->yres = mode->y_res;
++      var->xres_virtual = mode->x_res;
++      var->yres_virtual = (par->ypan) ?
++                      info->fix.smem_len / mode->bytes_per_scan_line :
++                      mode->y_res;
++      var->xoffset = 0;
++      var->yoffset = 0;
++      var->bits_per_pixel = mode->bits_per_pixel;
++
++      if (var->bits_per_pixel == 15)
++              var->bits_per_pixel = 16;
++
++      if (var->bits_per_pixel > 8) {
++              var->red.offset    = mode->red_off;
++              var->red.length    = mode->red_len;
++              var->green.offset  = mode->green_off;
++              var->green.length  = mode->green_len;
++              var->blue.offset   = mode->blue_off;
++              var->blue.length   = mode->blue_len;
++              var->transp.offset = mode->rsvd_off;
++              var->transp.length = mode->rsvd_len;
++      } else {
++              var->red.offset    = 0;
++              var->green.offset  = 0;
++              var->blue.offset   = 0;
++              var->transp.offset = 0;
++
++              /*
++               * We're assuming that we can switch the DAC to 8 bits. If
++               * this proves to be incorrect, we'll update the fields
++               * later in set_par().
++               */
++              if (par->vbe_ib.capabilities & VBE_CAP_CAN_SWITCH_DAC) {
++                      var->red.length    = 8;
++                      var->green.length  = 8;
++                      var->blue.length   = 8;
++                      var->transp.length = 0;
++              } else {
++                      var->red.length    = 6;
++                      var->green.length  = 6;
++                      var->blue.length   = 6;
++                      var->transp.length = 0;
++              }
++      }
++}
++
++static int uvesafb_vbe_find_mode(struct uvesafb_par *par,
++              int xres, int yres, int depth, unsigned char flags)
++{
++      int i, match = -1, h = 0, d = 0x7fffffff;
++
++      for (i = 0; i < par->vbe_modes_cnt; i++) {
++              h = abs(par->vbe_modes[i].x_res - xres) +
++                  abs(par->vbe_modes[i].y_res - yres) +
++                  abs(depth - par->vbe_modes[i].depth);
++
++              /*
++               * We have an exact match in terms of resolution
++               * and depth.
++               */
++              if (h == 0)
++                      return i;
++
++              if (h < d || (h == d && par->vbe_modes[i].depth > depth)) {
++                      d = h;
++                      match = i;
++              }
++      }
++      i = 1;
++
++      if (flags & UVESAFB_EXACT_DEPTH &&
++                      par->vbe_modes[match].depth != depth)
++              i = 0;
++
++      if (flags & UVESAFB_EXACT_RES && d > 24)
++              i = 0;
++
++      if (i != 0)
++              return match;
++      else
++              return -1;
++}
++
++static u8 *uvesafb_vbe_state_save(struct uvesafb_par *par)
++{
++      struct uvesafb_ktask *task;
++      u8 *state;
++      int err;
++
++      if (!par->vbe_state_size)
++              return NULL;
++
++      state = kmalloc(par->vbe_state_size, GFP_KERNEL);
++      if (!state)
++              return NULL;
++
++      task = uvesafb_prep();
++      if (!task) {
++              kfree(state);
++              return NULL;
++      }
++
++      task->t.regs.eax = 0x4f04;
++      task->t.regs.ecx = 0x000f;
++      task->t.regs.edx = 0x0001;
++      task->t.flags = TF_BUF_RET | TF_BUF_ESBX;
++      task->t.buf_len = par->vbe_state_size;
++      task->buf = state;
++      err = uvesafb_exec(task);
++
++      if (err || (task->t.regs.eax & 0xffff) != 0x004f) {
++              printk(KERN_WARNING "uvesafb: VBE get state call "
++                              "failed (eax=0x%x, err=%d)\n",
++                              task->t.regs.eax, err);
++              kfree(state);
++              state = NULL;
++      }
++
++      uvesafb_free(task);
++      return state;
++}
++
++static void uvesafb_vbe_state_restore(struct uvesafb_par *par, u8 *state_buf)
++{
++      struct uvesafb_ktask *task;
++      int err;
++
++      if (!state_buf)
++              return;
++
++      task = uvesafb_prep();
++      if (!task)
++              return;
++
++      task->t.regs.eax = 0x4f04;
++      task->t.regs.ecx = 0x000f;
++      task->t.regs.edx = 0x0002;
++      task->t.buf_len = par->vbe_state_size;
++      task->t.flags = TF_BUF_ESBX;
++      task->buf = state_buf;
++
++      err = uvesafb_exec(task);
++      if (err || (task->t.regs.eax & 0xffff) != 0x004f)
++              printk(KERN_WARNING "uvesafb: VBE state restore call "
++                              "failed (eax=0x%x, err=%d)\n",
++                              task->t.regs.eax, err);
++
++      uvesafb_free(task);
++}
++
++static int __devinit uvesafb_vbe_getinfo(struct uvesafb_ktask *task,
++              struct uvesafb_par *par)
++{
++      int err;
++
++      task->t.regs.eax = 0x4f00;
++      task->t.flags = TF_VBEIB;
++      task->t.buf_len = sizeof(struct vbe_ib);
++      task->buf = &par->vbe_ib;
++      strncpy(par->vbe_ib.vbe_signature, "VBE2", 4);
++
++      err = uvesafb_exec(task);
++      if (err || (task->t.regs.eax & 0xffff) != 0x004f) {
++              printk(KERN_ERR "uvesafb: Getting VBE info block failed "
++                              "(eax=0x%x, err=%d)\n", (u32)task->t.regs.eax,
++                              err);
++              return -EINVAL;
++      }
++
++      if (par->vbe_ib.vbe_version < 0x0200) {
++              printk(KERN_ERR "uvesafb: Sorry, pre-VBE 2.0 cards are "
++                              "not supported.\n");
++              return -EINVAL;
++      }
++
++      if (!par->vbe_ib.mode_list_ptr) {
++              printk(KERN_ERR "uvesafb: Missing mode list!\n");
++              return -EINVAL;
++      }
++
++      printk(KERN_INFO "uvesafb: ");
++
++      /*
++       * Convert string pointers and the mode list pointer into
++       * usable addresses. Print informational messages about the
++       * video adapter and its vendor.
++       */
++      if (par->vbe_ib.oem_vendor_name_ptr)
++              printk("%s, ",
++                      ((char *)task->buf) + par->vbe_ib.oem_vendor_name_ptr);
++
++      if (par->vbe_ib.oem_product_name_ptr)
++              printk("%s, ",
++                      ((char *)task->buf) + par->vbe_ib.oem_product_name_ptr);
++
++      if (par->vbe_ib.oem_product_rev_ptr)
++              printk("%s, ",
++                      ((char *)task->buf) + par->vbe_ib.oem_product_rev_ptr);
++
++      if (par->vbe_ib.oem_string_ptr)
++              printk("OEM: %s, ",
++                      ((char *)task->buf) + par->vbe_ib.oem_string_ptr);
++
++      printk("VBE v%d.%d\n", ((par->vbe_ib.vbe_version & 0xff00) >> 8),
++                      par->vbe_ib.vbe_version & 0xff);
++
++      return 0;
++}
++
++static int __devinit uvesafb_vbe_getmodes(struct uvesafb_ktask *task,
++              struct uvesafb_par *par)
++{
++      int off = 0, err;
++      u16 *mode;
++
++      par->vbe_modes_cnt = 0;
++
++      /* Count available modes. */
++      mode = (u16 *) (((u8 *)&par->vbe_ib) + par->vbe_ib.mode_list_ptr);
++      while (*mode != 0xffff) {
++              par->vbe_modes_cnt++;
++              mode++;
++      }
++
++      par->vbe_modes = kzalloc(sizeof(struct vbe_mode_ib) *
++                              par->vbe_modes_cnt, GFP_KERNEL);
++      if (!par->vbe_modes)
++              return -ENOMEM;
++
++      /* Get info about all available modes. */
++      mode = (u16 *) (((u8 *)&par->vbe_ib) + par->vbe_ib.mode_list_ptr);
++      while (*mode != 0xffff) {
++              struct vbe_mode_ib *mib;
++
++              uvesafb_reset(task);
++              task->t.regs.eax = 0x4f01;
++              task->t.regs.ecx = (u32) *mode;
++              task->t.flags = TF_BUF_RET | TF_BUF_ESDI;
++              task->t.buf_len = sizeof(struct vbe_mode_ib);
++              task->buf = par->vbe_modes + off;
++
++              err = uvesafb_exec(task);
++              if (err || (task->t.regs.eax & 0xffff) != 0x004f) {
++                      printk(KERN_ERR "uvesafb: Getting mode info block "
++                              "for mode 0x%x failed (eax=0x%x, err=%d)\n",
++                              *mode, (u32)task->t.regs.eax, err);
++                      return -EINVAL;
++              }
++
++              mib = task->buf;
++              mib->mode_id = *mode;
++
++              /*
++               * We only want modes that are supported with the current
++               * hardware configuration, color, graphics and that have
++               * support for the LFB.
++               */
++              if ((mib->mode_attr & VBE_MODE_MASK) == VBE_MODE_MASK &&
++                               mib->bits_per_pixel >= 8)
++                      off++;
++              else
++                      par->vbe_modes_cnt--;
++
++              mode++;
++              mib->depth = mib->red_len + mib->green_len + mib->blue_len;
++
++              /*
++               * Handle 8bpp modes and modes with broken color component
++               * lengths.
++               */
++              if (mib->depth == 0 || (mib->depth == 24 &&
++                                      mib->bits_per_pixel == 32))
++                      mib->depth = mib->bits_per_pixel;
++      }
++
++      return 0;
++}
++
++/*
++ * The Protected Mode Interface is 32-bit x86 code, so we only run it on
++ * x86 and not x86_64.
++ */
++#ifdef CONFIG_X86_32
++static int __devinit uvesafb_vbe_getpmi(struct uvesafb_ktask *task,
++              struct uvesafb_par *par)
++{
++      int i, err;
++
++      uvesafb_reset(task);
++      task->t.regs.eax = 0x4f0a;
++      task->t.regs.ebx = 0x0;
++      err = uvesafb_exec(task);
++
++      if ((task->t.regs.eax & 0xffff) != 0x4f || task->t.regs.es < 0xc000) {
++              par->pmi_setpal = par->ypan = 0;
++      } else {
++              par->pmi_base = (u16 *)phys_to_virt(((u32)task->t.regs.es << 4)
++                                              + task->t.regs.edi);
++              par->pmi_start = (u8 *)par->pmi_base + par->pmi_base[1];
++              par->pmi_pal = (u8 *)par->pmi_base + par->pmi_base[2];
++              printk(KERN_INFO "uvesafb: protected mode interface info at "
++                               "%04x:%04x\n",
++                               (u16)task->t.regs.es, (u16)task->t.regs.edi);
++              printk(KERN_INFO "uvesafb: pmi: set display start = %p, "
++                               "set palette = %p\n", par->pmi_start,
++                               par->pmi_pal);
++
++              if (par->pmi_base[3]) {
++                      printk(KERN_INFO "uvesafb: pmi: ports = ");
++                      for (i = par->pmi_base[3]/2;
++                                      par->pmi_base[i] != 0xffff; i++)
++                              printk("%x ", par->pmi_base[i]);
++                      printk("\n");
++
++                      if (par->pmi_base[i] != 0xffff) {
++                              printk(KERN_INFO "uvesafb: can't handle memory"
++                                               " requests, pmi disabled\n");
++                              par->ypan = par->pmi_setpal = 0;
++                      }
++              }
++      }
++      return 0;
++}
++#endif /* CONFIG_X86_32 */
++
++/*
++ * Check whether a video mode is supported by the Video BIOS and is
++ * compatible with the monitor limits.
++ */
++static int __devinit uvesafb_is_valid_mode(struct fb_videomode *mode,
++              struct fb_info *info)
++{
++      if (info->monspecs.gtf) {
++              fb_videomode_to_var(&info->var, mode);
++              if (fb_validate_mode(&info->var, info))
++                      return 0;
++      }
++
++      if (uvesafb_vbe_find_mode(info->par, mode->xres, mode->yres, 8,
++                              UVESAFB_EXACT_RES) == -1)
++              return 0;
++
++      return 1;
++}
++
++static int __devinit uvesafb_vbe_getedid(struct uvesafb_ktask *task,
++              struct fb_info *info)
++{
++      struct uvesafb_par *par = info->par;
++      int err = 0;
++
++      if (noedid || par->vbe_ib.vbe_version < 0x0300)
++              return -EINVAL;
++
++      task->t.regs.eax = 0x4f15;
++      task->t.regs.ebx = 0;
++      task->t.regs.ecx = 0;
++      task->t.buf_len = 0;
++      task->t.flags = 0;
++
++      err = uvesafb_exec(task);
++
++      if ((task->t.regs.eax & 0xffff) != 0x004f || err)
++              return -EINVAL;
++
++      if ((task->t.regs.ebx & 0x3) == 3) {
++              printk(KERN_INFO "uvesafb: VBIOS/hardware supports both "
++                               "DDC1 and DDC2 transfers\n");
++      } else if ((task->t.regs.ebx & 0x3) == 2) {
++              printk(KERN_INFO "uvesafb: VBIOS/hardware supports DDC2 "
++                               "transfers\n");
++      } else if ((task->t.regs.ebx & 0x3) == 1) {
++              printk(KERN_INFO "uvesafb: VBIOS/hardware supports DDC1 "
++                               "transfers\n");
++      } else {
++              printk(KERN_INFO "uvesafb: VBIOS/hardware doesn't support "
++                               "DDC transfers\n");
++              return -EINVAL;
++      }
++
++      task->t.regs.eax = 0x4f15;
++      task->t.regs.ebx = 1;
++      task->t.regs.ecx = task->t.regs.edx = 0;
++      task->t.flags = TF_BUF_RET | TF_BUF_ESDI;
++      task->t.buf_len = EDID_LENGTH;
++      task->buf = kzalloc(EDID_LENGTH, GFP_KERNEL);
++
++      err = uvesafb_exec(task);
++
++      if ((task->t.regs.eax & 0xffff) == 0x004f && !err) {
++              fb_edid_to_monspecs(task->buf, &info->monspecs);
++
++              if (info->monspecs.vfmax && info->monspecs.hfmax) {
++                      /*
++                       * If the maximum pixel clock wasn't specified in
++                       * the EDID block, set it to 300 MHz.
++                       */
++                      if (info->monspecs.dclkmax == 0)
++                              info->monspecs.dclkmax = 300 * 1000000;
++                      info->monspecs.gtf = 1;
++              }
++      } else {
++              err = -EINVAL;
++      }
++
++      kfree(task->buf);
++      return err;
++}
++
++static void __devinit uvesafb_vbe_getmonspecs(struct uvesafb_ktask *task,
++              struct fb_info *info)
++{
++      struct uvesafb_par *par = info->par;
++      int i;
++
++      memset(&info->monspecs, 0, sizeof(info->monspecs));
++
++      /*
++       * If we don't get all necessary data from the EDID block,
++       * mark it as incompatible with the GTF and set nocrtc so
++       * that we always use the default BIOS refresh rate.
++       */
++      if (uvesafb_vbe_getedid(task, info)) {
++              info->monspecs.gtf = 0;
++              par->nocrtc = 1;
++      }
++
++      /* Kernel command line overrides. */
++      if (maxclk)
++              info->monspecs.dclkmax = maxclk * 1000000;
++      if (maxvf)
++              info->monspecs.vfmax = maxvf;
++      if (maxhf)
++              info->monspecs.hfmax = maxhf * 1000;
++
++      /*
++       * In case DDC transfers are not supported, the user can provide
++       * monitor limits manually. Lower limits are set to "safe" values.
++       */
++      if (info->monspecs.gtf == 0 && maxclk && maxvf && maxhf) {
++              info->monspecs.dclkmin = 0;
++              info->monspecs.vfmin = 60;
++              info->monspecs.hfmin = 29000;
++              info->monspecs.gtf = 1;
++              par->nocrtc = 0;
++      }
++
++      if (info->monspecs.gtf)
++              printk(KERN_INFO
++                      "uvesafb: monitor limits: vf = %d Hz, hf = %d kHz, "
++                      "clk = %d MHz\n", info->monspecs.vfmax,
++                      (int)(info->monspecs.hfmax / 1000),
++                      (int)(info->monspecs.dclkmax / 1000000));
++      else
++              printk(KERN_INFO "uvesafb: no monitor limits have been set, "
++                               "default refresh rate will be used\n");
++
++      /* Add VBE modes to the modelist. */
++      for (i = 0; i < par->vbe_modes_cnt; i++) {
++              struct fb_var_screeninfo var;
++              struct vbe_mode_ib *mode;
++              struct fb_videomode vmode;
++
++              mode = &par->vbe_modes[i];
++              memset(&var, 0, sizeof(var));
++
++              var.xres = mode->x_res;
++              var.yres = mode->y_res;
++
++              fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON, 60, &var, info);
++              fb_var_to_videomode(&vmode, &var);
++              fb_add_videomode(&vmode, &info->modelist);
++      }
++
++      /* Add valid VESA modes to our modelist. */
++      for (i = 0; i < VESA_MODEDB_SIZE; i++) {
++              if (uvesafb_is_valid_mode((struct fb_videomode *)
++                                              &vesa_modes[i], info))
++                      fb_add_videomode(&vesa_modes[i], &info->modelist);
++      }
++
++      for (i = 0; i < info->monspecs.modedb_len; i++) {
++              if (uvesafb_is_valid_mode(&info->monspecs.modedb[i], info))
++                      fb_add_videomode(&info->monspecs.modedb[i],
++                                      &info->modelist);
++      }
++
++      return;
++}
++
++static void __devinit uvesafb_vbe_getstatesize(struct uvesafb_ktask *task,
++              struct uvesafb_par *par)
++{
++      int err;
++
++      uvesafb_reset(task);
++
++      /*
++       * Get the VBE state buffer size. We want all available
++       * hardware state data (CL = 0x0f).
++       */
++      task->t.regs.eax = 0x4f04;
++      task->t.regs.ecx = 0x000f;
++      task->t.regs.edx = 0x0000;
++      task->t.flags = 0;
++
++      err = uvesafb_exec(task);
++
++      if (err || (task->t.regs.eax & 0xffff) != 0x004f) {
++              printk(KERN_WARNING "uvesafb: VBE state buffer size "
++                      "cannot be determined (eax=0x%x, err=%d)\n",
++                      task->t.regs.eax, err);
++              par->vbe_state_size = 0;
++              return;
++      }
++
++      par->vbe_state_size = 64 * (task->t.regs.ebx & 0xffff);
++}
++
++static int __devinit uvesafb_vbe_init(struct fb_info *info)
++{
++      struct uvesafb_ktask *task = NULL;
++      struct uvesafb_par *par = info->par;
++      int err;
++
++      task = uvesafb_prep();
++      if (!task)
++              return -ENOMEM;
++
++      err = uvesafb_vbe_getinfo(task, par);
++      if (err)
++              goto out;
++
++      err = uvesafb_vbe_getmodes(task, par);
++      if (err)
++              goto out;
++
++      par->nocrtc = nocrtc;
++#ifdef CONFIG_X86_32
++      par->pmi_setpal = pmi_setpal;
++      par->ypan = ypan;
++
++      if (par->pmi_setpal || par->ypan)
++              uvesafb_vbe_getpmi(task, par);
++#else
++      /* The protected mode interface is not available on non-x86. */
++      par->pmi_setpal = par->ypan = 0;
++#endif
++
++      INIT_LIST_HEAD(&info->modelist);
++      uvesafb_vbe_getmonspecs(task, info);
++      uvesafb_vbe_getstatesize(task, par);
++
++out:  uvesafb_free(task);
++      return err;
++}
++
++static int __devinit uvesafb_vbe_init_mode(struct fb_info *info)
++{
++      struct list_head *pos;
++      struct fb_modelist *modelist;
++      struct fb_videomode *mode;
++      struct uvesafb_par *par = info->par;
++      int i, modeid;
++
++      /* Has the user requested a specific VESA mode? */
++      if (vbemode) {
++              for (i = 0; i < par->vbe_modes_cnt; i++) {
++                      if (par->vbe_modes[i].mode_id == vbemode) {
++                              fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON, 60,
++                                                      &info->var, info);
++                              /*
++                               * With pixclock set to 0, the default BIOS
++                               * timings will be used in set_par().
++                               */
++                              info->var.pixclock = 0;
++                              modeid = i;
++                              goto gotmode;
++                      }
++              }
++              printk(KERN_INFO "uvesafb: requested VBE mode 0x%x is "
++                               "unavailable\n", vbemode);
++              vbemode = 0;
++      }
++
++      /* Count the modes in the modelist */
++      i = 0;
++      list_for_each(pos, &info->modelist)
++              i++;
++
++      /*
++       * Convert the modelist into a modedb so that we can use it with
++       * fb_find_mode().
++       */
++      mode = kzalloc(i * sizeof(*mode), GFP_KERNEL);
++      if (mode) {
++              i = 0;
++              list_for_each(pos, &info->modelist) {
++                      modelist = list_entry(pos, struct fb_modelist, list);
++                      mode[i] = modelist->mode;
++                      i++;
++              }
++
++              if (!mode_option)
++                      mode_option = UVESAFB_DEFAULT_MODE;
++
++              i = fb_find_mode(&info->var, info, mode_option, mode, i,
++                      NULL, 8);
++
++              kfree(mode);
++      }
++
++      /* fb_find_mode() failed */
++      if (i == 0 || i >= 3) {
++              info->var.xres = 640;
++              info->var.yres = 480;
++              mode = (struct fb_videomode *)
++                              fb_find_best_mode(&info->var, &info->modelist);
++
++              if (mode) {
++                      fb_videomode_to_var(&info->var, mode);
++              } else {
++                      modeid = par->vbe_modes[0].mode_id;
++                      fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON, 60,
++                                  &info->var, info);
++                      goto gotmode;
++              }
++      }
++
++      /* Look for a matching VBE mode. */
++      modeid = uvesafb_vbe_find_mode(par, info->var.xres, info->var.yres,
++                      info->var.bits_per_pixel, UVESAFB_EXACT_RES);
++
++      if (modeid == -1)
++              return -EINVAL;
++
++gotmode:
++      uvesafb_setup_var(&info->var, info, &par->vbe_modes[modeid]);
++
++      /*
++       * If we are not VBE3.0+ compliant, we're done -- the BIOS will
++       * ignore our timings anyway.
++       */
++      if (par->vbe_ib.vbe_version < 0x0300 || par->nocrtc)
++              fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON, 60,
++                                      &info->var, info);
++
++      return modeid;
++}
++
++static int uvesafb_setpalette(struct uvesafb_pal_entry *entries, int count,
++              int start, struct fb_info *info)
++{
++      struct uvesafb_ktask *task;
++      struct uvesafb_par *par = info->par;
++      int i = par->mode_idx;
++      int err = 0;
++
++      /*
++       * We support palette modifications for 8 bpp modes only, so
++       * there can never be more than 256 entries.
++       */
++      if (start + count > 256)
++              return -EINVAL;
++
++      /* Use VGA registers if mode is VGA-compatible. */
++      if (i >= 0 && i < par->vbe_modes_cnt &&
++          par->vbe_modes[i].mode_attr & VBE_MODE_VGACOMPAT) {
++              for (i = 0; i < count; i++) {
++                      outb_p(start + i,        dac_reg);
++                      outb_p(entries[i].red,   dac_val);
++                      outb_p(entries[i].green, dac_val);
++                      outb_p(entries[i].blue,  dac_val);
++              }
++      }
++#ifdef CONFIG_X86_32
++      else if (par->pmi_setpal) {
++              __asm__ __volatile__(
++              "call *(%%esi)"
++              : /* no return value */
++              : "a" (0x4f09),         /* EAX */
++                "b" (0),              /* EBX */
++                "c" (count),          /* ECX */
++                "d" (start),          /* EDX */
++                "D" (entries),        /* EDI */
++                "S" (&par->pmi_pal)); /* ESI */
++      }
++#endif
++      else {
++              task = uvesafb_prep();
++              if (!task)
++                      return -ENOMEM;
++
++              task->t.regs.eax = 0x4f09;
++              task->t.regs.ebx = 0x0;
++              task->t.regs.ecx = count;
++              task->t.regs.edx = start;
++              task->t.flags = TF_BUF_ESDI;
++              task->t.buf_len = sizeof(struct uvesafb_pal_entry) * count;
++              task->buf = entries;
++
++              err = uvesafb_exec(task);
++              if ((task->t.regs.eax & 0xffff) != 0x004f)
++                      err = 1;
++
++              uvesafb_free(task);
++      }
++      return err;
++}
++
++static int uvesafb_setcolreg(unsigned regno, unsigned red, unsigned green,
++              unsigned blue, unsigned transp,
++              struct fb_info *info)
++{
++      struct uvesafb_pal_entry entry;
++      int shift = 16 - info->var.green.length;
++      int err = 0;
++
++      if (regno >= info->cmap.len)
++              return -EINVAL;
++
++      if (info->var.bits_per_pixel == 8) {
++              entry.red   = red   >> shift;
++              entry.green = green >> shift;
++              entry.blue  = blue  >> shift;
++              entry.pad   = 0;
++
++              err = uvesafb_setpalette(&entry, 1, regno, info);
++      } else if (regno < 16) {
++              switch (info->var.bits_per_pixel) {
++              case 16:
++                      if (info->var.red.offset == 10) {
++                              /* 1:5:5:5 */
++                              ((u32 *) (info->pseudo_palette))[regno] =
++                                              ((red   & 0xf800) >>  1) |
++                                              ((green & 0xf800) >>  6) |
++                                              ((blue  & 0xf800) >> 11);
++                      } else {
++                              /* 0:5:6:5 */
++                              ((u32 *) (info->pseudo_palette))[regno] =
++                                              ((red   & 0xf800)      ) |
++                                              ((green & 0xfc00) >>  5) |
++                                              ((blue  & 0xf800) >> 11);
++                      }
++                      break;
++
++              case 24:
++              case 32:
++                      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);
++                      break;
++              }
++      }
++      return err;
++}
++
++static int uvesafb_setcmap(struct fb_cmap *cmap, struct fb_info *info)
++{
++      struct uvesafb_pal_entry *entries;
++      int shift = 16 - info->var.green.length;
++      int i, err = 0;
++
++      if (info->var.bits_per_pixel == 8) {
++              if (cmap->start + cmap->len > info->cmap.start +
++                  info->cmap.len || cmap->start < info->cmap.start)
++                      return -EINVAL;
++
++              entries = kmalloc(sizeof(*entries) * cmap->len, GFP_KERNEL);
++              if (!entries)
++                      return -ENOMEM;
++
++              for (i = 0; i < cmap->len; i++) {
++                      entries[i].red   = cmap->red[i]   >> shift;
++                      entries[i].green = cmap->green[i] >> shift;
++                      entries[i].blue  = cmap->blue[i]  >> shift;
++                      entries[i].pad   = 0;
++              }
++              err = uvesafb_setpalette(entries, cmap->len, cmap->start, info);
++              kfree(entries);
++      } else {
++              /*
++               * For modes with bpp > 8, we only set the pseudo palette in
++               * the fb_info struct. We rely on uvesafb_setcolreg to do all
++               * sanity checking.
++               */
++              for (i = 0; i < cmap->len; i++) {
++                      err |= uvesafb_setcolreg(cmap->start + i, cmap->red[i],
++                                              cmap->green[i], cmap->blue[i],
++                                              0, info);
++              }
++      }
++      return err;
++}
++
++static int uvesafb_pan_display(struct fb_var_screeninfo *var,
++              struct fb_info *info)
++{
++#ifdef CONFIG_X86_32
++      int offset;
++      struct uvesafb_par *par = info->par;
++
++      offset = (var->yoffset * info->fix.line_length + var->xoffset) / 4;
++
++      /*
++       * It turns out it's not the best idea to do panning via vm86,
++       * so we only allow it if we have a PMI.
++       */
++      if (par->pmi_start) {
++              __asm__ __volatile__(
++                      "call *(%%edi)"
++                      : /* no return value */
++                      : "a" (0x4f07),         /* EAX */
++                        "b" (0),              /* EBX */
++                        "c" (offset),         /* ECX */
++                        "d" (offset >> 16),   /* EDX */
++                        "D" (&par->pmi_start));    /* EDI */
++      }
++#endif
++      return 0;
++}
++
++static int uvesafb_blank(int blank, struct fb_info *info)
++{
++      struct uvesafb_par *par = info->par;
++      struct uvesafb_ktask *task;
++      int err = 1;
++
++      if (par->vbe_ib.capabilities & VBE_CAP_VGACOMPAT) {
++              int loop = 10000;
++              u8 seq = 0, crtc17 = 0;
++
++              if (blank == FB_BLANK_POWERDOWN) {
++                      seq = 0x20;
++                      crtc17 = 0x00;
++                      err = 0;
++              } else {
++                      seq = 0x00;
++                      crtc17 = 0x80;
++                      err = (blank == FB_BLANK_UNBLANK) ? 0 : -EINVAL;
++              }
++
++              vga_wseq(NULL, 0x00, 0x01);
++              seq |= vga_rseq(NULL, 0x01) & ~0x20;
++              vga_wseq(NULL, 0x00, seq);
++
++              crtc17 |= vga_rcrt(NULL, 0x17) & ~0x80;
++              while (loop--);
++              vga_wcrt(NULL, 0x17, crtc17);
++              vga_wseq(NULL, 0x00, 0x03);
++      } else {
++              task = uvesafb_prep();
++              if (!task)
++                      return -ENOMEM;
++
++              task->t.regs.eax = 0x4f10;
++              switch (blank) {
++              case FB_BLANK_UNBLANK:
++                      task->t.regs.ebx = 0x0001;
++                      break;
++              case FB_BLANK_NORMAL:
++                      task->t.regs.ebx = 0x0101;      /* standby */
++                      break;
++              case FB_BLANK_POWERDOWN:
++                      task->t.regs.ebx = 0x0401;      /* powerdown */
++                      break;
++              default:
++                      goto out;
++              }
++
++              err = uvesafb_exec(task);
++              if (err || (task->t.regs.eax & 0xffff) != 0x004f)
++                      err = 1;
++out:          uvesafb_free(task);
++      }
++      return err;
++}
++
++static int uvesafb_open(struct fb_info *info, int user)
++{
++      struct uvesafb_par *par = info->par;
++      int cnt = atomic_read(&par->ref_count);
++
++      if (!cnt && par->vbe_state_size)
++              par->vbe_state_orig = uvesafb_vbe_state_save(par);
++
++      atomic_inc(&par->ref_count);
++      return 0;
++}
++
++static int uvesafb_release(struct fb_info *info, int user)
++{
++      struct uvesafb_ktask *task = NULL;
++      struct uvesafb_par *par = info->par;
++      int cnt = atomic_read(&par->ref_count);
++
++      if (!cnt)
++              return -EINVAL;
++
++      if (cnt != 1)
++              goto out;
++
++      task = uvesafb_prep();
++      if (!task)
++              goto out;
++
++      /* First, try to set the standard 80x25 text mode. */
++      task->t.regs.eax = 0x0003;
++      uvesafb_exec(task);
++
++      /*
++       * Now try to restore whatever hardware state we might have
++       * saved when the fb device was first opened.
++       */
++      uvesafb_vbe_state_restore(par, par->vbe_state_orig);
++out:
++      atomic_dec(&par->ref_count);
++      if (task)
++              uvesafb_free(task);
++      return 0;
++}
++
++static int uvesafb_set_par(struct fb_info *info)
++{
++      struct uvesafb_par *par = info->par;
++      struct uvesafb_ktask *task = NULL;
++      struct vbe_crtc_ib *crtc = NULL;
++      struct vbe_mode_ib *mode = NULL;
++      int i, err = 0, depth = info->var.bits_per_pixel;
++
++      if (depth > 8 && depth != 32)
++              depth = info->var.red.length + info->var.green.length +
++                      info->var.blue.length;
++
++      i = uvesafb_vbe_find_mode(par, info->var.xres, info->var.yres, depth,
++                               UVESAFB_EXACT_RES | UVESAFB_EXACT_DEPTH);
++      if (i >= 0)
++              mode = &par->vbe_modes[i];
++      else
++              return -EINVAL;
++
++      task = uvesafb_prep();
++      if (!task)
++              return -ENOMEM;
++setmode:
++      task->t.regs.eax = 0x4f02;
++      task->t.regs.ebx = mode->mode_id | 0x4000;      /* use LFB */
++
++      if (par->vbe_ib.vbe_version >= 0x0300 && !par->nocrtc &&
++          info->var.pixclock != 0) {
++              task->t.regs.ebx |= 0x0800;             /* use CRTC data */
++              task->t.flags = TF_BUF_ESDI;
++              crtc = kzalloc(sizeof(struct vbe_crtc_ib), GFP_KERNEL);
++              if (!crtc) {
++                      err = -ENOMEM;
++                      goto out;
++              }
++              crtc->horiz_start = info->var.xres + info->var.right_margin;
++              crtc->horiz_end   = crtc->horiz_start + info->var.hsync_len;
++              crtc->horiz_total = crtc->horiz_end + info->var.left_margin;
++
++              crtc->vert_start  = info->var.yres + info->var.lower_margin;
++              crtc->vert_end    = crtc->vert_start + info->var.vsync_len;
++              crtc->vert_total  = crtc->vert_end + info->var.upper_margin;
++
++              crtc->pixel_clock = PICOS2KHZ(info->var.pixclock) * 1000;
++              crtc->refresh_rate = (u16)(100 * (crtc->pixel_clock /
++                              (crtc->vert_total * crtc->horiz_total)));
++
++              if (info->var.vmode & FB_VMODE_DOUBLE)
++                      crtc->flags |= 0x1;
++              if (info->var.vmode & FB_VMODE_INTERLACED)
++                      crtc->flags |= 0x2;
++              if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT))
++                      crtc->flags |= 0x4;
++              if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT))
++                      crtc->flags |= 0x8;
++              memcpy(&par->crtc, crtc, sizeof(*crtc));
++      } else {
++              memset(&par->crtc, 0, sizeof(*crtc));
++      }
++
++      task->t.buf_len = sizeof(struct vbe_crtc_ib);
++      task->buf = &par->crtc;
++
++      err = uvesafb_exec(task);
++      if (err || (task->t.regs.eax & 0xffff) != 0x004f) {
++              /*
++               * The mode switch might have failed because we tried to
++               * use our own timings.  Try again with the default timings.
++               */
++              if (crtc != NULL) {
++                      printk(KERN_WARNING "uvesafb: mode switch failed "
++                              "(eax=0x%x, err=%d). Trying again with "
++                              "default timings.\n", task->t.regs.eax, err);
++                      uvesafb_reset(task);
++                      kfree(crtc);
++                      crtc = NULL;
++                      info->var.pixclock = 0;
++                      goto setmode;
++              } else {
++                      printk(KERN_ERR "uvesafb: mode switch failed (eax="
++                              "0x%x, err=%d)\n", task->t.regs.eax, err);
++                      err = -EINVAL;
++                      goto out;
++              }
++      }
++      par->mode_idx = i;
++
++      /* For 8bpp modes, always try to set the DAC to 8 bits. */
++      if (par->vbe_ib.capabilities & VBE_CAP_CAN_SWITCH_DAC &&
++          mode->bits_per_pixel <= 8) {
++              uvesafb_reset(task);
++              task->t.regs.eax = 0x4f08;
++              task->t.regs.ebx = 0x0800;
++
++              err = uvesafb_exec(task);
++              if (err || (task->t.regs.eax & 0xffff) != 0x004f ||
++                  ((task->t.regs.ebx & 0xff00) >> 8) != 8) {
++                      /*
++                       * We've failed to set the DAC palette format -
++                       * time to correct var.
++                       */
++                      info->var.red.length    = 6;
++                      info->var.green.length  = 6;
++                      info->var.blue.length   = 6;
++              }
++      }
++
++      info->fix.visual = (info->var.bits_per_pixel == 8) ?
++                              FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
++      info->fix.line_length = mode->bytes_per_scan_line;
++
++out:  if (crtc != NULL)
++              kfree(crtc);
++      uvesafb_free(task);
++
++      return err;
++}
++
++static void uvesafb_check_limits(struct fb_var_screeninfo *var,
++              struct fb_info *info)
++{
++      const struct fb_videomode *mode;
++      struct uvesafb_par *par = info->par;
++
++      /*
++       * If pixclock is set to 0, then we're using default BIOS timings
++       * and thus don't have to perform any checks here.
++       */
++      if (!var->pixclock)
++              return;
++
++      if (par->vbe_ib.vbe_version < 0x0300) {
++              fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON, 60, var, info);
++              return;
++      }
++
++      if (!fb_validate_mode(var, info))
++              return;
++
++      mode = fb_find_best_mode(var, &info->modelist);
++      if (mode) {
++              if (mode->xres == var->xres && mode->yres == var->yres &&
++                  !(mode->vmode & (FB_VMODE_INTERLACED | FB_VMODE_DOUBLE))) {
++                      fb_videomode_to_var(var, mode);
++                      return;
++              }
++      }
++
++      if (info->monspecs.gtf && !fb_get_mode(FB_MAXTIMINGS, 0, var, info))
++              return;
++      /* Use default refresh rate */
++      var->pixclock = 0;
++}
++
++static int uvesafb_check_var(struct fb_var_screeninfo *var,
++              struct fb_info *info)
++{
++      struct uvesafb_par *par = info->par;
++      struct vbe_mode_ib *mode = NULL;
++      int match = -1;
++      int depth = var->red.length + var->green.length + var->blue.length;
++
++      /*
++       * Various apps will use bits_per_pixel to set the color depth,
++       * which is theoretically incorrect, but which we'll try to handle
++       * here.
++       */
++      if (depth == 0 || abs(depth - var->bits_per_pixel) >= 8)
++              depth = var->bits_per_pixel;
++
++      match = uvesafb_vbe_find_mode(par, var->xres, var->yres, depth,
++                                              UVESAFB_EXACT_RES);
++      if (match == -1)
++              return -EINVAL;
++
++      mode = &par->vbe_modes[match];
++      uvesafb_setup_var(var, info, mode);
++
++      /*
++       * Check whether we have remapped enough memory for this mode.
++       * We might be called at an early stage, when we haven't remapped
++       * any memory yet, in which case we simply skip the check.
++       */
++      if (var->yres * mode->bytes_per_scan_line > info->fix.smem_len
++                                              && info->fix.smem_len)
++              return -EINVAL;
++
++      if ((var->vmode & FB_VMODE_DOUBLE) &&
++                              !(par->vbe_modes[match].mode_attr & 0x100))
++              var->vmode &= ~FB_VMODE_DOUBLE;
++
++      if ((var->vmode & FB_VMODE_INTERLACED) &&
++                              !(par->vbe_modes[match].mode_attr & 0x200))
++              var->vmode &= ~FB_VMODE_INTERLACED;
++
++      uvesafb_check_limits(var, info);
++
++      var->xres_virtual = var->xres;
++      var->yres_virtual = (par->ypan) ?
++                              info->fix.smem_len / mode->bytes_per_scan_line :
++                              var->yres;
++      return 0;
++}
++
++static void uvesafb_save_state(struct fb_info *info)
++{
++      struct uvesafb_par *par = info->par;
++
++      if (par->vbe_state_saved)
++              kfree(par->vbe_state_saved);
++
++      par->vbe_state_saved = uvesafb_vbe_state_save(par);
++}
++
++static void uvesafb_restore_state(struct fb_info *info)
++{
++      struct uvesafb_par *par = info->par;
++
++      uvesafb_vbe_state_restore(par, par->vbe_state_saved);
++}
++
++static struct fb_ops uvesafb_ops = {
++      .owner          = THIS_MODULE,
++      .fb_open        = uvesafb_open,
++      .fb_release     = uvesafb_release,
++      .fb_setcolreg   = uvesafb_setcolreg,
++      .fb_setcmap     = uvesafb_setcmap,
++      .fb_pan_display = uvesafb_pan_display,
++      .fb_blank       = uvesafb_blank,
++      .fb_fillrect    = cfb_fillrect,
++      .fb_copyarea    = cfb_copyarea,
++      .fb_imageblit   = cfb_imageblit,
++      .fb_check_var   = uvesafb_check_var,
++      .fb_set_par     = uvesafb_set_par,
++      .fb_save_state  = uvesafb_save_state,
++      .fb_restore_state = uvesafb_restore_state,
++};
++
++static void __devinit uvesafb_init_info(struct fb_info *info,
++              struct vbe_mode_ib *mode)
++{
++      unsigned int size_vmode;
++      unsigned int size_remap;
++      unsigned int size_total;
++      struct uvesafb_par *par = info->par;
++      int i, h;
++
++      info->pseudo_palette = ((u8 *)info->par + sizeof(struct uvesafb_par));
++      info->fix = uvesafb_fix;
++      info->fix.ypanstep = par->ypan ? 1 : 0;
++      info->fix.ywrapstep = (par->ypan > 1) ? 1 : 0;
++
++      /*
++       * If we were unable to get the state buffer size, disable
++       * functions for saving and restoring the hardware state.
++       */
++      if (par->vbe_state_size == 0) {
++              info->fbops->fb_save_state = NULL;
++              info->fbops->fb_restore_state = NULL;
++      }
++
++      /* Disable blanking if the user requested so. */
++      if (!blank)
++              info->fbops->fb_blank = NULL;
++
++      /*
++       * Find out how much IO memory is required for the mode with
++       * the highest resolution.
++       */
++      size_remap = 0;
++      for (i = 0; i < par->vbe_modes_cnt; i++) {
++              h = par->vbe_modes[i].bytes_per_scan_line *
++                                      par->vbe_modes[i].y_res;
++              if (h > size_remap)
++                      size_remap = h;
++      }
++      size_remap *= 2;
++
++      /*
++       *   size_vmode -- that is the amount of memory needed for the
++       *                 used video mode, i.e. the minimum amount of
++       *                 memory we need.
++       */
++      if (mode != NULL) {
++              size_vmode = info->var.yres * mode->bytes_per_scan_line;
++      } else {
++              size_vmode = info->var.yres * info->var.xres *
++                           ((info->var.bits_per_pixel + 7) >> 3);
++      }
++
++      /*
++       *   size_total -- all video memory we have. Used for mtrr
++       *                 entries, resource allocation and bounds
++       *                 checking.
++       */
++      size_total = par->vbe_ib.total_memory * 65536;
++      if (vram_total)
++              size_total = vram_total * 1024 * 1024;
++      if (size_total < size_vmode)
++              size_total = size_vmode;
++
++      /*
++       *   size_remap -- the amount of video memory we are going to
++       *                 use for vesafb.  With modern cards it is no
++       *                 option to simply use size_total as th
++       *                 wastes plenty of kernel address space.
++       */
++      if (vram_remap)
++              size_remap = vram_remap * 1024 * 1024;
++      if (size_remap < size_vmode)
++              size_remap = size_vmode;
++      if (size_remap > size_total)
++              size_remap = size_total;
++
++      info->fix.smem_len = size_remap;
++      info->fix.smem_start = mode->phys_base_ptr;
++
++      /*
++       * We have to set yres_virtual here because when setup_var() was
++       * called, smem_len wasn't defined yet.
++       */
++      info->var.yres_virtual = info->fix.smem_len /
++                               mode->bytes_per_scan_line;
++
++      if (par->ypan && info->var.yres_virtual > info->var.yres) {
++              printk(KERN_INFO "uvesafb: scrolling: %s "
++                      "using protected mode interface, "
++                      "yres_virtual=%d\n",
++                      (par->ypan > 1) ? "ywrap" : "ypan",
++                      info->var.yres_virtual);
++      } else {
++              printk(KERN_INFO "uvesafb: scrolling: redraw\n");
++              info->var.yres_virtual = info->var.yres;
++              par->ypan = 0;
++      }
++
++      info->flags = FBINFO_FLAG_DEFAULT |
++                      (par->ypan) ? FBINFO_HWACCEL_YPAN : 0;
++
++      if (!par->ypan)
++              info->fbops->fb_pan_display = NULL;
++}
++
++static void uvesafb_init_mtrr(struct fb_info *info)
++{
++#ifdef CONFIG_MTRR
++      if (mtrr && !(info->fix.smem_start & (PAGE_SIZE - 1))) {
++              int temp_size = info->fix.smem_len;
++              unsigned int type = 0;
++
++              switch (mtrr) {
++              case 1:
++                      type = MTRR_TYPE_UNCACHABLE;
++                      break;
++              case 2:
++                      type = MTRR_TYPE_WRBACK;
++                      break;
++              case 3:
++                      type = MTRR_TYPE_WRCOMB;
++                      break;
++              case 4:
++                      type = MTRR_TYPE_WRTHROUGH;
++                      break;
++              default:
++                      type = 0;
++                      break;
++              }
++
++              if (type) {
++                      int rc;
++
++                      /* Find the largest power-of-two */
++                      while (temp_size & (temp_size - 1))
++                              temp_size &= (temp_size - 1);
++
++                      /* Try and find a power of two to add */
++                      do {
++                              rc = mtrr_add(info->fix.smem_start,
++                                            temp_size, type, 1);
++                              temp_size >>= 1;
++                      } while (temp_size >= PAGE_SIZE && rc == -EINVAL);
++              }
++      }
++#endif /* CONFIG_MTRR */
++}
++
++
++static ssize_t uvesafb_show_vbe_ver(struct device *dev,
++              struct device_attribute *attr, char *buf)
++{
++      struct fb_info *info = platform_get_drvdata(to_platform_device(dev));
++      struct uvesafb_par *par = info->par;
++
++      return snprintf(buf, PAGE_SIZE, "%.4x\n", par->vbe_ib.vbe_version);
++}
++
++static DEVICE_ATTR(vbe_version, S_IRUGO, uvesafb_show_vbe_ver, NULL);
++
++static ssize_t uvesafb_show_vbe_modes(struct device *dev,
++              struct device_attribute *attr, char *buf)
++{
++      struct fb_info *info = platform_get_drvdata(to_platform_device(dev));
++      struct uvesafb_par *par = info->par;
++      int ret = 0, i;
++
++      for (i = 0; i < par->vbe_modes_cnt && ret < PAGE_SIZE; i++) {
++              ret += snprintf(buf + ret, PAGE_SIZE - ret,
++                      "%dx%d-%d, 0x%.4x\n",
++                      par->vbe_modes[i].x_res, par->vbe_modes[i].y_res,
++                      par->vbe_modes[i].depth, par->vbe_modes[i].mode_id);
++      }
++
++      return ret;
++}
++
++static DEVICE_ATTR(vbe_modes, S_IRUGO, uvesafb_show_vbe_modes, NULL);
++
++static ssize_t uvesafb_show_vendor(struct device *dev,
++              struct device_attribute *attr, char *buf)
++{
++      struct fb_info *info = platform_get_drvdata(to_platform_device(dev));
++      struct uvesafb_par *par = info->par;
++
++      if (par->vbe_ib.oem_vendor_name_ptr)
++              return snprintf(buf, PAGE_SIZE, "%s\n", (char *)
++                      (&par->vbe_ib) + par->vbe_ib.oem_vendor_name_ptr);
++      else
++              return 0;
++}
++
++static DEVICE_ATTR(oem_vendor, S_IRUGO, uvesafb_show_vendor, NULL);
++
++static ssize_t uvesafb_show_product_name(struct device *dev,
++              struct device_attribute *attr, char *buf)
++{
++      struct fb_info *info = platform_get_drvdata(to_platform_device(dev));
++      struct uvesafb_par *par = info->par;
++
++      if (par->vbe_ib.oem_product_name_ptr)
++              return snprintf(buf, PAGE_SIZE, "%s\n", (char *)
++                      (&par->vbe_ib) + par->vbe_ib.oem_product_name_ptr);
++      else
++              return 0;
++}
++
++static DEVICE_ATTR(oem_product_name, S_IRUGO, uvesafb_show_product_name, NULL);
++
++static ssize_t uvesafb_show_product_rev(struct device *dev,
++              struct device_attribute *attr, char *buf)
++{
++      struct fb_info *info = platform_get_drvdata(to_platform_device(dev));
++      struct uvesafb_par *par = info->par;
++
++      if (par->vbe_ib.oem_product_rev_ptr)
++              return snprintf(buf, PAGE_SIZE, "%s\n", (char *)
++                      (&par->vbe_ib) + par->vbe_ib.oem_product_rev_ptr);
++      else
++              return 0;
++}
++
++static DEVICE_ATTR(oem_product_rev, S_IRUGO, uvesafb_show_product_rev, NULL);
++
++static ssize_t uvesafb_show_oem_string(struct device *dev,
++              struct device_attribute *attr, char *buf)
++{
++      struct fb_info *info = platform_get_drvdata(to_platform_device(dev));
++      struct uvesafb_par *par = info->par;
++
++      if (par->vbe_ib.oem_string_ptr)
++              return snprintf(buf, PAGE_SIZE, "%s\n",
++                      (char *)(&par->vbe_ib) + par->vbe_ib.oem_string_ptr);
++      else
++              return 0;
++}
++
++static DEVICE_ATTR(oem_string, S_IRUGO, uvesafb_show_oem_string, NULL);
++
++static ssize_t uvesafb_show_nocrtc(struct device *dev,
++              struct device_attribute *attr, char *buf)
++{
++      struct fb_info *info = platform_get_drvdata(to_platform_device(dev));
++      struct uvesafb_par *par = info->par;
++
++      return snprintf(buf, PAGE_SIZE, "%d\n", par->nocrtc);
++}
++
++static ssize_t uvesafb_store_nocrtc(struct device *dev,
++              struct device_attribute *attr, const char *buf, size_t count)
++{
++      struct fb_info *info = platform_get_drvdata(to_platform_device(dev));
++      struct uvesafb_par *par = info->par;
++
++      if (count > 0) {
++              if (buf[0] == '0')
++                      par->nocrtc = 0;
++              else
++                      par->nocrtc = 1;
++      }
++      return count;
++}
++
++static DEVICE_ATTR(nocrtc, S_IRUGO | S_IWUSR, uvesafb_show_nocrtc,
++                      uvesafb_store_nocrtc);
++
++static struct attribute *uvesafb_dev_attrs[] = {
++      &dev_attr_vbe_version.attr,
++      &dev_attr_vbe_modes.attr,
++      &dev_attr_oem_vendor.attr,
++      &dev_attr_oem_product_name.attr,
++      &dev_attr_oem_product_rev.attr,
++      &dev_attr_oem_string.attr,
++      &dev_attr_nocrtc.attr,
++      NULL,
++};
++
++static struct attribute_group uvesafb_dev_attgrp = {
++      .name = NULL,
++      .attrs = uvesafb_dev_attrs,
++};
++
++static int __devinit uvesafb_probe(struct platform_device *dev)
++{
++      struct fb_info *info;
++      struct vbe_mode_ib *mode = NULL;
++      struct uvesafb_par *par;
++      int err = 0, i;
++
++      info = framebuffer_alloc(sizeof(*par) + sizeof(u32) * 256, &dev->dev);
++      if (!info)
++              return -ENOMEM;
++
++      par = info->par;
++
++      err = uvesafb_vbe_init(info);
++      if (err) {
++              printk(KERN_ERR "uvesafb: vbe_init() failed with %d\n", err);
++              goto out;
++      }
++
++      info->fbops = &uvesafb_ops;
++
++      i = uvesafb_vbe_init_mode(info);
++      if (i < 0) {
++              err = -EINVAL;
++              goto out;
++      } else {
++              mode = &par->vbe_modes[i];
++      }
++
++      if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
++              err = -ENXIO;
++              goto out;
++      }
++
++      uvesafb_init_info(info, mode);
++
++      if (!request_mem_region(info->fix.smem_start, info->fix.smem_len,
++                              "uvesafb")) {
++              printk(KERN_ERR "uvesafb: cannot reserve video memory at "
++                              "0x%lx\n", info->fix.smem_start);
++              err = -EIO;
++              goto out_mode;
++      }
++
++      info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len);
++
++      if (!info->screen_base) {
++              printk(KERN_ERR
++                      "uvesafb: abort, cannot ioremap 0x%x bytes of video "
++                      "memory at 0x%lx\n",
++                      info->fix.smem_len, info->fix.smem_start);
++              err = -EIO;
++              goto out_mem;
++      }
++
++      if (!request_region(0x3c0, 32, "uvesafb")) {
++              printk(KERN_ERR "uvesafb: request region 0x3c0-0x3e0 failed\n");
++              err = -EIO;
++              goto out_unmap;
++      }
++
++      uvesafb_init_mtrr(info);
++      platform_set_drvdata(dev, info);
++
++      if (register_framebuffer(info) < 0) {
++              printk(KERN_ERR
++                      "uvesafb: failed to register framebuffer device\n");
++              err = -EINVAL;
++              goto out_reg;
++      }
++
++      printk(KERN_INFO "uvesafb: framebuffer at 0x%lx, mapped to 0x%p, "
++                      "using %dk, total %dk\n", info->fix.smem_start,
++                      info->screen_base, info->fix.smem_len/1024,
++                      par->vbe_ib.total_memory * 64);
++      printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node,
++                      info->fix.id);
++
++      err = sysfs_create_group(&dev->dev.kobj, &uvesafb_dev_attgrp);
++      if (err != 0)
++              printk(KERN_WARNING "fb%d: failed to register attributes\n",
++                      info->node);
++
++      return 0;
++
++out_reg:
++      release_region(0x3c0, 32);
++out_unmap:
++      iounmap(info->screen_base);
++out_mem:
++      release_mem_region(info->fix.smem_start, info->fix.smem_len);
++out_mode:
++      if (!list_empty(&info->modelist))
++              fb_destroy_modelist(&info->modelist);
++      fb_destroy_modedb(info->monspecs.modedb);
++      fb_dealloc_cmap(&info->cmap);
++out:
++      if (par->vbe_modes)
++              kfree(par->vbe_modes);
++
++      framebuffer_release(info);
++      return err;
++}
++
++static int uvesafb_remove(struct platform_device *dev)
++{
++      struct fb_info *info = platform_get_drvdata(dev);
++
++      if (info) {
++              struct uvesafb_par *par = info->par;
++
++              sysfs_remove_group(&dev->dev.kobj, &uvesafb_dev_attgrp);
++              unregister_framebuffer(info);
++              release_region(0x3c0, 32);
++              iounmap(info->screen_base);
++              release_mem_region(info->fix.smem_start, info->fix.smem_len);
++              fb_destroy_modedb(info->monspecs.modedb);
++              fb_dealloc_cmap(&info->cmap);
++
++              if (par) {
++                      if (par->vbe_modes)
++                              kfree(par->vbe_modes);
++                      if (par->vbe_state_orig)
++                              kfree(par->vbe_state_orig);
++                      if (par->vbe_state_saved)
++                              kfree(par->vbe_state_saved);
++              }
++
++              framebuffer_release(info);
++      }
++      return 0;
++}
++
++static struct platform_driver uvesafb_driver = {
++      .probe  = uvesafb_probe,
++      .remove = uvesafb_remove,
++      .driver = {
++              .name = "uvesafb",
++      },
++};
++
++static struct platform_device *uvesafb_device;
++
++#ifndef MODULE
++static int __devinit uvesafb_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, "redraw"))
++                      ypan = 0;
++              else if (!strcmp(this_opt, "ypan"))
++                      ypan = 1;
++              else if (!strcmp(this_opt, "ywrap"))
++                      ypan = 2;
++              else if (!strcmp(this_opt, "vgapal"))
++                      pmi_setpal = 0;
++              else if (!strcmp(this_opt, "pmipal"))
++                      pmi_setpal = 1;
++              else if (!strncmp(this_opt, "mtrr:", 5))
++                      mtrr = simple_strtoul(this_opt+5, NULL, 0);
++              else if (!strcmp(this_opt, "nomtrr"))
++                      mtrr = 0;
++              else if (!strcmp(this_opt, "nocrtc"))
++                      nocrtc = 1;
++              else if (!strcmp(this_opt, "noedid"))
++                      noedid = 1;
++              else if (!strcmp(this_opt, "noblank"))
++                      blank = 0;
++              else if (!strncmp(this_opt, "vtotal:", 7))
++                      vram_total = simple_strtoul(this_opt + 7, NULL, 0);
++              else if (!strncmp(this_opt, "vremap:", 7))
++                      vram_remap = simple_strtoul(this_opt + 7, NULL, 0);
++              else if (!strncmp(this_opt, "maxhf:", 6))
++                      maxhf = simple_strtoul(this_opt + 6, NULL, 0);
++              else if (!strncmp(this_opt, "maxvf:", 6))
++                      maxvf = simple_strtoul(this_opt + 6, NULL, 0);
++              else if (!strncmp(this_opt, "maxclk:", 7))
++                      maxclk = simple_strtoul(this_opt + 7, NULL, 0);
++              else if (!strncmp(this_opt, "vbemode:", 8))
++                      vbemode = simple_strtoul(this_opt + 8, NULL, 0);
++              else if (this_opt[0] >= '0' && this_opt[0] <= '9') {
++                      mode_option = this_opt;
++              } else {
++                      printk(KERN_WARNING
++                              "uvesafb: unrecognized option %s\n", this_opt);
++              }
++      }
++
++      return 0;
++}
++#endif /* !MODULE */
++
++static ssize_t show_v86d(struct device_driver *dev, char *buf)
++{
++      return snprintf(buf, PAGE_SIZE, "%s\n", v86d_path);
++}
++
++static ssize_t store_v86d(struct device_driver *dev, const char *buf,
++              size_t count)
++{
++      strncpy(v86d_path, buf, PATH_MAX);
++      return count;
++}
++
++static DRIVER_ATTR(v86d, S_IRUGO | S_IWUSR, show_v86d, store_v86d);
++
++static int __devinit uvesafb_init(void)
++{
++      int err;
++
++#ifndef MODULE
++      char *option = NULL;
++
++      if (fb_get_options("uvesafb", &option))
++              return -ENODEV;
++      uvesafb_setup(option);
++#endif
++      err = cn_add_callback(&uvesafb_cn_id, "uvesafb", uvesafb_cn_callback);
++      if (err)
++              return err;
++
++      err = platform_driver_register(&uvesafb_driver);
++
++      if (!err) {
++              uvesafb_device = platform_device_alloc("uvesafb", 0);
++              if (uvesafb_device)
++                      err = platform_device_add(uvesafb_device);
++              else
++                      err = -ENOMEM;
++
++              if (err) {
++                      platform_device_put(uvesafb_device);
++                      platform_driver_unregister(&uvesafb_driver);
++                      cn_del_callback(&uvesafb_cn_id);
++                      return err;
++              }
++
++              err = driver_create_file(&uvesafb_driver.driver,
++                              &driver_attr_v86d);
++              if (err) {
++                      printk(KERN_WARNING "uvesafb: failed to register "
++                                      "attributes\n");
++                      err = 0;
++              }
++      }
++      return err;
++}
++
++module_init(uvesafb_init);
++
++static void __devexit uvesafb_exit(void)
++{
++      struct uvesafb_ktask *task;
++
++      if (v86d_started) {
++              task = uvesafb_prep();
++              if (task) {
++                      task->t.flags = TF_EXIT;
++                      uvesafb_exec(task);
++                      uvesafb_free(task);
++              }
++      }
++
++      cn_del_callback(&uvesafb_cn_id);
++      driver_remove_file(&uvesafb_driver.driver, &driver_attr_v86d);
++      platform_device_unregister(uvesafb_device);
++      platform_driver_unregister(&uvesafb_driver);
++}
++
++module_exit(uvesafb_exit);
++
++static inline int param_get_scroll(char *buffer, struct kernel_param *kp)
++{
++      return 0;
++}
++
++static inline int param_set_scroll(const char *val, struct kernel_param *kp)
++{
++      ypan = 0;
++
++      if (!strcmp(val, "redraw"))
++              ypan = 0;
++      else if (!strcmp(val, "ypan"))
++              ypan = 1;
++      else if (!strcmp(val, "ywrap"))
++              ypan = 2;
++
++      return 0;
++}
++
++#define param_check_scroll(name, p) __param_check(name, p, void);
++
++module_param_named(scroll, ypan, scroll, 0);
++MODULE_PARM_DESC(scroll,
++      "Scrolling mode, set to 'redraw', ''ypan' or 'ywrap'");
++module_param_named(vgapal, pmi_setpal, invbool, 0);
++MODULE_PARM_DESC(vgapal, "Set palette using VGA registers");
++module_param_named(pmipal, pmi_setpal, bool, 0);
++MODULE_PARM_DESC(pmipal, "Set palette using PMI calls");
++module_param(mtrr, uint, 0);
++MODULE_PARM_DESC(mtrr,
++      "Memory Type Range Registers setting. Use 0 to disable.");
++module_param(blank, bool, 0);
++MODULE_PARM_DESC(blank, "Enable hardware blanking");
++module_param(nocrtc, bool, 0);
++MODULE_PARM_DESC(nocrtc, "Ignore CRTC timings when setting modes");
++module_param(noedid, bool, 0);
++MODULE_PARM_DESC(noedid,
++      "Ignore EDID-provided monitor limits when setting modes");
++module_param(vram_remap, uint, 0);
++MODULE_PARM_DESC(vram_remap, "Set amount of video memory to be used [MiB]");
++module_param(vram_total, uint, 0);
++MODULE_PARM_DESC(vram_total, "Set total amount of video memoery [MiB]");
++module_param(maxclk, ushort, 0);
++MODULE_PARM_DESC(maxclk, "Maximum pixelclock [MHz], overrides EDID data");
++module_param(maxhf, ushort, 0);
++MODULE_PARM_DESC(maxhf,
++      "Maximum horizontal frequency [kHz], overrides EDID data");
++module_param(maxvf, ushort, 0);
++MODULE_PARM_DESC(maxvf,
++      "Maximum vertical frequency [Hz], overrides EDID data");
++module_param_named(mode, mode_option, charp, 0);
++MODULE_PARM_DESC(mode,
++      "Specify initial video mode as \"<xres>x<yres>[-<bpp>][@<refresh>]\"");
++module_param(vbemode, ushort, 0);
++MODULE_PARM_DESC(vbemode,
++      "VBE mode number to set, overrides the 'mode' option");
++module_param_string(v86d, v86d_path, PATH_MAX, 0660);
++MODULE_PARM_DESC(v86d, "Path to the v86d userspace helper.");
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Michal Januszewski <spock@gentoo.org>");
++MODULE_DESCRIPTION("Framebuffer driver for VBE2.0+ compliant graphics boards");
++
+Index: linux-2.6.22/include/linux/connector.h
+===================================================================
+--- linux-2.6.22.orig/include/linux/connector.h        2007-08-28 21:54:13.000000000 +0100
++++ linux-2.6.22/include/linux/connector.h     2007-08-28 21:56:34.000000000 +0100
+@@ -36,14 +36,15 @@
+ #define CN_VAL_CIFS                     0x1
+ #define CN_W1_IDX                     0x3     /* w1 communication */
+ #define CN_W1_VAL                     0x1
++#define CN_IDX_V86D                   0x4
++#define CN_VAL_V86D_UVESAFB           0x1
+-
+-#define CN_NETLINK_USERS              4
++#define CN_NETLINK_USERS              5
+ /*
+  * Maximum connector's message size.
+  */
+-#define CONNECTOR_MAX_MSG_SIZE        1024
++#define CONNECTOR_MAX_MSG_SIZE        16384
+ /*
+  * idx and val are unique identifiers which 
+Index: linux-2.6.22/include/video/Kbuild
+===================================================================
+--- linux-2.6.22.orig/include/video/Kbuild     2007-08-28 21:54:13.000000000 +0100
++++ linux-2.6.22/include/video/Kbuild  2007-08-28 21:56:34.000000000 +0100
+@@ -1 +1 @@
+-unifdef-y += sisfb.h
++unifdef-y += sisfb.h uvesafb.h
+Index: linux-2.6.22/include/video/uvesafb.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/include/video/uvesafb.h       2007-08-28 21:56:34.000000000 +0100
+@@ -0,0 +1,193 @@
++#ifndef _UVESAFB_H
++#define _UVESAFB_H
++
++struct v86_regs {
++      __u32 ebx;
++      __u32 ecx;
++      __u32 edx;
++      __u32 esi;
++      __u32 edi;
++      __u32 ebp;
++      __u32 eax;
++      __u32 eip;
++      __u32 eflags;
++      __u32 esp;
++      __u16 cs;
++      __u16 ss;
++      __u16 es;
++      __u16 ds;
++      __u16 fs;
++      __u16 gs;
++};
++
++/* Task flags */
++#define TF_VBEIB      0x01
++#define TF_BUF_ESDI   0x02
++#define TF_BUF_ESBX   0x04
++#define TF_BUF_RET    0x08
++#define TF_EXIT               0x10
++
++struct uvesafb_task {
++      __u8 flags;
++      int buf_len;
++      struct v86_regs regs;
++};
++
++/* Constants for the capabilities field
++ * in vbe_ib */
++#define VBE_CAP_CAN_SWITCH_DAC        0x01
++#define VBE_CAP_VGACOMPAT     0x02
++
++/* The VBE Info Block */
++struct vbe_ib {
++      char  vbe_signature[4];
++      __u16 vbe_version;
++      __u32 oem_string_ptr;
++      __u32 capabilities;
++      __u32 mode_list_ptr;
++      __u16 total_memory;
++      __u16 oem_software_rev;
++      __u32 oem_vendor_name_ptr;
++      __u32 oem_product_name_ptr;
++      __u32 oem_product_rev_ptr;
++      __u8  reserved[222];
++      char  oem_data[256];
++      char  misc_data[512];
++} __attribute__ ((packed));
++
++#ifdef __KERNEL__
++
++/* VBE CRTC Info Block */
++struct vbe_crtc_ib {
++      u16 horiz_total;
++      u16 horiz_start;
++      u16 horiz_end;
++      u16 vert_total;
++      u16 vert_start;
++      u16 vert_end;
++      u8  flags;
++      u32 pixel_clock;
++      u16 refresh_rate;
++      u8  reserved[40];
++} __attribute__ ((packed));
++
++#define VBE_MODE_VGACOMPAT    0x20
++#define VBE_MODE_COLOR                0x08
++#define VBE_MODE_SUPPORTEDHW  0x01
++#define VBE_MODE_GRAPHICS     0x10
++#define VBE_MODE_LFB          0x80
++
++#define VBE_MODE_MASK         (VBE_MODE_COLOR | VBE_MODE_SUPPORTEDHW | \
++                              VBE_MODE_GRAPHICS | VBE_MODE_LFB)
++
++/* VBE Mode Info Block */
++struct vbe_mode_ib {
++      /* for all VBE revisions */
++      u16 mode_attr;
++      u8  winA_attr;
++      u8  winB_attr;
++      u16 win_granularity;
++      u16 win_size;
++      u16 winA_seg;
++      u16 winB_seg;
++      u32 win_func_ptr;
++      u16 bytes_per_scan_line;
++
++      /* for VBE 1.2+ */
++      u16 x_res;
++      u16 y_res;
++      u8  x_char_size;
++      u8  y_char_size;
++      u8  planes;
++      u8  bits_per_pixel;
++      u8  banks;
++      u8  memory_model;
++      u8  bank_size;
++      u8  image_pages;
++      u8  reserved1;
++
++      /* Direct color fields for direct/6 and YUV/7 memory models. */
++      /* Offsets are bit positions of lsb in the mask. */
++      u8  red_len;
++      u8  red_off;
++      u8  green_len;
++      u8  green_off;
++      u8  blue_len;
++      u8  blue_off;
++      u8  rsvd_len;
++      u8  rsvd_off;
++      u8  direct_color_info;  /* direct color mode attributes */
++
++      /* for VBE 2.0+ */
++      u32 phys_base_ptr;
++      u8  reserved2[6];
++
++      /* for VBE 3.0+ */
++      u16 lin_bytes_per_scan_line;
++      u8  bnk_image_pages;
++      u8  lin_image_pages;
++      u8  lin_red_len;
++      u8  lin_red_off;
++      u8  lin_green_len;
++      u8  lin_green_off;
++      u8  lin_blue_len;
++      u8  lin_blue_off;
++      u8  lin_rsvd_len;
++      u8  lin_rsvd_off;
++      u32 max_pixel_clock;
++      u16 mode_id;
++      u8  depth;
++} __attribute__ ((packed));
++
++#define UVESAFB_DEFAULT_MODE "640x480-16"
++
++/* How long to wait for a reply from userspace [ms] */
++#define UVESAFB_TIMEOUT 5000
++
++/* Max number of concurrent tasks */
++#define UVESAFB_TASKS_MAX 16
++
++#define dac_reg       (0x3c8)
++#define dac_val       (0x3c9)
++
++struct uvesafb_pal_entry {
++      u_char blue, green, red, pad;
++} __attribute__ ((packed));
++
++struct uvesafb_ktask {
++      struct uvesafb_task t;
++      void *buf;
++      struct completion *done;
++      u32 ack;
++};
++
++static int uvesafb_exec(struct uvesafb_ktask *tsk);
++
++#define UVESAFB_EXACT_RES     1
++#define UVESAFB_EXACT_DEPTH   2
++
++struct uvesafb_par {
++      struct vbe_ib vbe_ib;           /* VBE Info Block */
++      struct vbe_mode_ib *vbe_modes;  /* list of supported VBE modes */
++      int vbe_modes_cnt;
++
++      u8 nocrtc;
++      u8 ypan;                        /* 0 - nothing, 1 - ypan, 2 - ywrap */
++      u8 pmi_setpal;                  /* PMI for palette changes */
++      u16 *pmi_base;                  /* protected mode interface location */
++      void *pmi_start;
++      void *pmi_pal;
++      u8 *vbe_state_orig;             /*
++                                       * original hardware state, before the
++                                       * driver was loaded
++                                       */
++      u8 *vbe_state_saved;            /* state saved by fb_save_state */
++      int vbe_state_size;
++      atomic_t ref_count;
++
++      int mode_idx;
++      struct vbe_crtc_ib crtc;
++};
++
++#endif /* __KERNEL__ */
++#endif /* _UVESAFB_H */
diff --git a/packages/kexecboot/linux-kexecboot-2.6.23/versatile-armv6.patch b/packages/kexecboot/linux-kexecboot-2.6.23/versatile-armv6.patch
new file mode 100644 (file)
index 0000000..e2d0060
--- /dev/null
@@ -0,0 +1,19 @@
+---
+ arch/arm/mm/Kconfig |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- linux-2.6.23.orig/arch/arm/mm/Kconfig
++++ linux-2.6.23/arch/arm/mm/Kconfig
+@@ -343,11 +343,11 @@ config CPU_XSC3
+       select IO_36
+ # ARMv6
+ config CPU_V6
+       bool "Support ARM V6 processor"
+-      depends on ARCH_INTEGRATOR || MACH_REALVIEW_EB || ARCH_OMAP2 || ARCH_MX3
++      depends on ARCH_INTEGRATOR || MACH_REALVIEW_EB || ARCH_OMAP2 || ARCH_MX3 || ARCH_VERSATILE_PB
+       default y if ARCH_MX3
+       select CPU_32v6
+       select CPU_ABRT_EV6
+       select CPU_CACHE_V6
+       select CPU_CACHE_VIPT
diff --git a/packages/kexecboot/linux-kexecboot-2.6.23/wm8750-treble.patch b/packages/kexecboot/linux-kexecboot-2.6.23/wm8750-treble.patch
new file mode 100644 (file)
index 0000000..07a8d8e
--- /dev/null
@@ -0,0 +1,11 @@
+--- linux-2.6.23/sound/soc/codecs/wm8750.c     2007-10-09 22:31:38.000000000 +0200
++++ linux-2.6.23/sound/soc/codecs/wm8750.c     2007-11-02 16:47:35.000000000 +0100
+@@ -189,7 +189,7 @@
+ SOC_ENUM("Bass Filter", wm8750_enum[1]),
+ SOC_SINGLE("Bass Volume", WM8750_BASS, 0, 15, 1),
+-SOC_SINGLE("Treble Volume", WM8750_TREBLE, 0, 15, 0),
++SOC_SINGLE("Treble Volume", WM8750_TREBLE, 0, 15, 1),
+ SOC_ENUM("Treble Cut-off", wm8750_enum[2]),
+ SOC_SINGLE("3D Switch", WM8750_3D, 0, 1, 0),
diff --git a/packages/kexecboot/linux-kexecboot-2.6.23/wm9712-reset-loop-r2.patch b/packages/kexecboot/linux-kexecboot-2.6.23/wm9712-reset-loop-r2.patch
new file mode 100644 (file)
index 0000000..78e81ea
--- /dev/null
@@ -0,0 +1,44 @@
+ sound/soc/codecs/wm9712.c |   28 ++++++++++++++++++----------
+ 1 file changed, 18 insertions(+), 10 deletions(-)
+
+Index: git/sound/soc/codecs/wm9712.c
+===================================================================
+--- git.orig/sound/soc/codecs/wm9712.c 2006-11-07 22:10:01.000000000 +0000
++++ git/sound/soc/codecs/wm9712.c      2006-11-07 22:11:50.000000000 +0000
+@@ -618,18 +618,26 @@ static int wm9712_dapm_event(struct snd_
+ static int wm9712_reset(struct snd_soc_codec *codec, int try_warm)
+ {
+-      if (try_warm && soc_ac97_ops.warm_reset) {
+-              soc_ac97_ops.warm_reset(codec->ac97);
+-              if (!(ac97_read(codec, 0) & 0x8000))
+-                      return 1;
+-      }
++      int retry = 3;
+-      soc_ac97_ops.reset(codec->ac97);
+-      if (ac97_read(codec, 0) & 0x8000)
+-              goto err;
+-      return 0;
++      while (retry--)
++      {
++              if(try_warm && soc_ac97_ops.warm_reset) {
++                      soc_ac97_ops.warm_reset(codec->ac97);
++                      if(ac97_read(codec, 0) & 0x8000)
++                              continue;
++                      else
++                              return 1;
++              }
++
++              soc_ac97_ops.reset(codec->ac97);
++              if(ac97_read(codec, 0) & 0x8000)
++                      continue;
++              else
++                      return 0;
++
++      }
+-err:
+       printk(KERN_ERR "WM9712 AC97 reset failed\n");
+       return -EIO;
+ }
diff --git a/packages/kexecboot/linux-kexecboot-2.6.23/wm9712-suspend-cold-res-r2.patch b/packages/kexecboot/linux-kexecboot-2.6.23/wm9712-suspend-cold-res-r2.patch
new file mode 100644 (file)
index 0000000..5179b47
--- /dev/null
@@ -0,0 +1,16 @@
+ sound/soc/codecs/wm9712.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+Index: git/sound/soc/codecs/wm9712.c
+===================================================================
+--- git.orig/sound/soc/codecs/wm9712.c 2006-11-07 21:57:34.000000000 +0000
++++ git/sound/soc/codecs/wm9712.c      2006-11-07 21:59:30.000000000 +0000
+@@ -651,7 +651,7 @@ static int wm9712_soc_resume(struct plat
+       int i, ret;
+       u16 *cache = codec->reg_cache;
+-      ret = wm9712_reset(codec, 1);
++      ret = wm9712_reset(codec, 0);
+       if (ret < 0){
+               printk(KERN_ERR "could not reset AC97 codec\n");
+               return ret;
diff --git a/packages/kexecboot/linux-kexecboot-2.6.23/wm97xx-lg13-r0-fix-r0.patch b/packages/kexecboot/linux-kexecboot-2.6.23/wm97xx-lg13-r0-fix-r0.patch
new file mode 100644 (file)
index 0000000..5ad0d87
--- /dev/null
@@ -0,0 +1,128 @@
+ drivers/input/power.c                   |    2 +-
+ drivers/input/touchscreen/Kconfig       |    2 +-
+ drivers/input/touchscreen/wm97xx-core.c |   35 ++++++++++++++++---------------
+ include/linux/wm97xx.h                  |    2 +-
+ 4 files changed, 21 insertions(+), 20 deletions(-)
+
+diff --git a/drivers/input/power.c b/drivers/input/power.c
+index 4443e34..7aac875 100644
+--- a/drivers/input/power.c
++++ b/drivers/input/power.c
+@@ -156,7 +156,7 @@ static void power_event(struct input_handle *handle, unsigned int type,
+       }
+ }
+-static struct input_handle *power_connect(struct input_handler *handler,
++static int power_connect(struct input_handler *handler,
+                                         struct input_dev *dev,
+                                         const struct input_device_id *id)
+ {
+diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
+index 6862e8f..9b532e9 100644
+--- a/drivers/input/touchscreen/Kconfig
++++ b/drivers/input/touchscreen/Kconfig
+@@ -247,7 +247,7 @@ config TOUCHSCREEN_TSC2101
+ config TOUCHSCREEN_WM97XX
+       tristate "Support for WM97xx AC97 touchscreen controllers"
+-      depends SND_AC97_BUS
++      depends AC97_BUS
+ choice
+       prompt "WM97xx codec type"
+diff --git a/drivers/input/touchscreen/wm97xx-core.c b/drivers/input/touchscreen/wm97xx-core.c
+index 9b2710e..d3ce3f3 100644
+--- a/drivers/input/touchscreen/wm97xx-core.c
++++ b/drivers/input/touchscreen/wm97xx-core.c
+@@ -84,6 +84,7 @@
+ #include <linux/bitops.h>
+ #include <linux/workqueue.h>
+ #include <linux/device.h>
++#include <linux/freezer.h>
+ #include <linux/wm97xx.h>
+ #include <asm/uaccess.h>
+ #include <asm/io.h>
+@@ -241,14 +242,15 @@ WM97XX_STATUS_ATTR(gpio);
+ static int wm97xx_sys_add(struct device *dev)
+ {
++      int err;
+       if (aux_sys) {
+-              device_create_file(dev, &dev_attr_aux1);
+-              device_create_file(dev, &dev_attr_aux2);
+-              device_create_file(dev, &dev_attr_aux3);
+-              device_create_file(dev, &dev_attr_aux4);
++              err = device_create_file(dev, &dev_attr_aux1);    
++              err = device_create_file(dev, &dev_attr_aux2);
++              err = device_create_file(dev, &dev_attr_aux3);
++              err = device_create_file(dev, &dev_attr_aux4);
+       }
+       if (status_sys)
+-              device_create_file(dev, &dev_attr_gpio);
++              err = device_create_file(dev, &dev_attr_gpio);
+       return 0;
+ }
+@@ -366,12 +368,12 @@ void wm97xx_config_gpio(struct wm97xx *wm, u32 gpio, wm97xx_gpio_dir_t dir,
+ /*
+  * Handle a pen down interrupt.
+- */
+-static void wm97xx_pen_irq_worker(void *ptr)
+-{
+-      struct wm97xx *wm = (struct wm97xx *) ptr;
+-
+-      /* do we need to enable the touch panel reader */
++ */ 
++static void wm97xx_pen_irq_worker(struct work_struct *work) 
++{                  
++      struct wm97xx *wm = container_of(work, struct wm97xx, pen_event_work);
++      
++      /* do we need to enable the touch panel reader */ 
+       if (wm->id == WM9705_ID2) {
+               if (wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD) & WM97XX_PEN_DOWN)
+                       wm->pen_is_down = 1;
+@@ -411,9 +413,8 @@ static void wm97xx_pen_irq_worker(void *ptr)
+  * We have to disable the codec interrupt in the handler because it can
+  * take upto 1ms to clear the interrupt source. The interrupt is then enabled
+  * again in the slow handler when the source has been cleared.
+- */
+-static irqreturn_t wm97xx_pen_interrupt(int irq, void *dev_id,
+-                                      struct pt_regs *regs)
++ */ 
++static irqreturn_t wm97xx_pen_interrupt(int irq, void *dev_id)
+ {
+       struct wm97xx *wm = (struct wm97xx *) dev_id;
+       disable_irq(wm->pen_irq);
+@@ -428,15 +429,15 @@ static int wm97xx_init_pen_irq(struct wm97xx *wm)
+ {
+       u16 reg;
+-      INIT_WORK(&wm->pen_event_work, wm97xx_pen_irq_worker, wm);
+-      if ((wm->pen_irq_workq =
++      INIT_WORK(&wm->pen_event_work, wm97xx_pen_irq_worker);
++      if ((wm->pen_irq_workq = 
+               create_singlethread_workqueue("kwm97pen")) == NULL) {
+               err("could not create pen irq work queue");
+               wm->pen_irq = 0;
+               return -EINVAL;
+       }
+-      if (request_irq (wm->pen_irq, wm97xx_pen_interrupt, SA_SHIRQ, "wm97xx-pen", wm)) {
++      if (request_irq (wm->pen_irq, wm97xx_pen_interrupt, IRQF_SHARED, "wm97xx-pen", wm)) {
+               err("could not register codec pen down interrupt, will poll for pen down");
+               destroy_workqueue(wm->pen_irq_workq);
+               wm->pen_irq = 0;
+diff --git a/include/linux/wm97xx.h b/include/linux/wm97xx.h
+index b1c1740..a9bd57e 100644
+--- a/include/linux/wm97xx.h
++++ b/include/linux/wm97xx.h
+@@ -243,7 +243,7 @@ struct wm97xx {
+       u16 dig_save[3];                /* saved during aux reading */
+       struct wm97xx_codec_drv *codec; /* attached codec driver*/
+       struct input_dev* input_dev;    /* touchscreen input device */
+-      ac97_t *ac97;                   /* ALSA codec access */
++      struct snd_ac97 *ac97;                  /* ALSA codec access */
+       struct device *dev;             /* ALSA device */
+     struct device *battery_dev;
+     struct device *touch_dev;
diff --git a/packages/kexecboot/linux-kexecboot-2.6.23/wm97xx-lg13-r0.patch b/packages/kexecboot/linux-kexecboot-2.6.23/wm97xx-lg13-r0.patch
new file mode 100644 (file)
index 0000000..c918c5d
--- /dev/null
@@ -0,0 +1,2899 @@
+Index: linux-2.6.17/drivers/input/touchscreen/Kconfig
+===================================================================
+--- linux-2.6.17.orig/drivers/input/touchscreen/Kconfig        2006-09-19 20:35:35.060495500 +0200
++++ linux-2.6.17/drivers/input/touchscreen/Kconfig     2006-09-19 20:36:47.965051750 +0200
+@@ -121,4 +121,57 @@ config TOUCHSCREEN_TSC2101
+         To compile this driver as a module, choose M here: the
+         module will be called ads7846_ts.
++config TOUCHSCREEN_WM97XX
++      tristate "Support for WM97xx AC97 touchscreen controllers"
++      depends SND_AC97_BUS
++
++choice
++      prompt "WM97xx codec type"
++
++config TOUCHSCREEN_WM9705
++      bool "WM9705 Touchscreen interface support"
++      depends on TOUCHSCREEN_WM97XX
++      help
++        Say Y here if you have the wm9705 touchscreen.
++
++        If unsure, say N.
++
++        To compile this driver as a module, choose M here: the
++        module will be called wm9705.
++
++config TOUCHSCREEN_WM9712
++      bool "WM9712 Touchscreen interface support"
++      depends on TOUCHSCREEN_WM97XX
++      help
++        Say Y here if you have the wm9712 touchscreen.
++
++        If unsure, say N.
++
++        To compile this driver as a module, choose M here: the
++        module will be called wm9712.
++
++config TOUCHSCREEN_WM9713
++      bool "WM9713 Touchscreen interface support"
++      depends on TOUCHSCREEN_WM97XX
++      help
++        Say Y here if you have the wm9713 touchscreen.
++
++        If unsure, say N.
++
++        To compile this driver as a module, choose M here: the
++        module will be called wm9713.
++
++endchoice
++
++config TOUCHSCREEN_WM97XX_PXA
++      tristate "WM97xx PXA accelerated touch"
++      depends on TOUCHSCREEN_WM97XX && ARCH_PXA
++      help
++        Say Y here for continuous mode touch on the PXA
++
++        If unsure, say N
++
++        To compile this driver as a module, choose M here: the
++        module will be called pxa-wm97xx
++
+ endif
+Index: linux-2.6.17/drivers/input/touchscreen/Makefile
+===================================================================
+--- linux-2.6.17.orig/drivers/input/touchscreen/Makefile       2006-09-19 20:35:35.072496250 +0200
++++ linux-2.6.17/drivers/input/touchscreen/Makefile    2006-09-19 20:37:40.540337500 +0200
+@@ -4,6 +4,8 @@
+ # Each configuration option enables a list of files.
++wm97xx-ts-objs := wm97xx-core.o
++
+ obj-$(CONFIG_TOUCHSCREEN_ADS7846)     += ads7846.o
+ obj-$(CONFIG_TOUCHSCREEN_BITSY)       += h3600_ts_input.o
+ obj-$(CONFIG_TOUCHSCREEN_CORGI)       += corgi_ts.o
+@@ -13,3 +15,16 @@ obj-$(CONFIG_TOUCHSCREEN_MTOUCH) += mtou
+ obj-$(CONFIG_TOUCHSCREEN_MK712)       += mk712.o
+ obj-$(CONFIG_TOUCHSCREEN_HP600)       += hp680_ts_input.o
+ obj-$(CONFIG_TOUCHSCREEN_TSC2101)     += tsc2101_ts.o
++obj-$(CONFIG_TOUCHSCREEN_WM97XX)      += wm97xx-ts.o
++obj-$(CONFIG_TOUCHSCREEN_WM97XX_PXA)    += pxa-wm97xx.o
++
++ifeq ($(CONFIG_TOUCHSCREEN_WM9713),y)
++wm97xx-ts-objs += wm9713.o
++endif
++
++ifeq ($(CONFIG_TOUCHSCREEN_WM9712),y)
++wm97xx-ts-objs += wm9712.o
++endif
++ifeq ($(CONFIG_TOUCHSCREEN_WM9705),y)
++wm97xx-ts-objs += wm9705.o
++endif
+Index: linux-2.6.17/drivers/input/touchscreen/pxa-wm97xx.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.17/drivers/input/touchscreen/pxa-wm97xx.c        2006-09-19 20:36:47.965051750 +0200
+@@ -0,0 +1,289 @@
++/*
++ * pxa-wm97xx.c  --  pxa-wm97xx Continuous Touch screen driver for
++ *                   Wolfson WM97xx AC97 Codecs.
++ *
++ * Copyright 2004 Wolfson Microelectronics PLC.
++ * Author: Liam Girdwood
++ *         liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
++ * Parts Copyright : Ian Molton <spyro@f2s.com>
++ *                   Andrew Zabolotny <zap@homelink.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.
++ *
++ * Notes:
++ *     This is a wm97xx extended touch driver to capture touch
++ *     data in a continuous manner on the Intel XScale archictecture
++ *
++ *  Features:
++ *       - codecs supported:- WM9705, WM9712, WM9713
++ *       - processors supported:- Intel XScale PXA25x, PXA26x, PXA27x
++ *
++ *  Revision history
++ *    18th Aug 2004   Initial version.
++ *    26th Jul 2005   Improved continous read back and added FIFO flushing.
++ *    06th Sep 2005   Mike Arthur <linux@wolfsonmicro.com>
++ *                    Moved to using the wm97xx bus
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/irq.h>
++#include <linux/wm97xx.h>
++#include <asm/io.h>
++#include <asm/arch/pxa-regs.h>
++
++#define VERSION               "0.13"
++
++struct continuous {
++      u16 id;    /* codec id */
++      u8 code;   /* continuous code */
++      u8 reads;  /* number of coord reads per read cycle */
++      u32 speed; /* number of coords per second */
++};
++
++#define WM_READS(sp) ((sp / HZ) + 1)
++
++static const struct continuous cinfo[] = {
++      {WM9705_ID2, 0, WM_READS(94), 94},
++      {WM9705_ID2, 1, WM_READS(188), 188},
++      {WM9705_ID2, 2, WM_READS(375), 375},
++      {WM9705_ID2, 3, WM_READS(750), 750},
++      {WM9712_ID2, 0, WM_READS(94), 94},
++      {WM9712_ID2, 1, WM_READS(188), 188},
++      {WM9712_ID2, 2, WM_READS(375), 375},
++      {WM9712_ID2, 3, WM_READS(750), 750},
++      {WM9713_ID2, 0, WM_READS(94), 94},
++      {WM9713_ID2, 1, WM_READS(120), 120},
++      {WM9713_ID2, 2, WM_READS(154), 154},
++      {WM9713_ID2, 3, WM_READS(188), 188},
++};
++
++/* continuous speed index */
++static int sp_idx = 0;
++static u16 last = 0, tries = 0;
++
++/*
++ * Pen sampling frequency (Hz) in continuous mode.
++ */
++static int cont_rate = 200;
++module_param(cont_rate, int, 0);
++MODULE_PARM_DESC(cont_rate, "Sampling rate in continuous mode (Hz)");
++
++/*
++ * Pen down detection.
++ *
++ * This driver can either poll or use an interrupt to indicate a pen down
++ * event. If the irq request fails then it will fall back to polling mode.
++ */
++static int pen_int = 1;
++module_param(pen_int, int, 0);
++MODULE_PARM_DESC(pen_int, "Pen down detection (1 = interrupt, 0 = polling)");
++
++/*
++ * Pressure readback.
++ *
++ * Set to 1 to read back pen down pressure
++ */
++static int pressure = 0;
++module_param(pressure, int, 0);
++MODULE_PARM_DESC(pressure, "Pressure readback (1 = pressure, 0 = no pressure)");
++
++/*
++ * AC97 touch data slot.
++ *
++ * Touch screen readback data ac97 slot
++ */
++static int ac97_touch_slot = 5;
++module_param(ac97_touch_slot, int, 0);
++MODULE_PARM_DESC(ac97_touch_slot, "Touch screen data slot AC97 number");
++
++
++/* flush AC97 slot 5 FIFO on pxa machines */
++#ifdef CONFIG_PXA27x
++void wm97xx_acc_pen_up (struct wm97xx* wm)
++{
++      set_current_state(TASK_INTERRUPTIBLE);
++      schedule_timeout(1);
++
++      while (MISR & (1 << 2))
++              MODR;
++}
++#else
++void wm97xx_acc_pen_up (struct wm97xx* wm)
++{
++      int count = 16;
++      set_current_state(TASK_INTERRUPTIBLE);
++      schedule_timeout(1);
++
++      while (count < 16) {
++              MODR;
++              count--;
++      }
++}
++#endif
++
++int wm97xx_acc_pen_down (struct wm97xx* wm)
++{
++      u16 x, y, p = 0x100 | WM97XX_ADCSEL_PRES;
++      int reads = 0;
++
++      /* data is never immediately available after pen down irq */
++      set_current_state(TASK_INTERRUPTIBLE);
++      schedule_timeout(1);
++
++      if (tries > 5){
++              tries = 0;
++              return RC_PENUP;
++      }
++
++      x = MODR;
++      if (x == last) {
++              tries++;
++              return RC_AGAIN;
++      }
++      last = x;
++      do {
++              if (reads)
++                      x= MODR;
++              y= MODR;
++              if (pressure)
++                      p = MODR;
++
++              /* are samples valid */
++              if ((x & 0x7000) != WM97XX_ADCSEL_X ||
++                      (y & 0x7000) != WM97XX_ADCSEL_Y ||
++                      (p & 0x7000) != WM97XX_ADCSEL_PRES)
++                      goto up;
++
++              /* coordinate is good */
++              tries = 0;
++              //printk("x %x y %x p %x\n", x,y,p);
++              input_report_abs (wm->input_dev, ABS_X, x & 0xfff);
++              input_report_abs (wm->input_dev, ABS_Y, y & 0xfff);
++              input_report_abs (wm->input_dev, ABS_PRESSURE, p & 0xfff);
++              input_sync (wm->input_dev);
++              reads++;
++      } while (reads < cinfo[sp_idx].reads);
++up:
++      return RC_PENDOWN | RC_AGAIN;
++}
++
++int wm97xx_acc_startup(struct wm97xx* wm)
++{
++      int idx = 0;
++
++      /* check we have a codec */
++      if (wm->ac97 == NULL)
++              return -ENODEV;
++
++      /* Go you big red fire engine */
++      for (idx = 0; idx < ARRAY_SIZE(cinfo); idx++) {
++              if (wm->id != cinfo[idx].id)
++                      continue;
++              sp_idx = idx;
++              if (cont_rate <= cinfo[idx].speed)
++                      break;
++      }
++      wm->acc_rate = cinfo[sp_idx].code;
++      wm->acc_slot = ac97_touch_slot;
++      printk(KERN_INFO "pxa2xx accelerated touchscreen driver, %d samples (sec)\n",
++              cinfo[sp_idx].speed);
++
++      /* codec specific irq config */
++      if (pen_int) {
++              switch (wm->id) {
++                      case WM9705_ID2:
++                              wm->pen_irq = IRQ_GPIO(4);
++                              set_irq_type(IRQ_GPIO(4), IRQT_BOTHEDGE);
++                              break;
++                      case WM9712_ID2:
++                      case WM9713_ID2:
++                              /* enable pen down interrupt */
++                              /* use PEN_DOWN GPIO 13 to assert IRQ on GPIO line 2 */
++                              wm->pen_irq = MAINSTONE_AC97_IRQ;
++                              wm97xx_config_gpio(wm, WM97XX_GPIO_13, WM97XX_GPIO_IN,
++                                      WM97XX_GPIO_POL_HIGH, WM97XX_GPIO_STICKY, WM97XX_GPIO_WAKE);
++                              wm97xx_config_gpio(wm, WM97XX_GPIO_2, WM97XX_GPIO_OUT,
++                                      WM97XX_GPIO_POL_HIGH, WM97XX_GPIO_NOTSTICKY, WM97XX_GPIO_NOWAKE);
++                              break;
++                      default:
++                              printk(KERN_WARNING "pen down irq not supported on this device\n");
++                              pen_int = 0;
++                              break;
++              }
++      }
++
++      return 0;
++}
++
++void wm97xx_acc_shutdown(struct wm97xx* wm)
++{
++    /* codec specific deconfig */
++      if (pen_int) {
++              switch (wm->id & 0xffff) {
++                      case WM9705_ID2:
++                              wm->pen_irq = 0;
++                              break;
++                      case WM9712_ID2:
++                      case WM9713_ID2:
++                              /* disable interrupt */
++                              wm->pen_irq = 0;
++                              break;
++              }
++      }
++}
++
++static struct wm97xx_mach_ops pxa_mach_ops = {
++      .acc_enabled = 1,
++      .acc_pen_up = wm97xx_acc_pen_up,
++    .acc_pen_down = wm97xx_acc_pen_down,
++    .acc_startup = wm97xx_acc_startup,
++    .acc_shutdown = wm97xx_acc_shutdown,
++};
++
++int pxa_wm97xx_probe(struct device *dev)
++{
++    struct wm97xx *wm = dev->driver_data;
++    return wm97xx_register_mach_ops (wm, &pxa_mach_ops);
++}
++
++int pxa_wm97xx_remove(struct device *dev)
++{
++      struct wm97xx *wm = dev->driver_data;
++    wm97xx_unregister_mach_ops (wm);
++    return 0;
++}
++
++static struct device_driver  pxa_wm97xx_driver = {
++    .name = "wm97xx-touchscreen",
++    .bus = &wm97xx_bus_type,
++    .owner = THIS_MODULE,
++    .probe = pxa_wm97xx_probe,
++    .remove = pxa_wm97xx_remove
++};
++
++static int __init pxa_wm97xx_init(void)
++{
++    return driver_register(&pxa_wm97xx_driver);
++}
++
++static void __exit pxa_wm97xx_exit(void)
++{
++    driver_unregister(&pxa_wm97xx_driver);
++}
++
++module_init(pxa_wm97xx_init);
++module_exit(pxa_wm97xx_exit);
++
++/* Module information */
++MODULE_AUTHOR("Liam Girdwood <liam.girdwood@wolfsonmicro.com>");
++MODULE_DESCRIPTION("wm97xx continuous touch driver for pxa2xx");
++MODULE_LICENSE("GPL");
+Index: linux-2.6.17/drivers/input/touchscreen/wm9705.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.17/drivers/input/touchscreen/wm9705.c    2006-09-19 20:36:47.969052000 +0200
+@@ -0,0 +1,360 @@
++/*
++ * wm9705.c  --  Codec driver for Wolfson WM9705 AC97 Codec.
++ *
++ * Copyright 2003, 2004, 2005, 2006 Wolfson Microelectronics PLC.
++ * Author: Liam Girdwood
++ *         liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
++ * Parts Copyright : Ian Molton <spyro@f2s.com>
++ *                   Andrew Zabolotny <zap@homelink.ru>
++ *                   Russell King <rmk@arm.linux.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 of the  License, or (at your
++ *  option) any later version.
++ *
++ *  Revision history
++ *     6th Sep 2006  Mike Arthur <linux@wolfsonmicro.com>
++ *                   Added pre and post sample calls.
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/input.h>
++#include <linux/delay.h>
++#include <linux/bitops.h>
++#include <linux/wm97xx.h>
++
++#define TS_NAME                       "wm97xx"
++#define WM9705_VERSION                "0.62"
++#define DEFAULT_PRESSURE      0xb0c0
++
++/*
++ * Debug
++ */
++#if 0
++#define dbg(format, arg...) printk(KERN_DEBUG TS_NAME ": " format "\n" , ## arg)
++#else
++#define dbg(format, arg...)
++#endif
++#define err(format, arg...) printk(KERN_ERR TS_NAME ": " format "\n" , ## arg)
++#define info(format, arg...) printk(KERN_INFO TS_NAME ": " format "\n" , ## arg)
++#define warn(format, arg...) printk(KERN_WARNING TS_NAME ": " format "\n" , ## arg)
++
++/*
++ * Module parameters
++ */
++
++/*
++ * Set current used for pressure measurement.
++ *
++ * Set pil = 2 to use 400uA
++ *     pil = 1 to use 200uA and
++ *     pil = 0 to disable pressure measurement.
++ *
++ * This is used to increase the range of values returned by the adc
++ * when measureing touchpanel pressure.
++ */
++static int pil = 0;
++module_param(pil, int, 0);
++MODULE_PARM_DESC(pil, "Set current used for pressure measurement.");
++
++/*
++ * Set threshold for pressure measurement.
++ *
++ * Pen down pressure below threshold is ignored.
++ */
++static int pressure = DEFAULT_PRESSURE & 0xfff;
++module_param(pressure, int, 0);
++MODULE_PARM_DESC(pressure, "Set threshold for pressure measurement.");
++
++/*
++ * Set adc sample delay.
++ *
++ * For accurate touchpanel measurements, some settling time may be
++ * required between the switch matrix applying a voltage across the
++ * touchpanel plate and the ADC sampling the signal.
++ *
++ * This delay can be set by setting delay = n, where n is the array
++ * position of the delay in the array delay_table below.
++ * Long delays > 1ms are supported for completeness, but are not
++ * recommended.
++ */
++static int delay = 4;
++module_param(delay, int, 0);
++MODULE_PARM_DESC(delay, "Set adc sample delay.");
++
++/*
++ * Pen detect comparator threshold.
++ *
++ * 0 to Vmid in 15 steps, 0 = use zero power comparator with Vmid threshold
++ * i.e. 1 =  Vmid/15 threshold
++ *      15 =  Vmid/1 threshold
++ *
++ * Adjust this value if you are having problems with pen detect not
++ * detecting any down events.
++ */
++static int pdd = 8;
++module_param(pdd, int, 0);
++MODULE_PARM_DESC(pdd, "Set pen detect comparator threshold");
++
++/*
++ * Set adc mask function.
++ *
++ * Sources of glitch noise, such as signals driving an LCD display, may feed
++ * through to the touch screen plates and affect measurement accuracy. In
++ * order to minimise this, a signal may be applied to the MASK pin to delay or
++ * synchronise the sampling.
++ *
++ * 0 = No delay or sync
++ * 1 = High on pin stops conversions
++ * 2 = Edge triggered, edge on pin delays conversion by delay param (above)
++ * 3 = Edge triggered, edge on pin starts conversion after delay param
++ */
++static int mask = 0;
++module_param(mask, int, 0);
++MODULE_PARM_DESC(mask, "Set adc mask function.");
++
++/*
++ * ADC sample delay times in uS
++ */
++static const int delay_table[] = {
++      21,    // 1 AC97 Link frames
++      42,    // 2
++      84,    // 4
++      167,   // 8
++      333,   // 16
++      667,   // 32
++      1000,  // 48
++      1333,  // 64
++      2000,  // 96
++      2667,  // 128
++      3333,  // 160
++      4000,  // 192
++      4667,  // 224
++      5333,  // 256
++      6000,  // 288
++      0      // No delay, switch matrix always on
++};
++
++/*
++ * Delay after issuing a POLL command.
++ *
++ * The delay is 3 AC97 link frames + the touchpanel settling delay
++ */
++static inline void poll_delay(int d)
++{
++      udelay (3 * AC97_LINK_FRAME + delay_table [d]);
++}
++
++/*
++ * set up the physical settings of the WM9705
++ */
++static void init_wm9705_phy(struct wm97xx* wm)
++{
++      u16 dig1 = 0, dig2 = WM97XX_RPR;
++
++      /*
++      * mute VIDEO and AUX as they share X and Y touchscreen
++      * inputs on the WM9705
++      */
++      wm97xx_reg_write(wm, AC97_AUX, 0x8000);
++      wm97xx_reg_write(wm, AC97_VIDEO, 0x8000);
++
++      /* touchpanel pressure current*/
++      if  (pil == 2) {
++              dig2 |= WM9705_PIL;
++              dbg("setting pressure measurement current to 400uA.");
++      } else if (pil)
++              dbg("setting pressure measurement current to 200uA.");
++      if(!pil)
++              pressure = 0;
++
++      /* polling mode sample settling delay */
++      if (delay!=4) {
++              if (delay < 0 || delay > 15) {
++                  dbg("supplied delay out of range.");
++                  delay = 4;
++              }
++      }
++      dig1 &= 0xff0f;
++      dig1 |= WM97XX_DELAY(delay);
++      dbg("setting adc sample delay to %d u Secs.", delay_table[delay]);
++
++      /* WM9705 pdd */
++      dig2 |= (pdd & 0x000f);
++      dbg("setting pdd to Vmid/%d", 1 - (pdd & 0x000f));
++
++      /* mask */
++      dig2 |= ((mask & 0x3) << 4);
++
++      wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, dig1);
++      wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2);
++}
++
++static int wm9705_digitiser_ioctl(struct wm97xx* wm, int cmd)
++{
++      switch(cmd) {
++      case WM97XX_DIG_START:
++              wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, wm->dig[2] | WM97XX_PRP_DET_DIG);
++              wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); /* dummy read */
++              break;
++      case WM97XX_DIG_STOP:
++              wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, wm->dig[2] & ~WM97XX_PRP_DET_DIG);
++              break;
++      case WM97XX_AUX_PREPARE:
++              memcpy(wm->dig_save, wm->dig, sizeof(wm->dig));
++              wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, 0);
++              wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, WM97XX_PRP_DET_DIG);
++              break;
++      case WM97XX_DIG_RESTORE:
++              wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, wm->dig_save[1]);
++              wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, wm->dig_save[2]);
++              break;
++      case WM97XX_PHY_INIT:
++              init_wm9705_phy(wm);
++              break;
++      default:
++              return -EINVAL;
++      }
++      return 0;
++}
++
++static inline int is_pden (struct wm97xx* wm)
++{
++      return wm->dig[2] & WM9705_PDEN;
++}
++
++/*
++ * Read a sample from the WM9705 adc in polling mode.
++ */
++static int wm9705_poll_sample (struct wm97xx* wm, int adcsel, int *sample)
++{
++      int timeout = 5 * delay;
++
++      if (!wm->pen_probably_down) {
++              u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
++              if (!(data & WM97XX_PEN_DOWN))
++                      return RC_PENUP;
++              wm->pen_probably_down = 1;
++      }
++
++      /* set up digitiser */
++      if (adcsel & 0x8000)
++              adcsel = ((adcsel & 0x7fff) + 3) << 12;
++
++      if (wm->mach_ops && wm->mach_ops->pre_sample)
++              wm->mach_ops->pre_sample(adcsel);
++      wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, adcsel | WM97XX_POLL | WM97XX_DELAY(delay));
++
++      /* wait 3 AC97 time slots + delay for conversion */
++      poll_delay (delay);
++
++      /* wait for POLL to go low */
++      while ((wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER1) & WM97XX_POLL) && timeout) {
++              udelay(AC97_LINK_FRAME);
++              timeout--;
++      }
++
++      if (timeout <= 0) {
++              /* If PDEN is set, we can get a timeout when pen goes up */
++              if (is_pden(wm))
++                      wm->pen_probably_down = 0;
++              else
++                      dbg ("adc sample timeout");
++              return RC_PENUP;
++      }
++
++      *sample = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
++      if (wm->mach_ops && wm->mach_ops->post_sample)
++              wm->mach_ops->post_sample(adcsel);
++
++      /* check we have correct sample */
++      if ((*sample & WM97XX_ADCSEL_MASK) != adcsel) {
++              dbg ("adc wrong sample, read %x got %x", adcsel,
++              *sample & WM97XX_ADCSEL_MASK);
++              return RC_PENUP;
++      }
++
++      if (!(*sample & WM97XX_PEN_DOWN)) {
++              wm->pen_probably_down = 0;
++              return RC_PENUP;
++      }
++
++      return RC_VALID;
++}
++
++/*
++ * Sample the WM9705 touchscreen in polling mode
++ */
++static int wm9705_poll_touch(struct wm97xx* wm, struct wm97xx_data *data)
++{
++      int rc;
++
++      if ((rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_X, &data->x)) != RC_VALID)
++              return rc;
++      if ((rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_Y, &data->y)) != RC_VALID)
++              return rc;
++      if (pil) {
++              if ((rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_PRES, &data->p)) != RC_VALID)
++                      return rc;
++      } else
++              data->p = DEFAULT_PRESSURE;
++
++      return RC_VALID;
++}
++
++/*
++ * Enable WM9705 continuous mode, i.e. touch data is streamed across an AC97 slot
++ */
++static int wm9705_acc_enable (struct wm97xx* wm, int enable)
++{
++      u16 dig1, dig2;
++      int ret = 0;
++
++      dig1 = wm->dig[1];
++      dig2 = wm->dig[2];
++
++      if (enable) {
++              /* continous mode */
++              if (wm->mach_ops->acc_startup && (ret = wm->mach_ops->acc_startup(wm)) < 0)
++                      return ret;
++              dig1 &= ~(WM97XX_CM_RATE_MASK | WM97XX_ADCSEL_MASK |
++                      WM97XX_DELAY_MASK | WM97XX_SLT_MASK);
++              dig1 |= WM97XX_CTC | WM97XX_COO | WM97XX_SLEN |
++                      WM97XX_DELAY (delay) |
++                      WM97XX_SLT (wm->acc_slot) |
++                      WM97XX_RATE (wm->acc_rate);
++              if (pil)
++                      dig1 |= WM97XX_ADCSEL_PRES;
++              dig2 |= WM9705_PDEN;
++      } else {
++              dig1 &= ~(WM97XX_CTC | WM97XX_COO | WM97XX_SLEN);
++              dig2 &= ~WM9705_PDEN;
++              if (wm->mach_ops->acc_shutdown)
++                      wm->mach_ops->acc_shutdown(wm);
++      }
++
++      wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, dig1);
++      wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2);
++      return ret;
++}
++
++struct wm97xx_codec_drv wm97xx_codec = {
++      .id =   WM9705_ID2,
++      .name = "wm9705",
++      .poll_sample = wm9705_poll_sample,
++      .poll_touch = wm9705_poll_touch,
++      .acc_enable = wm9705_acc_enable,
++      .digitiser_ioctl = wm9705_digitiser_ioctl,
++};
++
++EXPORT_SYMBOL_GPL(wm97xx_codec);
++
++/* Module information */
++MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com");
++MODULE_DESCRIPTION("WM9705 Touch Screen Driver");
++MODULE_LICENSE("GPL");
+Index: linux-2.6.17/drivers/input/touchscreen/wm9712.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.17/drivers/input/touchscreen/wm9712.c    2006-09-19 20:36:47.969052000 +0200
+@@ -0,0 +1,464 @@
++/*
++ * wm9712.c  --  Codec driver for Wolfson WM9712 AC97 Codecs.
++ *
++ * Copyright 2003, 2004, 2005, 2006 Wolfson Microelectronics PLC.
++ * Author: Liam Girdwood
++ *         liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
++ * Parts Copyright : Ian Molton <spyro@f2s.com>
++ *                   Andrew Zabolotny <zap@homelink.ru>
++ *                   Russell King <rmk@arm.linux.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 of the  License, or (at your
++ *  option) any later version.
++ *
++ *  Revision history
++ *     4th Jul 2005  Initial version.
++ *     6th Sep 2006  Mike Arthur <linux@wolfsonmicro.com>
++ *                   Added pre and post sample calls.
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/input.h>
++#include <linux/delay.h>
++#include <linux/bitops.h>
++#include <linux/wm97xx.h>
++
++#define TS_NAME                       "wm97xx"
++#define WM9712_VERSION                "0.61"
++#define DEFAULT_PRESSURE      0xb0c0
++
++/*
++ * Debug
++ */
++#if 0
++#define dbg(format, arg...) printk(KERN_DEBUG TS_NAME ": " format "\n" , ## arg)
++#else
++#define dbg(format, arg...)
++#endif
++#define err(format, arg...) printk(KERN_ERR TS_NAME ": " format "\n" , ## arg)
++#define info(format, arg...) printk(KERN_INFO TS_NAME ": " format "\n" , ## arg)
++#define warn(format, arg...) printk(KERN_WARNING TS_NAME ": " format "\n" , ## arg)
++
++/*
++ * Module parameters
++ */
++
++/*
++ * Set internal pull up for pen detect.
++ *
++ * Pull up is in the range 1.02k (least sensitive) to 64k (most sensitive)
++ * i.e. pull up resistance = 64k Ohms / rpu.
++ *
++ * Adjust this value if you are having problems with pen detect not
++ * detecting any down event.
++ */
++static int rpu = 3;
++module_param(rpu, int, 0);
++MODULE_PARM_DESC(rpu, "Set internal pull up resitor for pen detect.");
++
++/*
++ * Set current used for pressure measurement.
++ *
++ * Set pil = 2 to use 400uA
++ *     pil = 1 to use 200uA and
++ *     pil = 0 to disable pressure measurement.
++ *
++ * This is used to increase the range of values returned by the adc
++ * when measureing touchpanel pressure.
++ */
++static int pil = 0;
++module_param(pil, int, 0);
++MODULE_PARM_DESC(pil, "Set current used for pressure measurement.");
++
++/*
++ * Set threshold for pressure measurement.
++ *
++ * Pen down pressure below threshold is ignored.
++ */
++static int pressure = DEFAULT_PRESSURE & 0xfff;
++module_param(pressure, int, 0);
++MODULE_PARM_DESC(pressure, "Set threshold for pressure measurement.");
++
++/*
++ * Set adc sample delay.
++ *
++ * For accurate touchpanel measurements, some settling time may be
++ * required between the switch matrix applying a voltage across the
++ * touchpanel plate and the ADC sampling the signal.
++ *
++ * This delay can be set by setting delay = n, where n is the array
++ * position of the delay in the array delay_table below.
++ * Long delays > 1ms are supported for completeness, but are not
++ * recommended.
++ */
++static int delay = 3;
++module_param(delay, int, 0);
++MODULE_PARM_DESC(delay, "Set adc sample delay.");
++
++/*
++ * Set five_wire = 1 to use a 5 wire touchscreen.
++ *
++ * NOTE: Five wire mode does not allow for readback of pressure.
++ */
++static int five_wire;
++module_param(five_wire, int, 0);
++MODULE_PARM_DESC(five_wire, "Set to '1' to use 5-wire touchscreen.");
++
++/*
++ * Set adc mask function.
++ *
++ * Sources of glitch noise, such as signals driving an LCD display, may feed
++ * through to the touch screen plates and affect measurement accuracy. In
++ * order to minimise this, a signal may be applied to the MASK pin to delay or
++ * synchronise the sampling.
++ *
++ * 0 = No delay or sync
++ * 1 = High on pin stops conversions
++ * 2 = Edge triggered, edge on pin delays conversion by delay param (above)
++ * 3 = Edge triggered, edge on pin starts conversion after delay param
++ */
++static int mask = 0;
++module_param(mask, int, 0);
++MODULE_PARM_DESC(mask, "Set adc mask function.");
++
++/*
++ * Coordinate Polling Enable.
++ *
++ * Set to 1 to enable coordinate polling. e.g. x,y[,p] is sampled together
++ * for every poll.
++ */
++static int coord = 0;
++module_param(coord, int, 0);
++MODULE_PARM_DESC(coord, "Polling coordinate mode");
++
++/*
++ * ADC sample delay times in uS
++ */
++static const int delay_table[] = {
++      21,    // 1 AC97 Link frames
++      42,    // 2
++      84,    // 4
++      167,   // 8
++      333,   // 16
++      667,   // 32
++      1000,  // 48
++      1333,  // 64
++      2000,  // 96
++      2667,  // 128
++      3333,  // 160
++      4000,  // 192
++      4667,  // 224
++      5333,  // 256
++      6000,  // 288
++      0      // No delay, switch matrix always on
++};
++
++/*
++ * Delay after issuing a POLL command.
++ *
++ * The delay is 3 AC97 link frames + the touchpanel settling delay
++ */
++static inline void poll_delay(int d)
++{
++      udelay (3 * AC97_LINK_FRAME + delay_table [d]);
++}
++
++/*
++ * set up the physical settings of the WM9712
++ */
++static void init_wm9712_phy(struct wm97xx* wm)
++{
++      u16 dig1 = 0;
++      u16 dig2 = WM97XX_RPR | WM9712_RPU(1);
++
++      /* WM9712 rpu */
++      if (rpu) {
++              dig2 &= 0xffc0;
++              dig2 |= WM9712_RPU(rpu);
++              dbg("setting pen detect pull-up to %d Ohms",64000 / rpu);
++      }
++
++      /* touchpanel pressure current*/
++      if (pil == 2) {
++              dig2 |= WM9712_PIL;
++              dbg("setting pressure measurement current to 400uA.");
++      } else if (pil)
++              dbg("setting pressure measurement current to 200uA.");
++      if(!pil)
++              pressure = 0;
++
++      /* WM9712 five wire */
++      if (five_wire) {
++              dig2 |= WM9712_45W;
++              dbg("setting 5-wire touchscreen mode.");
++      }
++
++      /* polling mode sample settling delay */
++      if (delay < 0 || delay > 15) {
++              dbg("supplied delay out of range.");
++              delay = 4;
++      }
++      dig1 &= 0xff0f;
++      dig1 |= WM97XX_DELAY(delay);
++      dbg("setting adc sample delay to %d u Secs.", delay_table[delay]);
++
++      /* mask */
++      dig2 |= ((mask & 0x3) << 6);
++      if (mask) {
++              u16 reg;
++              /* Set GPIO4 as Mask Pin*/
++              reg = wm97xx_reg_read(wm, AC97_MISC_AFE);
++              wm97xx_reg_write(wm, AC97_MISC_AFE, reg | WM97XX_GPIO_4);
++              reg = wm97xx_reg_read(wm, AC97_GPIO_CFG);
++              wm97xx_reg_write(wm, AC97_GPIO_CFG, reg | WM97XX_GPIO_4);
++      }
++
++      /* wait - coord mode */
++      if(coord)
++              dig2 |= WM9712_WAIT;
++
++      wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, dig1);
++      wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2);
++}
++
++static int wm9712_digitiser_ioctl(struct wm97xx* wm, int cmd)
++{
++      u16 dig2 = wm->dig[2];
++
++      switch(cmd) {
++      case WM97XX_DIG_START:
++              wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2 | WM97XX_PRP_DET_DIG);
++              wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); /* dummy read */
++              break;
++      case WM97XX_DIG_STOP:
++              wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2 & ~WM97XX_PRP_DET_DIG);
++              break;
++      case WM97XX_AUX_PREPARE:
++              memcpy(wm->dig_save, wm->dig, sizeof(wm->dig));
++              wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, 0);
++              wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, WM97XX_PRP_DET_DIG);
++              break;
++      case WM97XX_DIG_RESTORE:
++              wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, wm->dig_save[1]);
++              wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, wm->dig_save[2]);
++              break;
++      case WM97XX_PHY_INIT:
++              init_wm9712_phy(wm);
++              break;
++      default:
++              return -EINVAL;
++      }
++      return 0;
++}
++
++static inline int is_pden (struct wm97xx* wm)
++{
++      return wm->dig[2] & WM9712_PDEN;
++}
++
++/*
++ * Read a sample from the WM9712 adc in polling mode.
++ */
++static int wm9712_poll_sample (struct wm97xx* wm, int adcsel, int *sample)
++{
++      int timeout = 5 * delay;
++
++      if (!wm->pen_probably_down) {
++              u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
++              if (!(data & WM97XX_PEN_DOWN))
++                      return RC_PENUP;
++              wm->pen_probably_down = 1;
++      }
++
++      /* set up digitiser */
++      if (adcsel & 0x8000)
++              adcsel = ((adcsel & 0x7fff) + 3) << 12;
++
++      if (wm->mach_ops && wm->mach_ops->pre_sample)
++              wm->mach_ops->pre_sample(adcsel);
++      wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, adcsel | WM97XX_POLL | WM97XX_DELAY(delay));
++
++      /* wait 3 AC97 time slots + delay for conversion */
++      poll_delay (delay);
++
++      /* wait for POLL to go low */
++      while ((wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER1) & WM97XX_POLL) && timeout) {
++              udelay(AC97_LINK_FRAME);
++              timeout--;
++      }
++
++      if (timeout <= 0) {
++              /* If PDEN is set, we can get a timeout when pen goes up */
++              if (is_pden(wm))
++                      wm->pen_probably_down = 0;
++              else
++                      dbg ("adc sample timeout");
++              return RC_PENUP;
++      }
++
++      *sample = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
++      if (wm->mach_ops && wm->mach_ops->post_sample)
++              wm->mach_ops->post_sample(adcsel);
++
++      /* check we have correct sample */
++      if ((*sample & WM97XX_ADCSEL_MASK) != adcsel) {
++              dbg ("adc wrong sample, read %x got %x", adcsel,
++              *sample & WM97XX_ADCSEL_MASK);
++              return RC_PENUP;
++      }
++
++      if (!(*sample & WM97XX_PEN_DOWN)) {
++              wm->pen_probably_down = 0;
++              return RC_PENUP;
++      }
++
++      return RC_VALID;
++}
++
++/*
++ * Read a coord from the WM9712 adc in polling mode.
++ */
++static int wm9712_poll_coord (struct wm97xx* wm, struct wm97xx_data *data)
++{
++      int timeout = 5 * delay;
++
++      if (!wm->pen_probably_down) {
++              u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
++              if (!(data & WM97XX_PEN_DOWN))
++                      return RC_PENUP;
++              wm->pen_probably_down = 1;
++      }
++
++      /* set up digitiser */
++      if (wm->mach_ops && wm->mach_ops->pre_sample)
++              wm->mach_ops->pre_sample(WM97XX_ADCSEL_X | WM97XX_ADCSEL_Y);
++
++      wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1,
++              WM97XX_COO | WM97XX_POLL | WM97XX_DELAY(delay));
++
++      /* wait 3 AC97 time slots + delay for conversion and read x */
++      poll_delay(delay);
++      data->x = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
++      /* wait for POLL to go low */
++      while ((wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER1) & WM97XX_POLL) && timeout) {
++              udelay(AC97_LINK_FRAME);
++              timeout--;
++      }
++
++      if (timeout <= 0) {
++              /* If PDEN is set, we can get a timeout when pen goes up */
++              if (is_pden(wm))
++                      wm->pen_probably_down = 0;
++              else
++                      dbg ("adc sample timeout");
++              return RC_PENUP;
++      }
++
++      /* read back y data */
++      data->y = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
++      if (pil)
++              data->p = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
++      else
++              data->p = DEFAULT_PRESSURE;
++
++      if (wm->mach_ops && wm->mach_ops->post_sample)
++              wm->mach_ops->post_sample(WM97XX_ADCSEL_X | WM97XX_ADCSEL_Y);
++
++      /* check we have correct sample */
++      if (!(data->x & WM97XX_ADCSEL_X) || !(data->y & WM97XX_ADCSEL_Y))
++              goto err;
++      if(pil && !(data->p & WM97XX_ADCSEL_PRES))
++              goto err;
++
++      if (!(data->x & WM97XX_PEN_DOWN)) {
++              wm->pen_probably_down = 0;
++              return RC_PENUP;
++      }
++      return RC_VALID;
++err:
++      return RC_PENUP;
++}
++
++/*
++ * Sample the WM9712 touchscreen in polling mode
++ */
++static int wm9712_poll_touch(struct wm97xx* wm, struct wm97xx_data *data)
++{
++      int rc;
++
++      if(coord) {
++              if((rc = wm9712_poll_coord(wm, data)) != RC_VALID)
++                      return rc;
++      } else {
++              if ((rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_X, &data->x)) != RC_VALID)
++                      return rc;
++
++              if ((rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_Y, &data->y)) != RC_VALID)
++                      return rc;
++
++              if (pil && !five_wire) {
++                      if ((rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_PRES, &data->p)) != RC_VALID)
++                              return rc;
++              } else
++                      data->p = DEFAULT_PRESSURE;
++      }
++      return RC_VALID;
++}
++
++/*
++ * Enable WM9712 continuous mode, i.e. touch data is streamed across an AC97 slot
++ */
++static int wm9712_acc_enable (struct wm97xx* wm, int enable)
++{
++      u16 dig1, dig2;
++      int ret = 0;
++
++      dig1 = wm->dig[1];
++      dig2 = wm->dig[2];
++
++      if (enable) {
++              /* continous mode */
++              if (wm->mach_ops->acc_startup && (ret = wm->mach_ops->acc_startup(wm)) < 0)
++                      return ret;
++              dig1 &= ~(WM97XX_CM_RATE_MASK | WM97XX_ADCSEL_MASK |
++                      WM97XX_DELAY_MASK | WM97XX_SLT_MASK);
++              dig1 |= WM97XX_CTC | WM97XX_COO | WM97XX_SLEN |
++                      WM97XX_DELAY (delay) |
++                      WM97XX_SLT (wm->acc_slot) |
++                      WM97XX_RATE (wm->acc_rate);
++              if (pil)
++                      dig1 |= WM97XX_ADCSEL_PRES;
++              dig2 |= WM9712_PDEN;
++      } else {
++              dig1 &= ~(WM97XX_CTC | WM97XX_COO | WM97XX_SLEN);
++              dig2 &= ~WM9712_PDEN;
++              if (wm->mach_ops->acc_shutdown)
++                      wm->mach_ops->acc_shutdown(wm);
++      }
++
++      wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, dig1);
++      wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2);
++      return 0;
++}
++
++struct wm97xx_codec_drv wm97xx_codec = {
++      .id =   WM9712_ID2,
++      .name = "wm9712",
++      .poll_sample = wm9712_poll_sample,
++      .poll_touch = wm9712_poll_touch,
++      .acc_enable = wm9712_acc_enable,
++      .digitiser_ioctl = wm9712_digitiser_ioctl,
++};
++
++EXPORT_SYMBOL_GPL(wm97xx_codec);
++
++/* Module information */
++MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com");
++MODULE_DESCRIPTION("WM9712 Touch Screen Driver");
++MODULE_LICENSE("GPL");
+Index: linux-2.6.17/drivers/input/touchscreen/wm9713.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.17/drivers/input/touchscreen/wm9713.c    2006-09-19 20:36:47.969052000 +0200
+@@ -0,0 +1,461 @@
++/*
++ * wm9713.c  --  Codec touch driver for Wolfson WM9713 AC97 Codec.
++ *
++ * Copyright 2003, 2004, 2005, 2006 Wolfson Microelectronics PLC.
++ * Author: Liam Girdwood
++ *         liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
++ * Parts Copyright : Ian Molton <spyro@f2s.com>
++ *                   Andrew Zabolotny <zap@homelink.ru>
++ *                   Russell King <rmk@arm.linux.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 of the  License, or (at your
++ *  option) any later version.
++ *
++ *  Revision history
++ *     6th Sep 2006  Mike Arthur <linux@wolfsonmicro.com>
++ *                   Added pre and post sample calls.
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/input.h>
++#include <linux/delay.h>
++#include <linux/bitops.h>
++#include <linux/wm97xx.h>
++
++#define TS_NAME                       "wm97xx"
++#define WM9713_VERSION                "0.53"
++#define DEFAULT_PRESSURE      0xb0c0
++
++/*
++ * Debug
++ */
++#if 0
++#define dbg(format, arg...) printk(KERN_DEBUG TS_NAME ": " format "\n" , ## arg)
++#else
++#define dbg(format, arg...)
++#endif
++#define err(format, arg...) printk(KERN_ERR TS_NAME ": " format "\n" , ## arg)
++#define info(format, arg...) printk(KERN_INFO TS_NAME ": " format "\n" , ## arg)
++#define warn(format, arg...) printk(KERN_WARNING TS_NAME ": " format "\n" , ## arg)
++
++/*
++ * Module parameters
++ */
++
++/*
++ * Set internal pull up for pen detect.
++ *
++ * Pull up is in the range 1.02k (least sensitive) to 64k (most sensitive)
++ * i.e. pull up resistance = 64k Ohms / rpu.
++ *
++ * Adjust this value if you are having problems with pen detect not
++ * detecting any down event.
++ */
++static int rpu = 1;
++module_param(rpu, int, 0);
++MODULE_PARM_DESC(rpu, "Set internal pull up resitor for pen detect.");
++
++/*
++ * Set current used for pressure measurement.
++ *
++ * Set pil = 2 to use 400uA
++ *     pil = 1 to use 200uA and
++ *     pil = 0 to disable pressure measurement.
++ *
++ * This is used to increase the range of values returned by the adc
++ * when measureing touchpanel pressure.
++ */
++static int pil = 0;
++module_param(pil, int, 0);
++MODULE_PARM_DESC(pil, "Set current used for pressure measurement.");
++
++/*
++ * Set threshold for pressure measurement.
++ *
++ * Pen down pressure below threshold is ignored.
++ */
++static int pressure = DEFAULT_PRESSURE & 0xfff;
++module_param(pressure, int, 0);
++MODULE_PARM_DESC(pressure, "Set threshold for pressure measurement.");
++
++/*
++ * Set adc sample delay.
++ *
++ * For accurate touchpanel measurements, some settling time may be
++ * required between the switch matrix applying a voltage across the
++ * touchpanel plate and the ADC sampling the signal.
++ *
++ * This delay can be set by setting delay = n, where n is the array
++ * position of the delay in the array delay_table below.
++ * Long delays > 1ms are supported for completeness, but are not
++ * recommended.
++ */
++static int delay = 4;
++module_param(delay, int, 0);
++MODULE_PARM_DESC(delay, "Set adc sample delay.");
++
++/*
++ * Set adc mask function.
++ *
++ * Sources of glitch noise, such as signals driving an LCD display, may feed
++ * through to the touch screen plates and affect measurement accuracy. In
++ * order to minimise this, a signal may be applied to the MASK pin to delay or
++ * synchronise the sampling.
++ *
++ * 0 = No delay or sync
++ * 1 = High on pin stops conversions
++ * 2 = Edge triggered, edge on pin delays conversion by delay param (above)
++ * 3 = Edge triggered, edge on pin starts conversion after delay param
++ */
++static int mask = 0;
++module_param(mask, int, 0);
++MODULE_PARM_DESC(mask, "Set adc mask function.");
++
++/*
++ * Coordinate Polling Enable.
++ *
++ * Set to 1 to enable coordinate polling. e.g. x,y[,p] is sampled together
++ * for every poll.
++ */
++static int coord = 1;
++module_param(coord, int, 0);
++MODULE_PARM_DESC(coord, "Polling coordinate mode");
++
++/*
++ * ADC sample delay times in uS
++ */
++static const int delay_table[] = {
++      21,    // 1 AC97 Link frames
++      42,    // 2
++      84,    // 4
++      167,   // 8
++      333,   // 16
++      667,   // 32
++      1000,  // 48
++      1333,  // 64
++      2000,  // 96
++      2667,  // 128
++      3333,  // 160
++      4000,  // 192
++      4667,  // 224
++      5333,  // 256
++      6000,  // 288
++      0      // No delay, switch matrix always on
++};
++
++/*
++ * Delay after issuing a POLL command.
++ *
++ * The delay is 3 AC97 link frames + the touchpanel settling delay
++ */
++static inline void poll_delay(int d)
++{
++      udelay (3 * AC97_LINK_FRAME + delay_table [d]);
++}
++
++/*
++ * set up the physical settings of the WM9713
++ */
++static void init_wm9713_phy(struct wm97xx* wm)
++{
++      u16 dig1 = 0, dig2, dig3;
++
++      /* default values */
++      dig2 = WM97XX_DELAY(4) | WM97XX_SLT(5);
++      dig3= WM9712_RPU(1);
++
++      /* rpu */
++      if (rpu) {
++              dig3 &= 0xffc0;
++              dig3 |= WM9712_RPU(rpu);
++              info("setting pen detect pull-up to %d Ohms",64000 / rpu);
++      }
++
++      /* touchpanel pressure */
++      if (pil == 2) {
++              dig3 |= WM9712_PIL;
++              info("setting pressure measurement current to 400uA.");
++      } else if (pil)
++              info ("setting pressure measurement current to 200uA.");
++      if(!pil)
++              pressure = 0;
++
++      /* sample settling delay */
++      if (delay < 0 || delay > 15) {
++              info ("supplied delay out of range.");
++              delay = 4;
++              info("setting adc sample delay to %d u Secs.", delay_table[delay]);
++      }
++      dig2 &= 0xff0f;
++      dig2 |= WM97XX_DELAY(delay);
++
++      /* mask */
++      dig3 |= ((mask & 0x3) << 4);
++      if(coord)
++              dig3 |= WM9713_WAIT;
++
++      wm->misc = wm97xx_reg_read(wm, 0x5a);
++
++      wm97xx_reg_write(wm, AC97_WM9713_DIG1, dig1);
++      wm97xx_reg_write(wm, AC97_WM9713_DIG2, dig2);
++      wm97xx_reg_write(wm, AC97_WM9713_DIG3, dig3);
++      wm97xx_reg_write(wm, AC97_GPIO_STICKY, 0x0);
++}
++
++static int wm9713_digitiser_ioctl(struct wm97xx* wm, int cmd)
++{
++      u16 val = 0;
++
++      switch(cmd){
++      case WM97XX_DIG_START:
++              val = wm97xx_reg_read(wm, AC97_EXTENDED_MID);
++              wm97xx_reg_write(wm, AC97_EXTENDED_MID, val & 0x7fff);
++              wm97xx_reg_write(wm, AC97_WM9713_DIG3, wm->dig[2] | WM97XX_PRP_DET_DIG);
++              wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); /* dummy read */
++              break;
++      case WM97XX_DIG_STOP:
++              wm97xx_reg_write(wm, AC97_WM9713_DIG3, wm->dig[2] & ~WM97XX_PRP_DET_DIG);
++              val = wm97xx_reg_read(wm, AC97_EXTENDED_MID);
++              wm97xx_reg_write(wm, AC97_EXTENDED_MID, val | 0x8000);
++              break;
++      case WM97XX_AUX_PREPARE:
++              memcpy(wm->dig_save, wm->dig, sizeof(wm->dig));
++              wm97xx_reg_write(wm, AC97_WM9713_DIG1, 0);
++              wm97xx_reg_write(wm, AC97_WM9713_DIG2, 0);
++              wm97xx_reg_write(wm, AC97_WM9713_DIG3, WM97XX_PRP_DET_DIG);
++              break;
++      case WM97XX_DIG_RESTORE:
++              wm97xx_reg_write(wm, AC97_WM9713_DIG1, wm->dig_save[0]);
++              wm97xx_reg_write(wm, AC97_WM9713_DIG2, wm->dig_save[1]);
++              wm97xx_reg_write(wm, AC97_WM9713_DIG3, wm->dig_save[2]);
++              break;
++      case WM97XX_PHY_INIT:
++              init_wm9713_phy(wm);
++              break;
++      default:
++              return -EINVAL;
++      }
++      return 0;
++}
++
++static inline int is_pden (struct wm97xx* wm)
++{
++      return wm->dig[2] & WM9713_PDEN;
++}
++
++/*
++ * Read a sample from the WM9713 adc in polling mode.
++ */
++static int wm9713_poll_sample (struct wm97xx* wm, int adcsel, int *sample)
++{
++      u16 dig1;
++      int timeout = 5 * delay;
++
++      if (!wm->pen_probably_down) {
++              u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
++              if (!(data & WM97XX_PEN_DOWN))
++                      return RC_PENUP;
++              wm->pen_probably_down = 1;
++      }
++
++      /* set up digitiser */
++      if (adcsel & 0x8000)
++              adcsel = 1 << ((adcsel & 0x7fff) + 3);
++
++      dig1 = wm97xx_reg_read(wm, AC97_WM9713_DIG1);
++      dig1 &= ~WM9713_ADCSEL_MASK;
++
++      if (wm->mach_ops && wm->mach_ops->pre_sample)
++              wm->mach_ops->pre_sample(adcsel);
++      wm97xx_reg_write(wm, AC97_WM9713_DIG1, dig1 | adcsel |WM9713_POLL);
++
++      /* wait 3 AC97 time slots + delay for conversion */
++      poll_delay(delay);
++
++      /* wait for POLL to go low */
++      while ((wm97xx_reg_read(wm, AC97_WM9713_DIG1) & WM9713_POLL) && timeout) {
++              udelay(AC97_LINK_FRAME);
++              timeout--;
++      }
++
++      if (timeout <= 0) {
++              /* If PDEN is set, we can get a timeout when pen goes up */
++              if (is_pden(wm))
++                      wm->pen_probably_down = 0;
++              else
++                      dbg ("adc sample timeout");
++              return RC_PENUP;
++      }
++
++      *sample =wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
++      if (wm->mach_ops && wm->mach_ops->post_sample)
++              wm->mach_ops->post_sample(adcsel);
++
++      /* check we have correct sample */
++      if ((*sample & WM97XX_ADCSRC_MASK) != ffs(adcsel >> 1) << 12) {
++              dbg ("adc wrong sample, read %x got %x", adcsel,
++                   *sample & WM97XX_ADCSRC_MASK);
++              return RC_PENUP;
++      }
++
++      if (!(*sample & WM97XX_PEN_DOWN)) {
++              wm->pen_probably_down = 0;
++              return RC_PENUP;
++      }
++
++      return RC_VALID;
++}
++
++/*
++ * Read a coordinate from the WM9713 adc in polling mode.
++ */
++static int wm9713_poll_coord (struct wm97xx* wm, struct wm97xx_data *data)
++{
++      u16 dig1;
++      int timeout = 5 * delay;
++
++      if (!wm->pen_probably_down) {
++              u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
++              if (!(data & WM97XX_PEN_DOWN))
++                      return RC_PENUP;
++              wm->pen_probably_down = 1;
++      }
++
++      /* set up digitiser */
++      dig1 = wm97xx_reg_read(wm, AC97_WM9713_DIG1);
++      dig1 &= ~WM9713_ADCSEL_MASK;
++      if(pil)
++              dig1 |= WM97XX_ADCSEL_PRES;
++
++      if (wm->mach_ops && wm->mach_ops->pre_sample)
++              wm->mach_ops->pre_sample(WM97XX_ADCSEL_X | WM97XX_ADCSEL_Y);
++      wm97xx_reg_write(wm, AC97_WM9713_DIG1, dig1 | WM9713_POLL | WM9713_COO);
++
++      /* wait 3 AC97 time slots + delay for conversion */
++      poll_delay(delay);
++      data->x = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
++      /* wait for POLL to go low */
++      while ((wm97xx_reg_read(wm, AC97_WM9713_DIG1) & WM9713_POLL) && timeout) {
++              udelay(AC97_LINK_FRAME);
++              timeout--;
++      }
++
++      if (timeout <= 0) {
++              /* If PDEN is set, we can get a timeout when pen goes up */
++              if (is_pden(wm))
++                      wm->pen_probably_down = 0;
++              else
++                      dbg ("adc sample timeout");
++              return RC_PENUP;
++      }
++
++      /* read back data */
++      data->y = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
++      if (pil)
++              data->p = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
++      else
++              data->p = DEFAULT_PRESSURE;
++
++      if (wm->mach_ops && wm->mach_ops->post_sample)
++              wm->mach_ops->post_sample(WM97XX_ADCSEL_X | WM97XX_ADCSEL_Y);
++
++      /* check we have correct sample */
++      if (!(data->x & WM97XX_ADCSEL_X) || !(data->y & WM97XX_ADCSEL_Y))
++              goto err;
++      if(pil && !(data->p & WM97XX_ADCSEL_PRES))
++              goto err;
++
++      if (!(data->x & WM97XX_PEN_DOWN)) {
++              wm->pen_probably_down = 0;
++              return RC_PENUP;
++      }
++      return RC_VALID;
++err:
++      return RC_PENUP;
++}
++
++/*
++ * Sample the WM9713 touchscreen in polling mode
++ */
++static int wm9713_poll_touch(struct wm97xx* wm, struct wm97xx_data *data)
++{
++      int rc;
++
++      if(coord) {
++              if((rc = wm9713_poll_coord(wm, data)) != RC_VALID)
++                      return rc;
++      } else {
++              if ((rc = wm9713_poll_sample(wm, WM9713_ADCSEL_X, &data->x)) != RC_VALID)
++                      return rc;
++              if ((rc = wm9713_poll_sample(wm, WM9713_ADCSEL_Y, &data->y)) != RC_VALID)
++                      return rc;
++              if (pil) {
++                      if ((rc = wm9713_poll_sample(wm, WM9713_ADCSEL_PRES, &data->p)) != RC_VALID)
++                              return rc;
++              } else
++                      data->p = DEFAULT_PRESSURE;
++      }
++      return RC_VALID;
++}
++
++/*
++ * Enable WM9713 continuous mode, i.e. touch data is streamed across an AC97 slot
++ */
++static int wm9713_acc_enable (struct wm97xx* wm, int enable)
++{
++      u16 dig1, dig2, dig3;
++      int ret = 0;
++
++      dig1 = wm->dig[0];
++      dig2 = wm->dig[1];
++      dig3 = wm->dig[2];
++
++      if (enable) {
++              /* continous mode */
++              if (wm->mach_ops->acc_startup &&
++                      (ret = wm->mach_ops->acc_startup(wm)) < 0)
++                      return ret;
++
++              dig1 &= ~WM9713_ADCSEL_MASK;
++              dig1 |= WM9713_CTC | WM9713_COO | WM9713_ADCSEL_X | WM9713_ADCSEL_Y;
++        if (pil)
++              dig1 |= WM9713_ADCSEL_PRES;
++              dig2 &= ~(WM97XX_DELAY_MASK | WM97XX_SLT_MASK  | WM97XX_CM_RATE_MASK);
++              dig2 |= WM97XX_SLEN | WM97XX_DELAY (delay) |
++              WM97XX_SLT (wm->acc_slot) | WM97XX_RATE (wm->acc_rate);
++              dig3 |= WM9713_PDEN;
++      } else {
++              dig1 &= ~(WM9713_CTC | WM9713_COO);
++              dig2 &= ~WM97XX_SLEN;
++              dig3 &= ~WM9713_PDEN;
++        if (wm->mach_ops->acc_shutdown)
++            wm->mach_ops->acc_shutdown(wm);
++      }
++
++      wm97xx_reg_write(wm, AC97_WM9713_DIG1, dig1);
++      wm97xx_reg_write(wm, AC97_WM9713_DIG2, dig2);
++      wm97xx_reg_write(wm, AC97_WM9713_DIG3, dig3);
++      return ret;
++}
++
++struct wm97xx_codec_drv wm97xx_codec = {
++      .id =   WM9713_ID2,
++    .name = "wm9713",
++      .poll_sample = wm9713_poll_sample,
++      .poll_touch = wm9713_poll_touch,
++      .acc_enable = wm9713_acc_enable,
++      .digitiser_ioctl = wm9713_digitiser_ioctl,
++};
++
++EXPORT_SYMBOL_GPL(wm97xx_codec);
++
++/* Module information */
++MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com");
++MODULE_DESCRIPTION("WM9713 Touch Screen Driver");
++MODULE_LICENSE("GPL");
+Index: linux-2.6.17/drivers/input/touchscreen/wm97xx-core.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.17/drivers/input/touchscreen/wm97xx-core.c       2006-09-19 20:36:47.969052000 +0200
+@@ -0,0 +1,912 @@
++/*
++ * wm97xx-core.c  --  Touch screen driver core for Wolfson WM9705, WM9712
++ *                    and WM9713 AC97 Codecs.
++ *
++ * Copyright 2003, 2004, 2005, 2006 Wolfson Microelectronics PLC.
++ * Author: Liam Girdwood
++ *         liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
++ * Parts Copyright : Ian Molton <spyro@f2s.com>
++ *                   Andrew Zabolotny <zap@homelink.ru>
++ *                   Russell King <rmk@arm.linux.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 of the  License, or (at your
++ *  option) any later version.
++ *
++ * Notes:
++ *
++ *  Features:
++ *       - supports WM9705, WM9712, WM9713
++ *       - polling mode
++ *       - continuous mode (arch-dependent)
++ *       - adjustable rpu/dpp settings
++ *       - adjustable pressure current
++ *       - adjustable sample settle delay
++ *       - 4 and 5 wire touchscreens (5 wire is WM9712 only)
++ *       - pen down detection
++ *       - battery monitor
++ *       - sample AUX adc's
++ *       - power management
++ *       - codec GPIO
++ *       - codec event notification
++ * Todo
++ *       - Support for async sampling control for noisy LCD's.
++ *
++ *  Revision history
++ *    7th May 2003   Initial version.
++ *    6th June 2003  Added non module support and AC97 registration.
++ *   18th June 2003  Added AUX adc sampling.
++ *   23rd June 2003  Did some minimal reformatting, fixed a couple of
++ *                   codec_mutexing bugs and noted a race to fix.
++ *   24th June 2003  Added power management and fixed race condition.
++ *   10th July 2003  Changed to a misc device.
++ *   31st July 2003  Moved TS_EVENT and TS_CAL to wm97xx.h
++ *    8th Aug  2003  Added option for read() calling wm97xx_sample_touch()
++ *                   because some ac97_read/ac_97_write call schedule()
++ *    7th Nov  2003  Added Input touch event interface, stanley.cai@intel.com
++ *   13th Nov  2003  Removed h3600 touch interface, added interrupt based
++ *                   pen down notification and implemented continous mode
++ *                   on XScale arch.
++ *   16th Nov  2003  Ian Molton <spyro@f2s.com>
++ *                   Modified so that it suits the new 2.6 driver model.
++ *   25th Jan  2004  Andrew Zabolotny <zap@homelink.ru>
++ *                   Implemented IRQ-driven pen down detection, implemented
++ *                   the private API meant to be exposed to platform-specific
++ *                   drivers, reorganized the driver so that it supports
++ *                   an arbitrary number of devices.
++ *    1st Feb  2004  Moved continuous mode handling to a separate
++ *                   architecture-dependent file. For now only PXA
++ *                   built-in AC97 controller is supported (pxa-ac97-wm97xx.c).
++ *    11th Feb 2004  Reduced CPU usage by keeping a cached copy of both
++ *                   digitizer registers instead of reading them every time.
++ *                   A reorganization of the whole code for better
++ *                   error handling.
++ *    17th Apr 2004  Added BMON support.
++ *    17th Nov 2004  Added codec GPIO, codec event handling (real and virtual
++ *                   GPIOs) and 2.6 power management.
++ *    29th Nov 2004  Added WM9713 support.
++ *     4th Jul 2005  Moved codec specific code out to seperate files.
++ *     6th Sep 2006  Mike Arthur <linux@wolfsonmicro.com>
++ *                   Added bus interface.
++ */
++
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/string.h>
++#include <linux/proc_fs.h>
++#include <linux/pm.h>
++#include <linux/interrupt.h>
++#include <linux/bitops.h>
++#include <linux/workqueue.h>
++#include <linux/device.h>
++#include <linux/wm97xx.h>
++#include <asm/uaccess.h>
++#include <asm/io.h>
++
++#define TS_NAME                       "wm97xx"
++#define WM_CORE_VERSION               "0.63"
++#define DEFAULT_PRESSURE      0xb0c0
++
++/*
++ * WM97xx - enable/disable AUX ADC sysfs
++ */
++static int aux_sys = 1;
++module_param(aux_sys, int, 0);
++MODULE_PARM_DESC(aux_sys, "enable AUX ADC sysfs entries");
++
++/*
++ * WM97xx - enable/disable codec status sysfs
++ */
++static int status_sys = 1;
++module_param(status_sys, int, 0);
++MODULE_PARM_DESC(status_sys, "enable codec status sysfs entries");
++
++/*
++ * Touchscreen absolute values
++ *
++ * These parameters are used to help the input layer discard out of
++ * range readings and reduce jitter etc.
++ *
++ *   o min, max:- indicate the min and max values your touch screen returns
++ *   o fuzz:- use a higher number to reduce jitter
++ *
++ * The default values correspond to Mainstone II in QVGA mode
++ *
++ * Please read
++ * Documentation/input/input-programming.txt for more details.
++ */
++
++static int abs_x[3] = {350,3900,5};
++module_param_array(abs_x, int, NULL, 0);
++MODULE_PARM_DESC(abs_x, "Touchscreen absolute X min, max, fuzz");
++
++static int abs_y[3] = {320,3750,40};
++module_param_array(abs_y, int, NULL, 0);
++MODULE_PARM_DESC(abs_y, "Touchscreen absolute Y min, max, fuzz");
++
++static int abs_p[3] = {0,150,4};
++module_param_array(abs_p, int, NULL, 0);
++MODULE_PARM_DESC(abs_p, "Touchscreen absolute Pressure min, max, fuzz");
++
++/*
++ * Debug
++ */
++#if 0
++#define dbg(format, arg...) printk(KERN_DEBUG TS_NAME ": " format "\n" , ## arg)
++#else
++#define dbg(format, arg...)
++#endif
++#define err(format, arg...) printk(KERN_ERR TS_NAME ": " format "\n" , ## arg)
++#define info(format, arg...) printk(KERN_INFO TS_NAME ": " format "\n" , ## arg)
++#define warn(format, arg...) printk(KERN_WARNING TS_NAME ": " format "\n" , ## arg)
++
++/* codec AC97 IO access */
++int wm97xx_reg_read(struct wm97xx *wm, u16 reg)
++{
++      if (wm->ac97)
++              return wm->ac97->bus->ops->read(wm->ac97, reg);
++      else
++              return -1;
++}
++
++void wm97xx_reg_write(struct wm97xx *wm, u16 reg, u16 val)
++{
++      /* cache digitiser registers */
++      if(reg >= AC97_WM9713_DIG1 && reg <= AC97_WM9713_DIG3)
++              wm->dig[(reg - AC97_WM9713_DIG1) >> 1] = val;
++
++      /* cache gpio regs */
++      if(reg >= AC97_GPIO_CFG && reg <= AC97_MISC_AFE)
++              wm->gpio[(reg - AC97_GPIO_CFG) >> 1] = val;
++
++      /* wm9713 irq reg */
++      if(reg == 0x5a)
++              wm->misc = val;
++
++      if (wm->ac97)
++              wm->ac97->bus->ops->write(wm->ac97, reg, val);
++}
++
++
++/**
++ *    wm97xx_read_aux_adc - Read the aux adc.
++ *    @wm: wm97xx device.
++ *  @adcsel: codec ADC to be read
++ *
++ *    Reads the selected AUX ADC.
++ */
++
++int wm97xx_read_aux_adc(struct wm97xx *wm, u16 adcsel)
++{
++      int power_adc = 0, auxval;
++      u16 power = 0;
++
++      /* get codec */
++      mutex_lock(&wm->codec_mutex);
++
++      /* When the touchscreen is not in use, we may have to power up the AUX ADC
++       * before we can use sample the AUX inputs->
++       */
++      if (wm->id == WM9713_ID2 &&
++          (power = wm97xx_reg_read(wm, AC97_EXTENDED_MID)) & 0x8000) {
++              power_adc = 1;
++              wm97xx_reg_write(wm, AC97_EXTENDED_MID, power & 0x7fff);
++      }
++
++      /* Prepare the codec for AUX reading */
++      wm->codec->digitiser_ioctl(wm, WM97XX_AUX_PREPARE);
++
++      /* Turn polling mode on to read AUX ADC */
++      wm->pen_probably_down = 1;
++      wm->codec->poll_sample(wm, adcsel, &auxval);
++
++      if (power_adc)
++              wm97xx_reg_write(wm, AC97_EXTENDED_MID, power | 0x8000);
++
++      wm->codec->digitiser_ioctl(wm, WM97XX_DIG_RESTORE);
++
++      wm->pen_probably_down = 0;
++
++      mutex_unlock(&wm->codec_mutex);
++      return auxval & 0xfff;
++}
++
++#define WM97XX_AUX_ATTR(name,input) \
++static ssize_t name##_show(struct device *dev, struct device_attribute *attr, char *buf)   \
++{ \
++      struct wm97xx *wm = (struct wm97xx*)dev->driver_data; \
++      return sprintf(buf, "%d\n", wm97xx_read_aux_adc(wm, input)); \
++} \
++static DEVICE_ATTR(name, 0444, name##_show, NULL)
++
++WM97XX_AUX_ATTR(aux1, WM97XX_AUX_ID1);
++WM97XX_AUX_ATTR(aux2, WM97XX_AUX_ID2);
++WM97XX_AUX_ATTR(aux3, WM97XX_AUX_ID3);
++WM97XX_AUX_ATTR(aux4, WM97XX_AUX_ID4);
++
++#define WM97XX_STATUS_ATTR(name) \
++static ssize_t name##_show(struct device *dev, struct device_attribute *attr, char *buf)   \
++{ \
++      struct wm97xx *wm = (struct wm97xx*)dev->driver_data; \
++      return sprintf(buf, "%d\n", wm97xx_reg_read(wm, AC97_GPIO_STATUS)); \
++} \
++static DEVICE_ATTR(name, 0444, name##_show, NULL)
++
++WM97XX_STATUS_ATTR(gpio);
++
++static int wm97xx_sys_add(struct device *dev)
++{
++      if (aux_sys) {
++              device_create_file(dev, &dev_attr_aux1);
++              device_create_file(dev, &dev_attr_aux2);
++              device_create_file(dev, &dev_attr_aux3);
++              device_create_file(dev, &dev_attr_aux4);
++      }
++      if (status_sys)
++              device_create_file(dev, &dev_attr_gpio);
++      return 0;
++}
++
++static void wm97xx_sys_remove(struct device *dev)
++{
++      if (status_sys)
++              device_remove_file(dev, &dev_attr_gpio);
++      if (aux_sys) {
++              device_remove_file(dev, &dev_attr_aux1);
++              device_remove_file(dev, &dev_attr_aux2);
++              device_remove_file(dev, &dev_attr_aux3);
++              device_remove_file(dev, &dev_attr_aux4);
++      }
++}
++
++/**
++ *    wm97xx_get_gpio - Get the status of a codec GPIO.
++ *    @wm: wm97xx device.
++ *  @gpio: gpio
++ *
++ *    Get the status of a codec GPIO pin
++ */
++
++wm97xx_gpio_status_t wm97xx_get_gpio(struct wm97xx *wm, u32 gpio)
++{
++      u16 status;
++      wm97xx_gpio_status_t ret;
++
++      mutex_lock(&wm->codec_mutex);
++      status = wm97xx_reg_read(wm, AC97_GPIO_STATUS);
++
++      if (status & gpio)
++              ret = WM97XX_GPIO_HIGH;
++      else
++              ret = WM97XX_GPIO_LOW;
++
++      mutex_unlock(&wm->codec_mutex);
++      return ret;
++}
++
++/**
++ *    wm97xx_set_gpio - Set the status of a codec GPIO.
++ *    @wm: wm97xx device.
++ *  @gpio: gpio
++ *
++ *
++ *    Set the status of a codec GPIO pin
++ */
++
++void wm97xx_set_gpio(struct wm97xx *wm, u32 gpio,
++                              wm97xx_gpio_status_t status)
++{
++      u16 reg;
++
++      mutex_lock(&wm->codec_mutex);
++      reg = wm97xx_reg_read(wm, AC97_GPIO_STATUS);
++
++      if (status & WM97XX_GPIO_HIGH)
++              reg |= gpio;
++      else
++              reg &= ~gpio;
++
++      if (wm->id == WM9712_ID2)
++              wm97xx_reg_write(wm, AC97_GPIO_STATUS, reg << 1);
++      else
++              wm97xx_reg_write(wm, AC97_GPIO_STATUS, reg);
++      mutex_unlock(&wm->codec_mutex);
++}
++
++/*
++ * Codec GPIO pin configuration, this set's pin direction, polarity,
++ * stickyness and wake up.
++ */
++void wm97xx_config_gpio(struct wm97xx *wm, u32 gpio, wm97xx_gpio_dir_t dir,
++                 wm97xx_gpio_pol_t pol, wm97xx_gpio_sticky_t sticky,
++                 wm97xx_gpio_wake_t wake)
++{
++      u16 reg;
++
++      mutex_lock(&wm->codec_mutex);
++      reg = wm97xx_reg_read(wm, AC97_GPIO_POLARITY);
++
++      if (pol == WM97XX_GPIO_POL_HIGH)
++              reg |= gpio;
++      else
++              reg &= ~gpio;
++
++      wm97xx_reg_write(wm, AC97_GPIO_POLARITY, reg);
++      reg = wm97xx_reg_read(wm, AC97_GPIO_STICKY);
++
++      if (sticky == WM97XX_GPIO_STICKY)
++              reg |= gpio;
++      else
++              reg &= ~gpio;
++
++      wm97xx_reg_write(wm, AC97_GPIO_STICKY, reg);
++      reg = wm97xx_reg_read(wm, AC97_GPIO_WAKEUP);
++
++      if (wake == WM97XX_GPIO_WAKE)
++              reg |= gpio;
++      else
++              reg &= ~gpio;
++
++      wm97xx_reg_write(wm, AC97_GPIO_WAKEUP, reg);
++      reg = wm97xx_reg_read(wm, AC97_GPIO_CFG);
++
++      if (dir == WM97XX_GPIO_IN)
++              reg |= gpio;
++      else
++              reg &= ~gpio;
++
++      wm97xx_reg_write(wm, AC97_GPIO_CFG, reg);
++      mutex_unlock(&wm->codec_mutex);
++}
++
++/*
++ * Handle a pen down interrupt.
++ */
++static void wm97xx_pen_irq_worker(void *ptr)
++{
++      struct wm97xx *wm = (struct wm97xx *) ptr;
++
++      /* do we need to enable the touch panel reader */
++      if (wm->id == WM9705_ID2) {
++              if (wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD) & WM97XX_PEN_DOWN)
++                      wm->pen_is_down = 1;
++              else
++                      wm->pen_is_down = 0;
++              wake_up_interruptible(&wm->pen_irq_wait);
++      } else {
++              u16 status, pol;
++              mutex_lock(&wm->codec_mutex);
++              status = wm97xx_reg_read(wm, AC97_GPIO_STATUS);
++              pol = wm97xx_reg_read(wm, AC97_GPIO_POLARITY);
++
++              if (WM97XX_GPIO_13 & pol & status) {
++                      wm->pen_is_down = 1;
++                      wm97xx_reg_write(wm, AC97_GPIO_POLARITY, pol & ~WM97XX_GPIO_13);
++              } else {
++                      wm->pen_is_down = 0;
++                  wm97xx_reg_write(wm, AC97_GPIO_POLARITY, pol | WM97XX_GPIO_13);
++              }
++
++              if (wm->id == WM9712_ID2)
++                      wm97xx_reg_write(wm, AC97_GPIO_STATUS, (status & ~WM97XX_GPIO_13) << 1);
++              else
++                      wm97xx_reg_write(wm, AC97_GPIO_STATUS, status & ~WM97XX_GPIO_13);
++              mutex_unlock(&wm->codec_mutex);
++              wake_up_interruptible(&wm->pen_irq_wait);
++      }
++
++      if (!wm->pen_is_down && wm->mach_ops && wm->mach_ops->acc_enabled)
++              wm->mach_ops->acc_pen_up(wm);
++      enable_irq(wm->pen_irq);
++}
++
++/*
++ * Codec PENDOWN irq handler
++ *
++ * We have to disable the codec interrupt in the handler because it can
++ * take upto 1ms to clear the interrupt source. The interrupt is then enabled
++ * again in the slow handler when the source has been cleared.
++ */
++static irqreturn_t wm97xx_pen_interrupt(int irq, void *dev_id,
++                                      struct pt_regs *regs)
++{
++      struct wm97xx *wm = (struct wm97xx *) dev_id;
++      disable_irq(wm->pen_irq);
++      queue_work(wm->pen_irq_workq, &wm->pen_event_work);
++      return IRQ_HANDLED;
++}
++
++/*
++ * initialise pen IRQ handler and workqueue
++ */
++static int wm97xx_init_pen_irq(struct wm97xx *wm)
++{
++      u16 reg;
++
++      INIT_WORK(&wm->pen_event_work, wm97xx_pen_irq_worker, wm);
++      if ((wm->pen_irq_workq =
++              create_singlethread_workqueue("kwm97pen")) == NULL) {
++              err("could not create pen irq work queue");
++              wm->pen_irq = 0;
++              return -EINVAL;
++      }
++
++      if (request_irq (wm->pen_irq, wm97xx_pen_interrupt, SA_SHIRQ, "wm97xx-pen", wm)) {
++              err("could not register codec pen down interrupt, will poll for pen down");
++              destroy_workqueue(wm->pen_irq_workq);
++              wm->pen_irq = 0;
++              return -EINVAL;
++      }
++
++      /* enable PEN down on wm9712/13 */
++      if (wm->id != WM9705_ID2) {
++              reg = wm97xx_reg_read(wm, AC97_MISC_AFE);
++              wm97xx_reg_write(wm, AC97_MISC_AFE, reg & 0xfffb);
++              reg = wm97xx_reg_read(wm, 0x5a);
++              wm97xx_reg_write(wm, 0x5a, reg & ~0x0001);
++      }
++
++      return 0;
++}
++
++/* Private struct for communication between struct wm97xx_tshread
++ * and wm97xx_read_samples */
++struct ts_state {
++      int sleep_time;
++      int min_sleep_time;
++};
++
++static int wm97xx_read_samples(struct wm97xx *wm, struct ts_state *state)
++{
++      struct wm97xx_data data;
++      int rc;
++
++      mutex_lock(&wm->codec_mutex);
++
++    if (wm->mach_ops && wm->mach_ops->acc_enabled)
++         rc = wm->mach_ops->acc_pen_down(wm);
++    else
++        rc = wm->codec->poll_touch(wm, &data);
++
++      if (rc & RC_PENUP) {
++              if (wm->pen_is_down) {
++                      wm->pen_is_down = 0;
++                      dbg("pen up");
++                      input_report_abs(wm->input_dev, ABS_PRESSURE, 0);
++                      input_sync(wm->input_dev);
++              } else if (!(rc & RC_AGAIN)) {
++                      /* We need high frequency updates only while pen is down,
++                      * the user never will be able to touch screen faster than
++                      * a few times per second... On the other hand, when the
++                      * user is actively working with the touchscreen we don't
++                      * want to lose the quick response. So we will slowly
++                      * increase sleep time after the pen is up and quicky
++                      * restore it to ~one task switch when pen is down again.
++                      */
++                      if (state->sleep_time < HZ / 10)
++                              state->sleep_time++;
++              }
++
++      } else if (rc & RC_VALID) {
++              dbg("pen down: x=%x:%d, y=%x:%d, pressure=%x:%d\n",
++                      data.x >> 12, data.x & 0xfff, data.y >> 12,
++                      data.y & 0xfff, data.p >> 12, data.p & 0xfff);
++              input_report_abs(wm->input_dev, ABS_X, data.x & 0xfff);
++              input_report_abs(wm->input_dev, ABS_Y, data.y & 0xfff);
++              input_report_abs(wm->input_dev, ABS_PRESSURE, data.p & 0xfff);
++              input_sync(wm->input_dev);
++              wm->pen_is_down = 1;
++              state->sleep_time = state->min_sleep_time;
++      } else if (rc & RC_PENDOWN) {
++              dbg("pen down");
++              wm->pen_is_down = 1;
++              state->sleep_time = state->min_sleep_time;
++      }
++
++      mutex_unlock(&wm->codec_mutex);
++      return rc;
++}
++
++/*
++* The touchscreen sample reader thread.
++*/
++static int wm97xx_ts_read(void *data)
++{
++      int rc;
++      struct ts_state state;
++      struct wm97xx *wm = (struct wm97xx *) data;
++
++      /* set up thread context */
++      wm->ts_task = current;
++      daemonize("kwm97xxts");
++
++      if (wm->codec == NULL) {
++              wm->ts_task = NULL;
++              printk(KERN_ERR "codec is NULL, bailing\n");
++      }
++
++      complete(&wm->ts_init);
++      wm->pen_is_down = 0;
++      state.min_sleep_time = HZ >= 100 ? HZ / 100 : 1;
++      if (state.min_sleep_time < 1)
++              state.min_sleep_time = 1;
++      state.sleep_time = state.min_sleep_time;
++
++      /* touch reader loop */
++      while (wm->ts_task) {
++              do {
++                      try_to_freeze();
++                      rc = wm97xx_read_samples(wm, &state);
++              } while (rc & RC_AGAIN);
++              if (!wm->pen_is_down && wm->pen_irq) {
++                      /* Nice, we don't have to poll for pen down event */
++                      wait_event_interruptible(wm->pen_irq_wait, wm->pen_is_down);
++              } else {
++                      set_task_state(current, TASK_INTERRUPTIBLE);
++                      schedule_timeout(state.sleep_time);
++              }
++      }
++      complete_and_exit(&wm->ts_exit, 0);
++}
++
++/**
++ *    wm97xx_ts_input_open - Open the touch screen input device.
++ *    @idev:  Input device to be opened.
++ *
++ *    Called by the input sub system to open a wm97xx touchscreen device.
++ *  Starts the touchscreen thread and touch digitiser.
++ */
++static int wm97xx_ts_input_open(struct input_dev *idev)
++{
++      int ret = 0;
++      struct wm97xx *wm = (struct wm97xx *) idev->private;
++
++      mutex_lock(&wm->codec_mutex);
++      /* first time opened ? */
++      if (wm->ts_use_count++ == 0) {
++              /* start touchscreen thread */
++              init_completion(&wm->ts_init);
++              init_completion(&wm->ts_exit);
++              ret = kernel_thread(wm97xx_ts_read, wm, CLONE_KERNEL);
++
++              if (ret >= 0) {
++                      wait_for_completion(&wm->ts_init);
++                      if (wm->ts_task == NULL)
++                              ret = -EINVAL;
++              } else {
++                      mutex_unlock(&wm->codec_mutex);
++                      return ret;
++              }
++
++              /* start digitiser */
++        if (wm->mach_ops && wm->mach_ops->acc_enabled)
++            wm->codec->acc_enable(wm, 1);
++              wm->codec->digitiser_ioctl(wm, WM97XX_DIG_START);
++
++              /* init pen down/up irq handling */
++              if (wm->pen_irq) {
++                      wm97xx_init_pen_irq(wm);
++
++                      if (wm->pen_irq == 0) {
++                              /* we failed to get an irq for pen down events,
++                               * so we resort to polling. kickstart the reader */
++                              wm->pen_is_down = 1;
++                              wake_up_interruptible(&wm->pen_irq_wait);
++                      }
++              }
++      }
++
++      mutex_unlock(&wm->codec_mutex);
++      return 0;
++}
++
++/**
++ *    wm97xx_ts_input_close - Close the touch screen input device.
++ *    @idev:  Input device to be closed.
++ *
++ *    Called by the input sub system to close a wm97xx touchscreen device.
++ *  Kills the touchscreen thread and stops the touch digitiser.
++ */
++
++static void wm97xx_ts_input_close(struct input_dev *idev)
++{
++      struct wm97xx *wm = (struct wm97xx *) idev->private;
++
++      mutex_lock(&wm->codec_mutex);
++      if (--wm->ts_use_count == 0) {
++              /* destroy workqueues and free irqs */
++              if (wm->pen_irq) {
++                      free_irq(wm->pen_irq, wm);
++                      destroy_workqueue(wm->pen_irq_workq);
++              }
++
++              /* kill thread */
++              if (wm->ts_task) {
++                      wm->ts_task = NULL;
++                      wm->pen_is_down = 1;
++                      wake_up_interruptible(&wm->pen_irq_wait);
++                      wait_for_completion(&wm->ts_exit);
++                      wm->pen_is_down = 0;
++              }
++
++              /* stop digitiser */
++              wm->codec->digitiser_ioctl(wm, WM97XX_DIG_STOP);
++              if (wm->mach_ops && wm->mach_ops->acc_enabled)
++                      wm->codec->acc_enable(wm, 0);
++      }
++      mutex_unlock(&wm->codec_mutex);
++}
++
++static int wm97xx_bus_match(struct device *dev, struct device_driver *drv)
++{
++    return !(strcmp(dev->bus_id,drv->name));
++}
++
++/*
++ * The AC97 audio driver will do all the Codec suspend and resume
++ * tasks. This is just for anything machine specific or extra.
++ */
++static int wm97xx_bus_suspend(struct device *dev, pm_message_t state)
++{
++    int ret = 0;
++
++    if (dev->driver && dev->driver->suspend)
++        ret = dev->driver->suspend(dev, state);
++
++    return ret;
++}
++
++static int wm97xx_bus_resume(struct device *dev)
++{
++    int ret = 0;
++
++    if (dev->driver && dev->driver->resume)
++        ret = dev->driver->resume(dev);
++
++    return ret;
++}
++
++struct bus_type wm97xx_bus_type = {
++    .name       = "wm97xx",
++    .match      = wm97xx_bus_match,
++    .suspend    = wm97xx_bus_suspend,
++    .resume     = wm97xx_bus_resume,
++};
++
++static void  wm97xx_release(struct device *dev)
++{
++    kfree(dev);
++}
++
++static int wm97xx_probe(struct device *dev)
++{
++      struct wm97xx* wm;
++      int ret = 0, id = 0;
++
++      if (!(wm = kzalloc(sizeof(struct wm97xx), GFP_KERNEL)))
++              return -ENOMEM;
++    mutex_init(&wm->codec_mutex);
++
++      init_waitqueue_head(&wm->pen_irq_wait);
++      wm->dev = dev;
++      dev->driver_data = wm;
++      wm->ac97 = to_ac97_t(dev);
++
++      /* check that we have a supported codec */
++      if ((id = wm97xx_reg_read(wm, AC97_VENDOR_ID1)) != WM97XX_ID1) {
++              err("could not find a wm97xx, found a %x instead\n", id);
++              kfree(wm);
++              return -ENODEV;
++      }
++
++      wm->id = wm97xx_reg_read(wm, AC97_VENDOR_ID2);
++      if(wm->id != wm97xx_codec.id) {
++              err("could not find a the selected codec, please build for wm97%2x", wm->id & 0xff);
++              kfree(wm);
++              return -ENODEV;
++      }
++
++      if((wm->input_dev = input_allocate_device()) == NULL) {
++        kfree(wm);
++              return -ENOMEM;
++    }
++
++      /* set up touch configuration */
++      info("detected a wm97%2x codec", wm->id & 0xff);
++      wm->input_dev->name = "wm97xx touchscreen";
++      wm->input_dev->open = wm97xx_ts_input_open;
++      wm->input_dev->close = wm97xx_ts_input_close;
++      set_bit(EV_ABS, wm->input_dev->evbit);
++      set_bit(ABS_X, wm->input_dev->absbit);
++      set_bit(ABS_Y, wm->input_dev->absbit);
++      set_bit(ABS_PRESSURE, wm->input_dev->absbit);
++      wm->input_dev->absmax[ABS_X] = abs_x[1];
++      wm->input_dev->absmax[ABS_Y] = abs_y[1];
++      wm->input_dev->absmax[ABS_PRESSURE] = abs_p[1];
++      wm->input_dev->absmin[ABS_X] = abs_x[0];
++      wm->input_dev->absmin[ABS_Y] = abs_y[0];
++      wm->input_dev->absmin[ABS_PRESSURE] = abs_p[0];
++      wm->input_dev->absfuzz[ABS_X] = abs_x[2];
++      wm->input_dev->absfuzz[ABS_Y] = abs_y[2];
++      wm->input_dev->absfuzz[ABS_PRESSURE] = abs_p[2];
++      wm->input_dev->private = wm;
++      wm->codec = &wm97xx_codec;
++      if((ret = input_register_device(wm->input_dev)) < 0) {
++              kfree(wm);
++              return -ENOMEM;
++    }
++
++      if(aux_sys)
++              wm97xx_sys_add(dev);
++
++      /* set up physical characteristics */
++      wm->codec->digitiser_ioctl(wm, WM97XX_PHY_INIT);
++
++      /* load gpio cache */
++      wm->gpio[0] = wm97xx_reg_read(wm, AC97_GPIO_CFG);
++      wm->gpio[1] = wm97xx_reg_read(wm, AC97_GPIO_POLARITY);
++      wm->gpio[2] = wm97xx_reg_read(wm, AC97_GPIO_STICKY);
++      wm->gpio[3] = wm97xx_reg_read(wm, AC97_GPIO_WAKEUP);
++      wm->gpio[4] = wm97xx_reg_read(wm, AC97_GPIO_STATUS);
++      wm->gpio[5] = wm97xx_reg_read(wm, AC97_MISC_AFE);
++
++      /* register our battery device */
++    if (!(wm->battery_dev = kzalloc(sizeof(struct device), GFP_KERNEL))) {
++      ret = -ENOMEM;
++        goto batt_err;
++    }
++    wm->battery_dev->bus = &wm97xx_bus_type;
++    strcpy(wm->battery_dev->bus_id,"wm97xx-battery");
++    wm->battery_dev->driver_data = wm;
++    wm->battery_dev->parent = dev;
++    wm->battery_dev->release = wm97xx_release;
++    if((ret = device_register(wm->battery_dev)) < 0)
++      goto batt_reg_err;
++
++      /* register our extended touch device (for machine specific extensions) */
++    if (!(wm->touch_dev = kzalloc(sizeof(struct device), GFP_KERNEL))) {
++      ret = -ENOMEM;
++        goto touch_err;
++    }
++    wm->touch_dev->bus = &wm97xx_bus_type;
++    strcpy(wm->touch_dev->bus_id,"wm97xx-touchscreen");
++    wm->touch_dev->driver_data = wm;
++    wm->touch_dev->parent = dev;
++    wm->touch_dev->release = wm97xx_release;
++    if((ret = device_register(wm->touch_dev)) < 0)
++      goto touch_reg_err;
++
++    return ret;
++
++touch_reg_err:
++      kfree(wm->touch_dev);
++touch_err:
++    device_unregister(wm->battery_dev);
++batt_reg_err:
++      kfree(wm->battery_dev);
++batt_err:
++    input_unregister_device(wm->input_dev);
++    kfree(wm);
++    return ret;
++}
++
++static int wm97xx_remove(struct device *dev)
++{
++      struct wm97xx *wm = dev_get_drvdata(dev);
++
++      /* Stop touch reader thread */
++      if (wm->ts_task) {
++              wm->ts_task = NULL;
++              wm->pen_is_down = 1;
++              wake_up_interruptible(&wm->pen_irq_wait);
++              wait_for_completion(&wm->ts_exit);
++      }
++      device_unregister(wm->battery_dev);
++      device_unregister(wm->touch_dev);
++    input_unregister_device(wm->input_dev);
++
++      if(aux_sys)
++              wm97xx_sys_remove(dev);
++
++      kfree(wm);
++      return 0;
++}
++
++#ifdef CONFIG_PM
++int wm97xx_resume(struct device* dev)
++{
++      struct wm97xx *wm = dev_get_drvdata(dev);
++
++      /* restore digitiser and gpio's */
++      if(wm->id == WM9713_ID2) {
++              wm97xx_reg_write(wm, AC97_WM9713_DIG1, wm->dig[0]);
++              wm97xx_reg_write(wm, 0x5a, wm->misc);
++              if(wm->ts_use_count) {
++                      u16 reg = wm97xx_reg_read(wm, AC97_EXTENDED_MID) & 0x7fff;
++                      wm97xx_reg_write(wm, AC97_EXTENDED_MID, reg);
++              }
++      }
++
++      wm97xx_reg_write(wm, AC97_WM9713_DIG2, wm->dig[1]);
++      wm97xx_reg_write(wm, AC97_WM9713_DIG3, wm->dig[2]);
++
++      wm97xx_reg_write(wm, AC97_GPIO_CFG, wm->gpio[0]);
++      wm97xx_reg_write(wm, AC97_GPIO_POLARITY, wm->gpio[1]);
++      wm97xx_reg_write(wm, AC97_GPIO_STICKY, wm->gpio[2]);
++      wm97xx_reg_write(wm, AC97_GPIO_WAKEUP, wm->gpio[3]);
++      wm97xx_reg_write(wm, AC97_GPIO_STATUS, wm->gpio[4]);
++      wm97xx_reg_write(wm, AC97_MISC_AFE, wm->gpio[5]);
++
++      return 0;
++}
++
++#else
++#define wm97xx_resume         NULL
++#endif
++
++int wm97xx_register_mach_ops(struct wm97xx *wm, struct wm97xx_mach_ops *mach_ops)
++{
++      mutex_lock(&wm->codec_mutex);
++    if(wm->mach_ops) {
++      mutex_unlock(&wm->codec_mutex);
++      return -EINVAL;
++    }
++    wm->mach_ops = mach_ops;
++    mutex_unlock(&wm->codec_mutex);
++    return 0;
++}
++
++void wm97xx_unregister_mach_ops(struct wm97xx *wm)
++{
++      mutex_lock(&wm->codec_mutex);
++    wm->mach_ops = NULL;
++    mutex_unlock(&wm->codec_mutex);
++}
++
++static struct device_driver wm97xx_driver = {
++      .name =         "ac97",
++      .bus =          &ac97_bus_type,
++      .owner =        THIS_MODULE,
++      .probe =        wm97xx_probe,
++      .remove =       wm97xx_remove,
++      .resume =       wm97xx_resume,
++};
++
++static int __init wm97xx_init(void)
++{
++      int ret;
++
++      info("version %s liam.girdwood@wolfsonmicro.com", WM_CORE_VERSION);
++    if((ret = bus_register(&wm97xx_bus_type)) < 0)
++      return ret;
++      return driver_register(&wm97xx_driver);
++}
++
++static void __exit wm97xx_exit(void)
++{
++      driver_unregister(&wm97xx_driver);
++    bus_unregister(&wm97xx_bus_type);
++}
++
++EXPORT_SYMBOL_GPL(wm97xx_get_gpio);
++EXPORT_SYMBOL_GPL(wm97xx_set_gpio);
++EXPORT_SYMBOL_GPL(wm97xx_config_gpio);
++EXPORT_SYMBOL_GPL(wm97xx_read_aux_adc);
++EXPORT_SYMBOL_GPL(wm97xx_reg_read);
++EXPORT_SYMBOL_GPL(wm97xx_reg_write);
++EXPORT_SYMBOL_GPL(wm97xx_bus_type);
++EXPORT_SYMBOL_GPL(wm97xx_register_mach_ops);
++EXPORT_SYMBOL_GPL(wm97xx_unregister_mach_ops);
++
++module_init(wm97xx_init);
++module_exit(wm97xx_exit);
++
++/* Module information */
++MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com");
++MODULE_DESCRIPTION("WM97xx Core - Touch Screen / AUX ADC / GPIO Driver");
++MODULE_LICENSE("GPL");
+Index: linux-2.6.17/include/linux/wm97xx.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.17/include/linux/wm97xx.h        2006-09-19 20:36:47.973052250 +0200
+@@ -0,0 +1,291 @@
++
++/*
++ * Register bits and API for Wolfson WM97xx series of codecs
++ */
++
++#ifndef _LINUX_WM97XX_H
++#define _LINUX_WM97XX_H
++
++#include <sound/driver.h>
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/ac97_codec.h>
++#include <sound/initval.h>
++#include <linux/types.h>
++#include <linux/list.h>
++#include <linux/input.h>      /* Input device layer */
++
++/*
++ * WM97xx AC97 Touchscreen registers
++ */
++#define AC97_WM97XX_DIGITISER1                0x76
++#define AC97_WM97XX_DIGITISER2                0x78
++#define AC97_WM97XX_DIGITISER_RD      0x7a
++#define AC97_WM9713_DIG1                      0x74
++#define AC97_WM9713_DIG2                      AC97_WM97XX_DIGITISER1
++#define AC97_WM9713_DIG3                      AC97_WM97XX_DIGITISER2
++
++/*
++ * WM97xx register bits
++ */
++#define WM97XX_POLL                   0x8000  /* initiate a polling measurement */
++#define WM97XX_ADCSEL_X               0x1000  /* x coord measurement */
++#define WM97XX_ADCSEL_Y               0x2000  /* y coord measurement */
++#define WM97XX_ADCSEL_PRES    0x3000  /* pressure measurement */
++#define WM97XX_ADCSEL_MASK    0x7000
++#define WM97XX_COO                    0x0800  /* enable coordinate mode */
++#define WM97XX_CTC                    0x0400  /* enable continuous mode */
++#define WM97XX_CM_RATE_93     0x0000  /* 93.75Hz continuous rate */
++#define WM97XX_CM_RATE_187    0x0100  /* 187.5Hz continuous rate */
++#define WM97XX_CM_RATE_375    0x0200  /* 375Hz continuous rate */
++#define WM97XX_CM_RATE_750    0x0300  /* 750Hz continuous rate */
++#define WM97XX_CM_RATE_8K     0x00f0  /* 8kHz continuous rate */
++#define WM97XX_CM_RATE_12K    0x01f0  /* 12kHz continuous rate */
++#define WM97XX_CM_RATE_24K    0x02f0  /* 24kHz continuous rate */
++#define WM97XX_CM_RATE_48K    0x03f0  /* 48kHz continuous rate */
++#define WM97XX_CM_RATE_MASK   0x03f0
++#define WM97XX_RATE(i)                (((i & 3) << 8) | ((i & 4) ? 0xf0 : 0))
++#define WM97XX_DELAY(i)               ((i << 4) & 0x00f0)     /* sample delay times */
++#define WM97XX_DELAY_MASK     0x00f0
++#define WM97XX_SLEN                   0x0008  /* slot read back enable */
++#define WM97XX_SLT(i)         ((i - 5) & 0x7) /* touchpanel slot selection (5-11) */
++#define WM97XX_SLT_MASK               0x0007
++#define WM97XX_PRP_DETW               0x4000  /* pen detect on, digitiser off, wake up */
++#define WM97XX_PRP_DET                0x8000  /* pen detect on, digitiser off, no wake up */
++#define WM97XX_PRP_DET_DIG    0xc000  /* pen detect on, digitiser on */
++#define WM97XX_RPR                    0x2000  /* wake up on pen down */
++#define WM97XX_PEN_DOWN               0x8000  /* pen is down */
++#define WM97XX_ADCSRC_MASK    0x7000  /* ADC source mask */
++
++#define WM97XX_AUX_ID1                0x8001
++#define WM97XX_AUX_ID2                0x8002
++#define WM97XX_AUX_ID3                0x8003
++#define WM97XX_AUX_ID4                0x8004
++
++
++/* WM9712 Bits */
++#define WM9712_45W                    0x1000  /* set for 5-wire touchscreen */
++#define WM9712_PDEN                   0x0800  /* measure only when pen down */
++#define WM9712_WAIT                   0x0200  /* wait until adc is read before next sample */
++#define WM9712_PIL                    0x0100  /* current used for pressure measurement. set 400uA else 200uA */
++#define WM9712_MASK_HI                0x0040  /* hi on mask pin (47) stops conversions */
++#define WM9712_MASK_EDGE      0x0080  /* rising/falling edge on pin delays sample */
++#define       WM9712_MASK_SYNC        0x00c0  /* rising/falling edge on mask initiates sample */
++#define WM9712_RPU(i)         (i&0x3f)        /* internal pull up on pen detect (64k / rpu) */
++#define WM9712_PD(i)          (0x1 << i)      /* power management */
++
++/* WM9712 Registers */
++#define AC97_WM9712_POWER     0x24
++#define AC97_WM9712_REV               0x58
++
++/* WM9705 Bits */
++#define WM9705_PDEN                   0x1000  /* measure only when pen is down */
++#define WM9705_PINV                   0x0800  /* inverts sense of pen down output */
++#define WM9705_BSEN                   0x0400  /* BUSY flag enable, pin47 is 1 when busy */
++#define WM9705_BINV                   0x0200  /* invert BUSY (pin47) output */
++#define WM9705_WAIT                   0x0100  /* wait until adc is read before next sample */
++#define WM9705_PIL                    0x0080  /* current used for pressure measurement. set 400uA else 200uA */
++#define WM9705_PHIZ                   0x0040  /* set PHONE and PCBEEP inputs to high impedance */
++#define WM9705_MASK_HI                0x0010  /* hi on mask stops conversions */
++#define WM9705_MASK_EDGE      0x0020  /* rising/falling edge on pin delays sample */
++#define       WM9705_MASK_SYNC        0x0030  /* rising/falling edge on mask initiates sample */
++#define WM9705_PDD(i)         (i & 0x000f)    /* pen detect comparator threshold */
++
++
++/* WM9713 Bits */
++#define WM9713_PDPOL          0x0400  /* Pen down polarity */
++#define WM9713_POLL                   0x0200  /* initiate a polling measurement */
++#define WM9713_CTC                    0x0100  /* enable continuous mode */
++#define WM9713_ADCSEL_X               0x0002  /* X measurement */
++#define WM9713_ADCSEL_Y               0x0004  /* Y measurement */
++#define WM9713_ADCSEL_PRES    0x0008  /* Pressure measurement */
++#define WM9713_COO                    0x0001  /* enable coordinate mode */
++#define WM9713_PDEN                   0x0800  /* measure only when pen down */
++#define WM9713_ADCSEL_MASK    0x00fe  /* ADC selection mask */
++#define WM9713_WAIT                   0x0200  /* coordinate wait */
++
++/* AUX ADC ID's */
++#define TS_COMP1                      0x0
++#define TS_COMP2                      0x1
++#define TS_BMON                               0x2
++#define TS_WIPER                      0x3
++
++/* ID numbers */
++#define WM97XX_ID1                    0x574d
++#define WM9712_ID2                    0x4c12
++#define WM9705_ID2                    0x4c05
++#define WM9713_ID2                    0x4c13
++
++/* Codec GPIO's */
++#define WM97XX_MAX_GPIO               16
++#define WM97XX_GPIO_1         (1 << 1)
++#define WM97XX_GPIO_2         (1 << 2)
++#define WM97XX_GPIO_3         (1 << 3)
++#define WM97XX_GPIO_4         (1 << 4)
++#define WM97XX_GPIO_5         (1 << 5)
++#define WM97XX_GPIO_6         (1 << 6)
++#define WM97XX_GPIO_7         (1 << 7)
++#define WM97XX_GPIO_8         (1 << 8)
++#define WM97XX_GPIO_9         (1 << 9)
++#define WM97XX_GPIO_10                (1 << 10)
++#define WM97XX_GPIO_11                (1 << 11)
++#define WM97XX_GPIO_12                (1 << 12)
++#define WM97XX_GPIO_13                (1 << 13)
++#define WM97XX_GPIO_14                (1 << 14)
++#define WM97XX_GPIO_15                (1 << 15)
++
++
++#define AC97_LINK_FRAME               21      /* time in uS for AC97 link frame */
++
++
++/*---------------- Return codes from sample reading functions ---------------*/
++
++/* More data is available; call the sample gathering function again */
++#define RC_AGAIN                      0x00000001
++/* The returned sample is valid */
++#define RC_VALID                      0x00000002
++/* The pen is up (the first RC_VALID without RC_PENUP means pen is down) */
++#define RC_PENUP                      0x00000004
++/* The pen is down (RC_VALID implies RC_PENDOWN, but sometimes it is helpful
++   to tell the handler that the pen is down but we don't know yet his coords,
++   so the handler should not sleep or wait for pendown irq) */
++#define RC_PENDOWN                    0x00000008
++
++/* The wm97xx driver provides a private API for writing platform-specific
++ * drivers.
++ */
++
++/* The structure used to return arch specific sampled data into */
++struct wm97xx_data {
++    int x;
++    int y;
++    int p;
++};
++
++/* Codec GPIO status
++ */
++typedef enum {
++    WM97XX_GPIO_HIGH,
++    WM97XX_GPIO_LOW
++} wm97xx_gpio_status_t;
++
++/* Codec GPIO direction
++ */
++typedef enum {
++    WM97XX_GPIO_IN,
++    WM97XX_GPIO_OUT
++} wm97xx_gpio_dir_t;
++
++/* Codec GPIO polarity
++ */
++typedef enum {
++    WM97XX_GPIO_POL_HIGH,
++    WM97XX_GPIO_POL_LOW
++} wm97xx_gpio_pol_t;
++
++/* Codec GPIO sticky
++ */
++typedef enum {
++    WM97XX_GPIO_STICKY,
++    WM97XX_GPIO_NOTSTICKY
++} wm97xx_gpio_sticky_t;
++
++/* Codec GPIO wake
++ */
++typedef enum {
++    WM97XX_GPIO_WAKE,
++    WM97XX_GPIO_NOWAKE
++} wm97xx_gpio_wake_t;
++
++
++/*
++ * Digitiser ioctl commands
++ */
++#define WM97XX_DIG_START      0x1
++#define WM97XX_DIG_STOP               0x2
++#define WM97XX_PHY_INIT               0x3
++#define WM97XX_AUX_PREPARE    0x4
++#define WM97XX_DIG_RESTORE    0x5
++
++struct wm97xx;
++extern struct wm97xx_codec_drv wm97xx_codec;
++
++/*
++ * Codec driver interface - allows mapping to WM9705/12/13 and newer codecs
++ */
++struct wm97xx_codec_drv {
++      u16 id;
++    char *name;
++      int (*poll_sample) (struct wm97xx *, int adcsel, int *sample);  /* read 1 sample */
++      int (*poll_touch) (struct wm97xx *, struct wm97xx_data *);      /* read X,Y,[P] in poll */
++      int (*digitiser_ioctl) (struct wm97xx *, int cmd);
++      int (*acc_enable) (struct wm97xx *, int enable);
++};
++
++
++/* Machine specific and accelerated touch operations */
++struct wm97xx_mach_ops {
++
++      /* accelerated touch readback - coords are transmited on AC97 link */
++      int acc_enabled;
++    void (*acc_pen_up) (struct wm97xx *);
++    int (*acc_pen_down) (struct wm97xx *);
++    int (*acc_startup) (struct wm97xx *);
++    void (*acc_shutdown) (struct wm97xx *);
++
++    /* pre and post sample - can be used to minimise any analog noise */
++    void (*pre_sample) (int);  /* function to run before sampling */
++    void (*post_sample) (int);  /* function to run after sampling */
++};
++
++struct wm97xx {
++      u16 dig[3], id, gpio[6], misc;  /* Cached codec registers */
++      u16 dig_save[3];                /* saved during aux reading */
++      struct wm97xx_codec_drv *codec; /* attached codec driver*/
++      struct input_dev* input_dev;    /* touchscreen input device */
++      ac97_t *ac97;                   /* ALSA codec access */
++      struct device *dev;             /* ALSA device */
++    struct device *battery_dev;
++    struct device *touch_dev;
++    struct wm97xx_mach_ops *mach_ops;
++    struct mutex codec_mutex;
++      struct completion ts_init;
++      struct completion ts_exit;
++      struct task_struct *ts_task;
++      unsigned int pen_irq;   /* Pen IRQ number in use */
++      wait_queue_head_t pen_irq_wait; /* Pen IRQ wait queue */
++      struct workqueue_struct *pen_irq_workq;
++      struct work_struct pen_event_work;
++      u16 acc_slot; /* AC97 slot used for acc touch data */
++      u16 acc_rate; /* acc touch data rate */
++      unsigned int ts_use_count;
++      unsigned pen_is_down:1; /* Pen is down */
++      unsigned aux_waiting:1; /* aux measurement waiting */
++      unsigned pen_probably_down:1;   /* used in polling mode */
++};
++
++/* Codec GPIO access (not supported on WM9705)
++ * This can be used to set/get codec GPIO and Virtual GPIO status.
++ */
++wm97xx_gpio_status_t wm97xx_get_gpio(struct wm97xx *wm, u32 gpio);
++void wm97xx_set_gpio(struct wm97xx *wm, u32 gpio,
++                        wm97xx_gpio_status_t status);
++void wm97xx_config_gpio(struct wm97xx *wm, u32 gpio,
++                                   wm97xx_gpio_dir_t dir,
++                                   wm97xx_gpio_pol_t pol,
++                                   wm97xx_gpio_sticky_t sticky,
++                                   wm97xx_gpio_wake_t wake);
++
++/* codec AC97 IO access */
++int wm97xx_reg_read(struct wm97xx *wm, u16 reg);
++void wm97xx_reg_write(struct wm97xx *wm, u16 reg, u16 val);
++
++/* aux adc readback */
++int wm97xx_read_aux_adc(struct wm97xx *wm, u16 adcsel);
++
++/* machine ops */
++int wm97xx_register_mach_ops(struct wm97xx *, struct wm97xx_mach_ops *);
++void wm97xx_unregister_mach_ops(struct wm97xx *);
++
++extern struct bus_type wm97xx_bus_type;
++#endif
diff --git a/packages/kexecboot/linux-kexecboot-2.6.23/zylonite-boot.patch b/packages/kexecboot/linux-kexecboot-2.6.23/zylonite-boot.patch
new file mode 100644 (file)
index 0000000..f41928e
--- /dev/null
@@ -0,0 +1,45 @@
+From 04c42f566c68b757fdadf54e0e0f9dfe9f3f9b06 Mon Sep 17 00:00:00 2001
+From: eric miao <eric.miao@marvell.com>
+Date: Tue, 19 Jun 2007 16:42:53 +0800
+Subject: [PATCH] [PATCH] make zylonite boot
+
+1. reuse head-xscale.S for XSC3
+
+2. add a workaround for machine ID assignment, which should be done
+   by boot loader
+---
+ arch/arm/boot/compressed/Makefile      |    4 ++++
+ arch/arm/boot/compressed/head-xscale.S |    5 +++++
+ 2 files changed, 9 insertions(+)
+
+Index: linux-2.6-pxa3/arch/arm/boot/compressed/Makefile
+===================================================================
+--- linux-2.6-pxa3.orig/arch/arm/boot/compressed/Makefile      2007-09-24 11:25:57.000000000 +0200
++++ linux-2.6-pxa3/arch/arm/boot/compressed/Makefile   2007-09-24 12:26:53.000000000 +0200
+@@ -40,6 +40,10 @@
+ OBJS          += head-xscale.o
+ endif
++ifeq ($(CONFIG_CPU_XSC3),y)
++OBJS          += head-xscale.o
++endif
++
+ ifeq ($(CONFIG_PXA_SHARPSL),y)
+ OBJS          += head-sharpsl.o
+ endif
+Index: linux-2.6-pxa3/arch/arm/boot/compressed/head-xscale.S
+===================================================================
+--- linux-2.6-pxa3.orig/arch/arm/boot/compressed/head-xscale.S 2007-09-24 11:42:27.000000000 +0200
++++ linux-2.6-pxa3/arch/arm/boot/compressed/head-xscale.S      2007-09-24 12:26:02.000000000 +0200
+@@ -33,6 +33,11 @@
+               bic     r0, r0, #0x1000         @ clear Icache
+               mcr     p15, 0, r0, c1, c0, 0
++#ifdef CONFIG_MACH_ZYLONITE
++              mov     r7, #(MACH_TYPE_ZYLONITE & 0xff)
++              orr     r7, r7, #(MACH_TYPE_ZYLONITE & 0xff00)
++#endif
++
+ #ifdef CONFIG_ARCH_COTULLA_IDP
+               mov     r7, #MACH_TYPE_COTULLA_IDP
+ #endif
diff --git a/packages/kexecboot/linux-kexecboot-2.6.23/zylonite/defconfig b/packages/kexecboot/linux-kexecboot-2.6.23/zylonite/defconfig
new file mode 100644 (file)
index 0000000..d989749
--- /dev/null
@@ -0,0 +1,1527 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.23
+# Mon Feb 18 01:42:46 2008
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_MMU=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ZONE_DMA=y
+CONFIG_ARCH_MTD_XIP=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+# CONFIG_EMBEDDED is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+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 is not set
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+
+#
+# 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_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_MXC 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_DAVINCI is not set
+# CONFIG_ARCH_OMAP is not set
+
+#
+# Intel PXA2xx/PXA3xx Implementations
+#
+
+#
+# Supported PXA3xx Processor Variants
+#
+CONFIG_CPU_PXA300=y
+CONFIG_CPU_PXA310=y
+CONFIG_CPU_PXA320=y
+# 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 is not set
+# CONFIG_MACH_EM_X270 is not set
+CONFIG_MACH_ZYLONITE=y
+# CONFIG_MACH_HX2750 is not set
+# CONFIG_MACH_HTCUNIVERSAL is not set
+CONFIG_PXA3xx=y
+
+#
+# Boot options
+#
+
+#
+# Power management
+#
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_XSC3=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+CONFIG_IO_36=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+# CONFIG_OUTER_CACHE is not set
+CONFIG_IWMMXT=y
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_TICK_ONESHOT is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+# CONFIG_PREEMPT is not set
+CONFIG_HZ=100
+CONFIG_AEABI=y
+CONFIG_OABI_COMPAT=y
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+CONFIG_RESOURCES_64BIT=y
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=ttyS0,38400 root=/dev/mtdblock2 rootfstype=jffs2 mem=64M  dyntick=enable debug"
+# CONFIG_XIP_KERNEL is not set
+CONFIG_KEXEC=y
+CONFIG_ATAGS_PROC=y
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+CONFIG_SUSPEND_UP_POSSIBLE=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=m
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK is not set
+# CONFIG_NF_CONNTRACK_ENABLED is not set
+# CONFIG_NF_CONNTRACK is not set
+CONFIG_NETFILTER_XTABLES=m
+# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
+# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
+# CONFIG_NETFILTER_XT_TARGET_MARK is not set
+# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
+# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
+# CONFIG_NETFILTER_XT_TARGET_TRACE is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
+# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
+# CONFIG_NETFILTER_XT_MATCH_ESP is not set
+# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
+# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_MAC is not set
+# CONFIG_NETFILTER_XT_MATCH_MARK is not set
+# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
+# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
+# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
+# CONFIG_NETFILTER_XT_MATCH_REALM is not set
+# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
+# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
+# CONFIG_NETFILTER_XT_MATCH_STRING is not set
+# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_U32 is not set
+# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=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_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# 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=y
+
+#
+# IrDA protocols
+#
+# CONFIG_IRLAN is not set
+# CONFIG_IRCOMM is not set
+# CONFIG_IRDA_ULTRA is not set
+
+#
+# IrDA options
+#
+# CONFIG_IRDA_CACHE_LAST_LSAP is not set
+# CONFIG_IRDA_FAST_RR is not set
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+# CONFIG_IRTTY_SIR is not set
+
+#
+# Dongle support
+#
+# CONFIG_KINGSUN_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_MCS_FIR is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+# CONFIG_STANDALONE is not set
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+CONFIG_MTD_CFI_ADV_OPTIONS=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=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_OTP is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+CONFIG_MTD_ROM=y
+# CONFIG_MTD_ABSENT 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
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_H1900 is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_SHARPSL is not set
+CONFIG_MTD_NAND_ZYLONITE=y
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+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_BLK_DEV_IDESCSI is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_PROC_FS=y
+
+#
+# IDE chipset support/bugfixes
+#
+# CONFIG_IDE_GENERIC is not set
+# CONFIG_IDEPCI_PCIBUS_ORDER is not set
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+CONFIG_SMC91X=y
+# CONFIG_DM9000 is not set
+# CONFIG_SMC911X is not set
+CONFIG_NETDEV_1000=y
+CONFIG_NETDEV_10000=y
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 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_MII is not set
+CONFIG_USB_USBNET=y
+# CONFIG_USB_NET_AX8817X is not set
+CONFIG_USB_NET_CDCETHER=y
+# CONFIG_USB_NET_DM9601 is not set
+# CONFIG_USB_NET_GL620A is not set
+# CONFIG_USB_NET_NET1080 is not set
+# CONFIG_USB_NET_PLUSB is not set
+# CONFIG_USB_NET_MCS7830 is not set
+# CONFIG_USB_NET_RNDIS_HOST is not set
+CONFIG_USB_NET_CDC_SUBSET=y
+# CONFIG_USB_ALI_M5632 is not set
+# CONFIG_USB_AN2720 is not set
+# CONFIG_USB_BELKIN is not set
+CONFIG_USB_ARMLINUX=y
+# CONFIG_USB_EPSON2888 is not set
+# CONFIG_USB_KC2190 is not set
+# CONFIG_USB_NET_ZAURUS is not set
+# 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
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_TSDEV=y
+CONFIG_INPUT_TSDEV_SCREEN_X=240
+CONFIG_INPUT_TSDEV_SCREEN_Y=320
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+# CONFIG_INPUT_POWER is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+CONFIG_KEYBOARD_PXA27x=y
+# CONFIG_KEYBOARD_GPIO is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ZYLONITE=y
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_UCB1400 is not set
+# CONFIG_TOUCHSCREEN_USB_COMPOSITE 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 is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_WATCHDOG is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_NVRAM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# 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_GPIO is not set
+CONFIG_I2C_PXA=y
+# CONFIG_I2C_PXA_SLAVE is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_DS1682 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_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+CONFIG_W1=y
+
+#
+# 1-wire Bus Masters
+#
+# CONFIG_W1_MASTER_DS2490 is not set
+# CONFIG_W1_MASTER_DS2482 is not set
+# CONFIG_W1_MASTER_DS1WM is not set
+
+#
+# 1-wire Slaves
+#
+# CONFIG_W1_SLAVE_THERM is not set
+# CONFIG_W1_SLAVE_SMEM is not set
+# CONFIG_W1_SLAVE_DS2433 is not set
+# CONFIG_W1_SLAVE_DS2760 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_EEPROM_93CX6 is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_ASIC3 is not set
+# CONFIG_HTC_ASIC3_DS1WM is not set
+
+#
+# Multi-Function Devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=y
+CONFIG_VIDEO_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_VIDEO_V4L2=y
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_TUNER_3036 is not set
+# CONFIG_TUNER_TEA5761 is not set
+CONFIG_V4L_USB_DRIVERS=y
+# CONFIG_VIDEO_PVRUSB2 is not set
+# CONFIG_VIDEO_EM28XX is not set
+# CONFIG_VIDEO_USBVISION is not set
+# CONFIG_USB_VICAM is not set
+# CONFIG_USB_IBMCAM is not set
+# CONFIG_USB_KONICAWC is not set
+# CONFIG_USB_QUICKCAM_MESSENGER is not set
+# CONFIG_USB_ET61X251 is not set
+# CONFIG_VIDEO_OVCAMCHIP is not set
+# CONFIG_USB_W9968CF is not set
+# CONFIG_USB_OV511 is not set
+# CONFIG_USB_SE401 is not set
+# CONFIG_USB_SN9C102 is not set
+# CONFIG_USB_STV680 is not set
+# CONFIG_USB_ZC0301 is not set
+# CONFIG_USB_PWC is not set
+# CONFIG_USB_ZR364XX is not set
+CONFIG_RADIO_ADAPTERS=y
+# CONFIG_USB_DSBR is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=y
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_SYS_FOPS is not set
+CONFIG_FB_DEFERRED_IO=y
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+CONFIG_FB_MODE_HELPERS=y
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_PXA=y
+# CONFIG_FB_PXA_LCD_QVGA is not set
+CONFIG_FB_PXA_LCD_VGA=y
+CONFIG_FB_PXA_OVERLAY=y
+# CONFIG_FB_PXA_PARAMETERS is not set
+# CONFIG_FB_MBX 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_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+CONFIG_FONTS=y
+# CONFIG_FONT_8x8 is not set
+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
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+CONFIG_LOGO_OHAND_CLUT224=y
+
+#
+# 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_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_PCM_OSS_PLUGINS=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# ALSA ARM devices
+#
+# CONFIG_SND_PXA2XX_AC97 is not set
+
+#
+# USB devices
+#
+# CONFIG_SND_USB_AUDIO is not set
+# CONFIG_SND_USB_CAIAQ is not set
+
+#
+# System on Chip audio support
+#
+# CONFIG_SND_SOC is not set
+
+#
+# SoC Audio support for SuperH
+#
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=m
+# CONFIG_HID_DEBUG is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEVICEFS is not set
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=y
+# 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_ISD200 is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK 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_ADUTUX is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG is not set
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_PXA2XX is not set
+CONFIG_USB_GADGET_M66592=y
+CONFIG_USB_M66592=y
+# CONFIG_USB_GADGET_PXA27X is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+CONFIG_USB_GADGET_DUALSPEED=y
+# CONFIG_USB_ZERO is not set
+# CONFIG_USB_ETH is not set
+# CONFIG_USB_GADGETFS is not set
+CONFIG_USB_FILE_STORAGE=y
+# CONFIG_USB_FILE_STORAGE_TEST is not set
+# CONFIG_USB_G_SERIAL is not set
+# CONFIG_USB_MIDI_GADGET is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+
+#
+# MMC/SD Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+
+#
+# MMC/SD Host Controller Drivers
+#
+CONFIG_MMC_PXA=y
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_SA1100=y
+
+#
+# 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=m
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_JBD=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 is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_SYSFS is not set
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_LZO=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_JFFS2_CMODE_FAVOURLZO is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS 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 is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_BIND34 is not set
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
+# Profiling support
+#
+CONFIG_PROFILING=y
+# CONFIG_OPROFILE is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
+CONFIG_FRAME_POINTER=y
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+CONFIG_DEBUG_USER=y
+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
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_MANAGER=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_ECB=y
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=y
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_TEST is not set
+CONFIG_CRYPTO_HW=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/packages/kexecboot/linux-kexecboot-2.6.23/zylonite_keypad-r0.patch b/packages/kexecboot/linux-kexecboot-2.6.23/zylonite_keypad-r0.patch
new file mode 100644 (file)
index 0000000..1889b38
--- /dev/null
@@ -0,0 +1,1187 @@
+Eric Miao's pxa keypad patchset backport.
+---
+ arch/arm/mach-pxa/devices.h                |    1 
+ arch/arm/mach-pxa/generic.c                |   31 +
+ arch/arm/mach-pxa/pxa27x.c                 |    2 
+ arch/arm/mach-pxa/pxa300.c                 |    6 
+ arch/arm/mach-pxa/pxa3xx.c                 |    1 
+ arch/arm/mach-pxa/zylonite.c               |   68 +++
+ drivers/input/keyboard/Kconfig             |    8 
+ drivers/input/keyboard/Makefile            |    2 
+ drivers/input/keyboard/pxa27x_keyboard.c   |  273 -------------
+ drivers/input/keyboard/pxa27x_keypad.c     |  575 +++++++++++++++++++++++++++++
+ include/asm-arm/arch-pxa/irqs.h            |    2 
+ include/asm-arm/arch-pxa/pxa27x_keyboard.h |   13 
+ include/asm-arm/arch-pxa/pxa27x_keypad.h   |   58 ++
+ 13 files changed, 745 insertions(+), 295 deletions(-)
+
+Index: linux-2.6.23-z-input/drivers/input/keyboard/Kconfig
+===================================================================
+--- linux-2.6.23-z-input.orig/drivers/input/keyboard/Kconfig   2008-02-18 01:43:28.000000000 +0100
++++ linux-2.6.23-z-input/drivers/input/keyboard/Kconfig        2008-02-18 01:43:28.000000000 +0100
+@@ -218,13 +218,13 @@
+         module will be called omap-keypad.
+ config KEYBOARD_PXA27x
+-      tristate "PXA27x keyboard support"
+-      depends on PXA27x
++      tristate "PXA27x/PXA3xx keypad support"
++      depends on PXA27x || PXA3xx
+       help
+-        Enable support for PXA27x matrix keyboard controller
++        Enable support for PXA27x/PXA3xx keypad controller
+         To compile this driver as a module, choose M here: the
+-        module will be called pxa27x_keyboard.
++        module will be called pxa27x_keypad.
+ config KEYBOARD_AAED2000
+       tristate "AAED-2000 keyboard"
+Index: linux-2.6.23-z-input/drivers/input/keyboard/Makefile
+===================================================================
+--- linux-2.6.23-z-input.orig/drivers/input/keyboard/Makefile  2008-02-18 01:43:28.000000000 +0100
++++ linux-2.6.23-z-input/drivers/input/keyboard/Makefile       2008-02-18 01:43:28.000000000 +0100
+@@ -18,7 +18,7 @@
+ obj-$(CONFIG_KEYBOARD_HIL)            += hil_kbd.o
+ obj-$(CONFIG_KEYBOARD_HIL_OLD)                += hilkbd.o
+ obj-$(CONFIG_KEYBOARD_OMAP)           += omap-keypad.o
+-obj-$(CONFIG_KEYBOARD_PXA27x)         += pxa27x_keyboard.o
++obj-$(CONFIG_KEYBOARD_PXA27x)         += pxa27x_keypad.o
+ obj-$(CONFIG_KEYBOARD_AAED2000)               += aaed2000_kbd.o
+ obj-$(CONFIG_KEYBOARD_GPIO)           += gpio_keys.o
+ obj-$(CONFIG_KEYBOARD_ASIC3)          += asic3_keys.o
+Index: linux-2.6.23-z-input/drivers/input/keyboard/pxa27x_keypad.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.23-z-input/drivers/input/keyboard/pxa27x_keypad.c        2008-02-19 01:40:04.000000000 +0100
+@@ -0,0 +1,575 @@
++/*
++ * linux/drivers/input/keyboard/pxa27x_keypad.c
++ *
++ * Driver for the pxa27x matrix keyboard controller.
++ *
++ * Created:   Feb 22, 2007
++ * Author:    Rodolfo Giometti <giometti@linux.it>
++ *
++ * Based on a previous implementations by Kevin O'Connor
++ * <kevin_at_koconnor.net> and Alex Osborne <bobofdoom@gmail.com> and
++ * on some suggestions by Nicolas Pitre <nico@cam.org>.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <linux/input.h>
++#include <linux/device.h>
++#include <linux/platform_device.h>
++#include <linux/clk.h>
++#include <linux/err.h>
++
++#include <asm/mach-types.h>
++#include <asm/mach/arch.h>
++#include <asm/mach/map.h>
++
++#include <asm/arch/hardware.h>
++#include <asm/arch/mfp.h>
++#include <asm/arch/pxa27x_keypad.h>
++
++#define BIT_MASK(nr)            (1UL << ((nr) % BITS_PER_LONG))
++
++/*
++ * Keypad Controller registers
++ */
++#define KPC             0x0000 /* Keypad Control register */
++#define KPDK            0x0008 /* Keypad Direct Key register */
++#define KPREC           0x0010 /* Keypad Rotary Encoder register */
++#define KPMK            0x0018 /* Keypad Matrix Key register */
++#define KPAS            0x0020 /* Keypad Automatic Scan register */
++
++/* Keypad Automatic Scan Multiple Key Presser register 0-3 */
++#define KPASMKP0        0x0028
++#define KPASMKP1        0x0030
++#define KPASMKP2        0x0038
++#define KPASMKP3        0x0040
++#define KPKDI           0x0048
++
++/* bit definitions */
++#define KPC_MKRN(n)   ((((n) - 1) & 0x7) << 26) /* matrix key row number */
++#define KPC_MKCN(n)   ((((n) - 1) & 0x7) << 23) /* matrix key column number */
++#define KPC_DKN(n)    ((((n) - 1) & 0x7) << 6)  /* direct key number */
++
++#define KPC_AS          (0x1 << 30)  /* Automatic Scan bit */
++#define KPC_ASACT       (0x1 << 29)  /* Automatic Scan on Activity */
++#define KPC_MI          (0x1 << 22)  /* Matrix interrupt bit */
++#define KPC_IMKP        (0x1 << 21)  /* Ignore Multiple Key Press */
++
++#define KPC_MS(n)     (0x1 << (13 + (n)))     /* Matrix scan line 'n' */
++#define KPC_MS_ALL      (0xff << 13)
++
++#define KPC_ME          (0x1 << 12)  /* Matrix Keypad Enable */
++#define KPC_MIE         (0x1 << 11)  /* Matrix Interrupt Enable */
++#define KPC_DK_DEB_SEL        (0x1 <<  9)  /* Direct Keypad Debounce Select */
++#define KPC_DI          (0x1 <<  5)  /* Direct key interrupt bit */
++#define KPC_RE_ZERO_DEB (0x1 <<  4)  /* Rotary Encoder Zero Debounce */
++#define KPC_REE1        (0x1 <<  3)  /* Rotary Encoder1 Enable */
++#define KPC_REE0        (0x1 <<  2)  /* Rotary Encoder0 Enable */
++#define KPC_DE          (0x1 <<  1)  /* Direct Keypad Enable */
++#define KPC_DIE         (0x1 <<  0)  /* Direct Keypad interrupt Enable */
++
++#define KPDK_DKP        (0x1 << 31)
++#define KPDK_DK(n)    ((n) & 0xff)
++
++#define KPREC_OF1       (0x1 << 31)
++#define kPREC_UF1       (0x1 << 30)
++#define KPREC_OF0       (0x1 << 15)
++#define KPREC_UF0       (0x1 << 14)
++
++#define KPREC_RECOUNT0(n)     ((n) & 0xff)
++#define KPREC_RECOUNT1(n)     (((n) >> 16) & 0xff)
++
++#define KPMK_MKP        (0x1 << 31)
++#define KPAS_SO         (0x1 << 31)
++#define KPASMKPx_SO     (0x1 << 31)
++
++#define KPAS_MUKP(n)  (((n) >> 26) & 0x1f)
++#define KPAS_RP(n)    (((n) >> 4) & 0xf)
++#define KPAS_CP(n)    ((n) & 0xf)
++
++#define KPASMKP_MKC_MASK      (0xff)
++
++#define keypad_readl(off)     __raw_readl(keypad->mmio_base + (off))
++#define keypad_writel(off, v) __raw_writel((v), keypad->mmio_base + (off))
++
++#define MAX_MATRIX_KEY_NUM    (8 * 8)
++
++struct pxa27x_keypad {
++      struct pxa27x_keypad_platform_data *pdata;
++
++      struct clk *clk;
++      struct input_dev *input_dev;
++      void __iomem *mmio_base;
++
++      /* matrix key code map */
++      unsigned int matrix_keycodes[MAX_MATRIX_KEY_NUM];
++
++      /* state row bits of each column scan */
++      uint32_t matrix_key_state[MAX_MATRIX_KEY_COLS];
++      uint32_t direct_key_state;
++
++      unsigned int direct_key_mask;
++
++      int rotary_rel_code[2];
++      int rotary_up_key[2];
++      int rotary_down_key[2];
++};
++
++static void pxa27x_keypad_build_keycode(struct pxa27x_keypad *keypad)
++{
++      struct pxa27x_keypad_platform_data *pdata = keypad->pdata;
++      struct input_dev *input_dev = keypad->input_dev;
++      unsigned int *key;
++      int i;
++
++      key = &pdata->matrix_key_map[0];
++      for (i = 0; i < pdata->matrix_key_map_size; i++, key++) {
++              int row = ((*key) >> 28) & 0xf;
++              int col = ((*key) >> 24) & 0xf;
++              int code = (*key) & 0xffffff;
++
++              keypad->matrix_keycodes[(row << 3) + col] = code;
++              set_bit(code, input_dev->keybit);
++      }
++
++      keypad->rotary_up_key[0] = pdata->rotary0_up_key;
++      keypad->rotary_up_key[1] = pdata->rotary1_up_key;
++      keypad->rotary_down_key[0] = pdata->rotary0_down_key;
++      keypad->rotary_down_key[1] = pdata->rotary1_down_key;
++      keypad->rotary_rel_code[0] = pdata->rotary0_rel_code;
++      keypad->rotary_rel_code[1] = pdata->rotary1_rel_code;
++
++      if (pdata->rotary0_up_key && pdata->rotary0_down_key) {
++              set_bit(pdata->rotary0_up_key, input_dev->keybit);
++              set_bit(pdata->rotary0_down_key, input_dev->keybit);
++      } else
++              set_bit(pdata->rotary0_rel_code, input_dev->relbit);
++
++      if (pdata->rotary1_up_key && pdata->rotary1_down_key) {
++              set_bit(pdata->rotary1_up_key, input_dev->keybit);
++              set_bit(pdata->rotary1_down_key, input_dev->keybit);
++      } else
++              set_bit(pdata->rotary1_rel_code, input_dev->relbit);
++}
++
++static inline unsigned int lookup_matrix_keycode(
++              struct pxa27x_keypad *keypad, int row, int col)
++{
++      return keypad->matrix_keycodes[(row << 3) + col];
++}
++
++static void pxa27x_keypad_scan_matrix(struct pxa27x_keypad *keypad)
++{
++      struct pxa27x_keypad_platform_data *pdata = keypad->pdata;
++      int row, col, num_keys_pressed = 0;
++      uint32_t new_state[MAX_MATRIX_KEY_COLS];
++      uint32_t kpas = keypad_readl(KPAS);
++
++      num_keys_pressed = KPAS_MUKP(kpas);
++
++      memset(new_state, 0, sizeof(new_state));
++
++      if (num_keys_pressed == 0)
++              goto scan;
++
++      if (num_keys_pressed == 1) {
++              col = KPAS_CP(kpas);
++              row = KPAS_RP(kpas);
++
++              /* if invalid row/col, treat as no key pressed */
++              if (col >= pdata->matrix_key_cols ||
++                  row >= pdata->matrix_key_rows)
++                      goto scan;
++
++              new_state[col] = (1 << row);
++              goto scan;
++      }
++
++      if (num_keys_pressed > 1) {
++              uint32_t kpasmkp0 = keypad_readl(KPASMKP0);
++              uint32_t kpasmkp1 = keypad_readl(KPASMKP1);
++              uint32_t kpasmkp2 = keypad_readl(KPASMKP2);
++              uint32_t kpasmkp3 = keypad_readl(KPASMKP3);
++
++              new_state[0] = kpasmkp0 & KPASMKP_MKC_MASK;
++              new_state[1] = (kpasmkp0 >> 16) & KPASMKP_MKC_MASK;
++              new_state[2] = kpasmkp1 & KPASMKP_MKC_MASK;
++              new_state[3] = (kpasmkp1 >> 16) & KPASMKP_MKC_MASK;
++              new_state[4] = kpasmkp2 & KPASMKP_MKC_MASK;
++              new_state[5] = (kpasmkp2 >> 16) & KPASMKP_MKC_MASK;
++              new_state[6] = kpasmkp3 & KPASMKP_MKC_MASK;
++              new_state[7] = (kpasmkp3 >> 16) & KPASMKP_MKC_MASK;
++      }
++scan:
++      for (col = 0; col < pdata->matrix_key_cols; col++) {
++              uint32_t bits_changed;
++
++              bits_changed = keypad->matrix_key_state[col] ^ new_state[col];
++              if (bits_changed == 0)
++                      continue;
++
++              for (row = 0; row < pdata->matrix_key_rows; row++) {
++                      if ((bits_changed & (1 << row)) == 0)
++                              continue;
++
++                      input_report_key(keypad->input_dev,
++                              lookup_matrix_keycode(keypad, row, col),
++                              new_state[col] & (1 << row));
++              }
++      }
++      input_sync(keypad->input_dev);
++      memcpy(keypad->matrix_key_state, new_state, sizeof(new_state));
++}
++
++#define DEFAULT_KPREC (0x007f007f)
++
++static inline int rotary_delta(uint32_t kprec)
++{
++      if (kprec & KPREC_OF0)
++              return (kprec & 0xff) + 0x7f;
++      else if (kprec & KPREC_UF0)
++              return (kprec & 0xff) - 0x7f - 0xff;
++      else
++              return (kprec & 0xff) - 0x7f;
++}
++
++static void report_rotary_event(struct pxa27x_keypad *keypad, int r, int delta)
++{
++      struct input_dev *dev = keypad->input_dev;
++
++      if (delta == 0)
++              return;
++
++      if (keypad->rotary_up_key[r] && keypad->rotary_down_key[r]) {
++              int keycode = (delta > 0) ? keypad->rotary_up_key[r] :
++                                          keypad->rotary_down_key[r];
++
++              /* simulate a press-n-release */
++              input_report_key(dev, keycode, 1);
++              input_sync(dev);
++              input_report_key(dev, keycode, 0);
++              input_sync(dev);
++      } else {
++              input_report_rel(dev, keypad->rotary_rel_code[r], delta);
++              input_sync(dev);
++      }
++}
++
++static void pxa27x_keypad_scan_rotary(struct pxa27x_keypad *keypad)
++{
++      struct pxa27x_keypad_platform_data *pdata = keypad->pdata;
++      uint32_t kprec;
++
++      /* read and reset to default count value */
++      kprec = keypad_readl(KPREC);
++      keypad_writel(KPREC, DEFAULT_KPREC);
++
++      if (pdata->enable_rotary0)
++              report_rotary_event(keypad, 0, rotary_delta(kprec));
++
++      if (pdata->enable_rotary1)
++              report_rotary_event(keypad, 1, rotary_delta(kprec >> 16));
++}
++
++static void pxa27x_keypad_scan_direct(struct pxa27x_keypad *keypad)
++{
++      struct pxa27x_keypad_platform_data *pdata = keypad->pdata;
++      unsigned int new_state;
++      uint32_t kpdk, bits_changed;
++      int i;
++
++      kpdk = keypad_readl(KPDK);
++
++      if (pdata->enable_rotary0 || pdata->enable_rotary1)
++              pxa27x_keypad_scan_rotary(keypad);
++
++      if (pdata->direct_key_map == NULL)
++              return;
++
++      new_state = KPDK_DK(kpdk) & keypad->direct_key_mask;
++      bits_changed = keypad->direct_key_state ^ new_state;
++
++      if (bits_changed == 0)
++              return;
++
++      for (i = 0; i < pdata->direct_key_num; i++) {
++              if (bits_changed & (1 << i))
++                      input_report_key(keypad->input_dev,
++                                      pdata->direct_key_map[i],
++                                      (new_state & (1 << i)));
++      }
++      input_sync(keypad->input_dev);
++      keypad->direct_key_state = new_state;
++}
++
++static irqreturn_t pxa27x_keypad_irq_handler(int irq, void *dev_id)
++{
++      struct pxa27x_keypad *keypad = dev_id;
++      unsigned long kpc = keypad_readl(KPC);
++
++      if (kpc & KPC_DI)
++              pxa27x_keypad_scan_direct(keypad);
++
++      if (kpc & KPC_MI)
++              pxa27x_keypad_scan_matrix(keypad);
++
++      return IRQ_HANDLED;
++}
++
++static void pxa27x_keypad_config(struct pxa27x_keypad *keypad)
++{
++      struct pxa27x_keypad_platform_data *pdata = keypad->pdata;
++      unsigned int mask = 0, direct_key_num = 0;
++      unsigned long kpc = 0;
++
++      /* enable matrix keys with automatic scan */
++      if (pdata->matrix_key_rows && pdata->matrix_key_cols) {
++              kpc |= KPC_ASACT | KPC_MIE | KPC_ME | KPC_MS_ALL;
++              kpc |= KPC_MKRN(pdata->matrix_key_rows) |
++                     KPC_MKCN(pdata->matrix_key_cols);
++      }
++
++      /* enable rotary key, debounce interval same as direct keys */
++      if (pdata->enable_rotary0) {
++              mask |= 0x03;
++              direct_key_num = 2;
++              kpc |= KPC_REE0;
++      }
++
++      if (pdata->enable_rotary1) {
++              mask |= 0x0c;
++              direct_key_num = 4;
++              kpc |= KPC_REE1;
++      }
++
++      if (pdata->direct_key_num > direct_key_num)
++              direct_key_num = pdata->direct_key_num;
++
++      keypad->direct_key_mask = ((2 << direct_key_num) - 1) & ~mask;
++
++      /* enable direct key */
++      if (direct_key_num)
++              kpc |= KPC_DE | KPC_DIE | KPC_DKN(direct_key_num);
++
++      keypad_writel(KPC, kpc | KPC_RE_ZERO_DEB);
++      keypad_writel(KPREC, DEFAULT_KPREC);
++      keypad_writel(KPKDI, pdata->debounce_interval);
++}
++
++static int pxa27x_keypad_open(struct input_dev *dev)
++{
++      struct pxa27x_keypad *keypad = input_get_drvdata(dev);
++
++      /* Enable unit clock */
++      clk_enable(keypad->clk);
++      pxa27x_keypad_config(keypad);
++
++      return 0;
++}
++
++static void pxa27x_keypad_close(struct input_dev *dev)
++{
++      struct pxa27x_keypad *keypad = input_get_drvdata(dev);
++
++      /* Disable clock unit */
++      clk_disable(keypad->clk);
++}
++
++#ifdef CONFIG_PM
++static int pxa27x_keypad_suspend(struct platform_device *pdev, pm_message_t state)
++{
++      struct pxa27x_keypad *keypad = platform_get_drvdata(pdev);
++
++      clk_disable(keypad->clk);
++      return 0;
++}
++
++static int pxa27x_keypad_resume(struct platform_device *pdev)
++{
++      struct pxa27x_keypad *keypad = platform_get_drvdata(pdev);
++      struct input_dev *input_dev = keypad->input_dev;
++
++      mutex_lock(&input_dev->mutex);
++
++      if (input_dev->users) {
++              /* Enable unit clock */
++              clk_enable(keypad->clk);
++              pxa27x_keypad_config(keypad);
++      }
++
++      mutex_unlock(&input_dev->mutex);
++
++      return 0;
++}
++#else
++#define pxa27x_keypad_suspend NULL
++#define pxa27x_keypad_resume  NULL
++#endif
++
++#define res_size(res) ((res)->end - (res)->start + 1)
++
++static int __devinit pxa27x_keypad_probe(struct platform_device *pdev)
++{
++      struct pxa27x_keypad *keypad;
++      struct input_dev *input_dev;
++      struct resource *res;
++      int irq, error;
++
++      keypad = kzalloc(sizeof(struct pxa27x_keypad), GFP_KERNEL);
++      if (keypad == NULL) {
++              dev_err(&pdev->dev, "failed to allocate driver data\n");
++              return -ENOMEM;
++      }
++
++      keypad->pdata = pdev->dev.platform_data;
++      if (keypad->pdata == NULL) {
++              dev_err(&pdev->dev, "no platform data defined\n");
++              error = -EINVAL;
++              goto failed_free;
++      }
++
++      irq = platform_get_irq(pdev, 0);
++      if (irq < 0) {
++              dev_err(&pdev->dev, "failed to get keypad irq\n");
++              error = -ENXIO;
++              goto failed_free;
++      }
++
++      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++      if (res == NULL) {
++              dev_err(&pdev->dev, "failed to get I/O memory\n");
++              error = -ENXIO;
++              goto failed_free;
++      }
++
++      res = request_mem_region(res->start, res_size(res), pdev->name);
++      if (res == NULL) {
++              dev_err(&pdev->dev, "failed to request I/O memory\n");
++              error = -EBUSY;
++              goto failed_free;
++      }
++
++      keypad->mmio_base = ioremap(res->start, res_size(res));
++      if (keypad->mmio_base == NULL) {
++              dev_err(&pdev->dev, "failed to remap I/O memory\n");
++              error = -ENXIO;
++              goto failed_free_mem;
++      }
++
++      keypad->clk = clk_get(&pdev->dev, "KBDCLK");
++      if (IS_ERR(keypad->clk)) {
++              dev_err(&pdev->dev, "failed to get keypad clock\n");
++              error = PTR_ERR(keypad->clk);
++              goto failed_free_io;
++      }
++
++      /* Create and register the input driver. */
++      input_dev = input_allocate_device();
++      if (!input_dev) {
++              dev_err(&pdev->dev, "failed to allocate input device\n");
++              error = -ENOMEM;
++              goto failed_put_clk;
++      }
++
++      input_dev->name = pdev->name;
++      input_dev->id.bustype = BUS_HOST;
++      input_dev->open = pxa27x_keypad_open;
++      input_dev->close = pxa27x_keypad_close;
++      input_dev->dev.parent = &pdev->dev;
++
++      keypad->input_dev = input_dev;
++      input_set_drvdata(input_dev, keypad);
++
++      input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) |
++              BIT_MASK(EV_REL);
++
++      pxa27x_keypad_build_keycode(keypad);
++      platform_set_drvdata(pdev, keypad);
++
++      error = request_irq(irq, pxa27x_keypad_irq_handler, IRQF_DISABLED,
++                          pdev->name, keypad);
++      if (error) {
++              dev_err(&pdev->dev, "failed to request IRQ\n");
++              goto failed_free_dev;
++      }
++
++      /* Register the input device */
++      error = input_register_device(input_dev);
++      if (error) {
++              dev_err(&pdev->dev, "failed to register input device\n");
++              goto failed_free_irq;
++      }
++
++      return 0;
++
++failed_free_irq:
++      free_irq(irq, pdev);
++      platform_set_drvdata(pdev, NULL);
++failed_free_dev:
++      input_free_device(input_dev);
++failed_put_clk:
++      clk_put(keypad->clk);
++failed_free_io:
++      iounmap(keypad->mmio_base);
++failed_free_mem:
++      release_mem_region(res->start, res_size(res));
++failed_free:
++      kfree(keypad);
++      return error;
++}
++
++static int __devexit pxa27x_keypad_remove(struct platform_device *pdev)
++{
++      struct pxa27x_keypad *keypad = platform_get_drvdata(pdev);
++      struct resource *res;
++
++      free_irq(platform_get_irq(pdev, 0), pdev);
++
++      clk_disable(keypad->clk);
++      clk_put(keypad->clk);
++
++      input_unregister_device(keypad->input_dev);
++      input_free_device(keypad->input_dev);
++
++      iounmap(keypad->mmio_base);
++
++      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++      release_mem_region(res->start, res_size(res));
++
++      platform_set_drvdata(pdev, NULL);
++      kfree(keypad);
++      return 0;
++}
++
++static struct platform_driver pxa27x_keypad_driver = {
++      .probe          = pxa27x_keypad_probe,
++      .remove         = __devexit_p(pxa27x_keypad_remove),
++      .suspend        = pxa27x_keypad_suspend,
++      .resume         = pxa27x_keypad_resume,
++      .driver         = {
++              .name   = "pxa27x-keypad",
++      },
++};
++
++static int __init pxa27x_keypad_init(void)
++{
++      return platform_driver_register(&pxa27x_keypad_driver);
++}
++
++static void __exit pxa27x_keypad_exit(void)
++{
++      platform_driver_unregister(&pxa27x_keypad_driver);
++}
++
++module_init(pxa27x_keypad_init);
++module_exit(pxa27x_keypad_exit);
++
++MODULE_DESCRIPTION("PXA27x Keypad Controller Driver");
++MODULE_LICENSE("GPL");
+Index: linux-2.6.23-z-input/include/asm-arm/arch-pxa/pxa27x_keyboard.h
+===================================================================
+--- linux-2.6.23-z-input.orig/include/asm-arm/arch-pxa/pxa27x_keyboard.h       2007-10-09 22:31:38.000000000 +0200
++++ /dev/null  1970-01-01 00:00:00.000000000 +0000
+@@ -1,13 +0,0 @@
+-#define PXAKBD_MAXROW         8
+-#define PXAKBD_MAXCOL         8
+-
+-struct pxa27x_keyboard_platform_data {
+-      int nr_rows, nr_cols;
+-      int keycodes[PXAKBD_MAXROW][PXAKBD_MAXCOL];
+-      int gpio_modes[PXAKBD_MAXROW + PXAKBD_MAXCOL];
+-
+-#ifdef CONFIG_PM
+-      u32 reg_kpc;
+-      u32 reg_kprec;
+-#endif
+-};
+Index: linux-2.6.23-z-input/include/asm-arm/arch-pxa/pxa27x_keypad.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.23-z-input/include/asm-arm/arch-pxa/pxa27x_keypad.h      2008-02-18 01:43:28.000000000 +0100
+@@ -0,0 +1,58 @@
++#ifndef __ASM_ARCH_PXA27x_KEYPAD_H
++#define __ASM_ARCH_PXA27x_KEYPAD_H
++
++#include <linux/input.h>
++
++#define MAX_MATRIX_KEY_ROWS   (8)
++#define MAX_MATRIX_KEY_COLS   (8)
++
++/* pxa3xx keypad platform specific parameters
++ *
++ * NOTE:
++ * 1. direct_key_num indicates the number of keys in the direct keypad
++ *    _plus_ the number of rotary-encoder sensor inputs,  this can be
++ *    left as 0 if only rotary encoders are enabled,  the driver will
++ *    automatically calculate this
++ *
++ * 2. direct_key_map is the key code map for the direct keys, if rotary
++ *    encoder(s) are enabled, direct key 0/1(2/3) will be ignored
++ *
++ * 3. rotary can be either interpreted as a relative input event (e.g.
++ *    REL_WHEEL/REL_HWHEEL) or specific keys (e.g. UP/DOWN/LEFT/RIGHT)
++ *
++ * 4. matrix key and direct key will use the same debounce_interval by
++ *    default, which should be sufficient in most cases
++ */
++struct pxa27x_keypad_platform_data {
++
++      /* code map for the matrix keys */
++      unsigned int    matrix_key_rows;
++      unsigned int    matrix_key_cols;
++      unsigned int    *matrix_key_map;
++      int             matrix_key_map_size;
++
++      /* direct keys */
++      int             direct_key_num;
++      unsigned int    direct_key_map[8];
++
++      /* rotary encoders 0 */
++      int             enable_rotary0;
++      int             rotary0_rel_code;
++      int             rotary0_up_key;
++      int             rotary0_down_key;
++
++      /* rotary encoders 1 */
++      int             enable_rotary1;
++      int             rotary1_rel_code;
++      int             rotary1_up_key;
++      int             rotary1_down_key;
++
++      /* key debounce interval */
++      unsigned int    debounce_interval;
++};
++
++#define KEY(row, col, val)    (((row) << 28) | ((col) << 24) | (val))
++
++extern void pxa_set_keypad_info(struct pxa27x_keypad_platform_data *info);
++
++#endif /* __ASM_ARCH_PXA27x_KEYPAD_H */
+Index: linux-2.6.23-z-input/drivers/input/keyboard/pxa27x_keyboard.c
+===================================================================
+--- linux-2.6.23-z-input.orig/drivers/input/keyboard/pxa27x_keyboard.c 2008-02-18 01:43:28.000000000 +0100
++++ /dev/null  1970-01-01 00:00:00.000000000 +0000
+@@ -1,273 +0,0 @@
+-/*
+- * linux/drivers/input/keyboard/pxa27x_keyboard.c
+- *
+- * Driver for the pxa27x matrix keyboard controller.
+- *
+- * Created:   Feb 22, 2007
+- * Author:    Rodolfo Giometti <giometti@linux.it>
+- *
+- * Based on a previous implementations by Kevin O'Connor
+- * <kevin_at_koconnor.net> and Alex Osborne <bobofdoom@gmail.com> and
+- * on some suggestions by Nicolas Pitre <nico@cam.org>.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- */
+-
+-
+-#include <linux/kernel.h>
+-#include <linux/module.h>
+-#include <linux/init.h>
+-#include <linux/interrupt.h>
+-#include <linux/input.h>
+-#include <linux/device.h>
+-#include <linux/platform_device.h>
+-#include <linux/clk.h>
+-#include <linux/err.h>
+-
+-#include <asm/mach-types.h>
+-#include <asm/mach/arch.h>
+-#include <asm/mach/map.h>
+-
+-#include <asm/arch/hardware.h>
+-#include <asm/arch/pxa-regs.h>
+-#include <asm/arch/irqs.h>
+-#include <asm/arch/pxa27x_keyboard.h>
+-
+-#define DRIVER_NAME           "pxa27x-keyboard"
+-
+-#define KPASMKP(col)          (col/2 == 0 ? KPASMKP0 : \
+-                               col/2 == 1 ? KPASMKP1 : \
+-                               col/2 == 2 ? KPASMKP2 : KPASMKP3)
+-#define KPASMKPx_MKC(row, col)        (1 << (row + 16 * (col % 2)))
+-
+-static struct clk *pxakbd_clk;
+-
+-static irqreturn_t pxakbd_irq_handler(int irq, void *dev_id)
+-{
+-      struct platform_device *pdev = dev_id;
+-      struct pxa27x_keyboard_platform_data *pdata = pdev->dev.platform_data;
+-      struct input_dev *input_dev = platform_get_drvdata(pdev);
+-      unsigned long kpc = KPC;
+-      int p, row, col, rel;
+-
+-      if (kpc & KPC_DI) {
+-              unsigned long kpdk = KPDK;
+-
+-              if (!(kpdk & KPDK_DKP)) {
+-                      /* better luck next time */
+-              } else if (kpc & KPC_REE0) {
+-                      unsigned long kprec = KPREC;
+-                      KPREC = 0x7f;
+-
+-                      if (kprec & KPREC_OF0)
+-                              rel = (kprec & 0xff) + 0x7f;
+-                      else if (kprec & KPREC_UF0)
+-                              rel = (kprec & 0xff) - 0x7f - 0xff;
+-                      else
+-                              rel = (kprec & 0xff) - 0x7f;
+-
+-                      if (rel) {
+-                              input_report_rel(input_dev, REL_WHEEL, rel);
+-                              input_sync(input_dev);
+-                      }
+-              }
+-      }
+-
+-      if (kpc & KPC_MI) {
+-              /* report the status of every button */
+-              for (row = 0; row < pdata->nr_rows; row++) {
+-                      for (col = 0; col < pdata->nr_cols; col++) {
+-                              p = KPASMKP(col) & KPASMKPx_MKC(row, col) ?
+-                                      1 : 0;
+-                              pr_debug("keycode %x - pressed %x\n",
+-                                              pdata->keycodes[row][col], p);
+-                              input_report_key(input_dev,
+-                                              pdata->keycodes[row][col], p);
+-                      }
+-              }
+-              input_sync(input_dev);
+-      }
+-
+-      return IRQ_HANDLED;
+-}
+-
+-static int pxakbd_open(struct input_dev *dev)
+-{
+-      /* Set keypad control register */
+-      KPC |= (KPC_ASACT |
+-              KPC_MS_ALL |
+-              (2 << 6) | KPC_REE0 | KPC_DK_DEB_SEL |
+-              KPC_ME | KPC_MIE | KPC_DE | KPC_DIE);
+-
+-      KPC &= ~KPC_AS;         /* disable automatic scan */
+-      KPC &= ~KPC_IMKP;       /* do not ignore multiple keypresses */
+-
+-      /* Set rotary count to mid-point value */
+-      KPREC = 0x7F;
+-
+-      /* Enable unit clock */
+-      clk_enable(pxakbd_clk);
+-
+-      return 0;
+-}
+-
+-static void pxakbd_close(struct input_dev *dev)
+-{
+-      /* Disable clock unit */
+-      clk_disable(pxakbd_clk);
+-}
+-
+-#ifdef CONFIG_PM
+-static int pxakbd_suspend(struct platform_device *pdev, pm_message_t state)
+-{
+-      struct pxa27x_keyboard_platform_data *pdata = pdev->dev.platform_data;
+-
+-      /* Save controller status */
+-      pdata->reg_kpc = KPC;
+-      pdata->reg_kprec = KPREC;
+-
+-      return 0;
+-}
+-
+-static int pxakbd_resume(struct platform_device *pdev)
+-{
+-      struct pxa27x_keyboard_platform_data *pdata = pdev->dev.platform_data;
+-      struct input_dev *input_dev = platform_get_drvdata(pdev);
+-
+-      mutex_lock(&input_dev->mutex);
+-
+-      if (input_dev->users) {
+-              /* Restore controller status */
+-              KPC = pdata->reg_kpc;
+-              KPREC = pdata->reg_kprec;
+-
+-              /* Enable unit clock */
+-              clk_disable(pxakbd_clk);
+-              clk_enable(pxakbd_clk);
+-      }
+-
+-      mutex_unlock(&input_dev->mutex);
+-
+-      return 0;
+-}
+-#else
+-#define pxakbd_suspend        NULL
+-#define pxakbd_resume NULL
+-#endif
+-
+-static int __devinit pxakbd_probe(struct platform_device *pdev)
+-{
+-      struct pxa27x_keyboard_platform_data *pdata = pdev->dev.platform_data;
+-      struct input_dev *input_dev;
+-      int i, row, col, error;
+-
+-      pxakbd_clk = clk_get(&pdev->dev, "KBDCLK");
+-      if (IS_ERR(pxakbd_clk)) {
+-              error = PTR_ERR(pxakbd_clk);
+-              goto err_clk;
+-      }
+-
+-      /* Create and register the input driver. */
+-      input_dev = input_allocate_device();
+-      if (!input_dev) {
+-              printk(KERN_ERR "Cannot request keypad device\n");
+-              error = -ENOMEM;
+-              goto err_alloc;
+-      }
+-
+-      input_dev->name = DRIVER_NAME;
+-      input_dev->id.bustype = BUS_HOST;
+-      input_dev->open = pxakbd_open;
+-      input_dev->close = pxakbd_close;
+-      input_dev->dev.parent = &pdev->dev;
+-
+-      input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_REL);
+-      input_dev->relbit[LONG(REL_WHEEL)] = BIT(REL_WHEEL);
+-      for (row = 0; row < pdata->nr_rows; row++) {
+-              for (col = 0; col < pdata->nr_cols; col++) {
+-                      int code = pdata->keycodes[row][col];
+-                      if (code > 0)
+-                              set_bit(code, input_dev->keybit);
+-              }
+-      }
+-
+-      error = request_irq(IRQ_KEYPAD, pxakbd_irq_handler, IRQF_DISABLED,
+-                          DRIVER_NAME, pdev);
+-      if (error) {
+-              printk(KERN_ERR "Cannot request keypad IRQ\n");
+-              goto err_free_dev;
+-      }
+-
+-      platform_set_drvdata(pdev, input_dev);
+-
+-      /* Register the input device */
+-      error = input_register_device(input_dev);
+-      if (error)
+-              goto err_free_irq;
+-
+-      /* Setup GPIOs. */
+-      for (i = 0; i < pdata->nr_rows + pdata->nr_cols; i++)
+-              pxa_gpio_mode(pdata->gpio_modes[i]);
+-
+-      /*
+-       * Store rows/cols info into keyboard registers.
+-       */
+-
+-      KPC |= (pdata->nr_rows - 1) << 26;
+-      KPC |= (pdata->nr_cols - 1) << 23;
+-
+-      for (col = 0; col < pdata->nr_cols; col++)
+-              KPC |= KPC_MS0 << col;
+-
+-      return 0;
+-
+- err_free_irq:
+-      platform_set_drvdata(pdev, NULL);
+-      free_irq(IRQ_KEYPAD, pdev);
+- err_free_dev:
+-      input_free_device(input_dev);
+- err_alloc:
+-      clk_put(pxakbd_clk);
+- err_clk:
+-      return error;
+-}
+-
+-static int __devexit pxakbd_remove(struct platform_device *pdev)
+-{
+-      struct input_dev *input_dev = platform_get_drvdata(pdev);
+-
+-      input_unregister_device(input_dev);
+-      free_irq(IRQ_KEYPAD, pdev);
+-      clk_put(pxakbd_clk);
+-      platform_set_drvdata(pdev, NULL);
+-
+-      return 0;
+-}
+-
+-static struct platform_driver pxakbd_driver = {
+-      .probe          = pxakbd_probe,
+-      .remove         = __devexit_p(pxakbd_remove),
+-      .suspend        = pxakbd_suspend,
+-      .resume         = pxakbd_resume,
+-      .driver         = {
+-              .name   = DRIVER_NAME,
+-      },
+-};
+-
+-static int __init pxakbd_init(void)
+-{
+-      return platform_driver_register(&pxakbd_driver);
+-}
+-
+-static void __exit pxakbd_exit(void)
+-{
+-      platform_driver_unregister(&pxakbd_driver);
+-}
+-
+-module_init(pxakbd_init);
+-module_exit(pxakbd_exit);
+-
+-MODULE_DESCRIPTION("PXA27x Matrix Keyboard Driver");
+-MODULE_LICENSE("GPL");
+Index: linux-2.6.23-z-input/arch/arm/mach-pxa/zylonite.c
+===================================================================
+--- linux-2.6.23-z-input.orig/arch/arm/mach-pxa/zylonite.c     2008-02-18 01:43:28.000000000 +0100
++++ linux-2.6.23-z-input/arch/arm/mach-pxa/zylonite.c  2008-02-19 01:31:33.000000000 +0100
+@@ -25,6 +25,7 @@
+ #include <asm/arch/gpio.h>
+ #include <asm/arch/pxafb.h>
+ #include <asm/arch/zylonite.h>
++#include <asm/arch/pxa27x_keypad.h>
+ #include "generic.h"
+@@ -173,6 +174,72 @@
+ static inline void zylonite_init_lcd(void) {}
+ #endif
++#if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULES)
++static unsigned int zylonite_matrix_key_map[] = {
++       /* KEY(row, col, key_code) */
++       KEY(0, 0, KEY_A), KEY(0, 1, KEY_B), KEY(0, 2, KEY_C), KEY(0, 5, KEY_D),
++       KEY(1, 0, KEY_E), KEY(1, 1, KEY_F), KEY(1, 2, KEY_G), KEY(1, 5, KEY_H),
++       KEY(2, 0, KEY_I), KEY(2, 1, KEY_J), KEY(2, 2, KEY_K), KEY(2, 5, KEY_L),
++       KEY(3, 0, KEY_M), KEY(3, 1, KEY_N), KEY(3, 2, KEY_O), KEY(3, 5, KEY_P),
++       KEY(5, 0, KEY_Q), KEY(5, 1, KEY_R), KEY(5, 2, KEY_S), KEY(5, 5, KEY_T),
++       KEY(6, 0, KEY_U), KEY(6, 1, KEY_V), KEY(6, 2, KEY_W), KEY(6, 5, KEY_X),
++       KEY(7, 1, KEY_Y), KEY(7, 2, KEY_Z),
++
++       KEY(4, 4, KEY_0), KEY(1, 3, KEY_1), KEY(4, 1, KEY_2), KEY(1, 4, KEY_3),
++       KEY(2, 3, KEY_4), KEY(4, 2, KEY_5), KEY(2, 4, KEY_6), KEY(3, 3, KEY_7),
++       KEY(4, 3, KEY_8), KEY(3, 4, KEY_9),
++
++       KEY(4, 5, KEY_SPACE),
++       KEY(5, 3, KEY_KPASTERISK),      /* * */
++       KEY(5, 4, KEY_KPDOT),           /* #" */
++
++       KEY(0, 7, KEY_UP),
++       KEY(1, 7, KEY_DOWN),
++       KEY(2, 7, KEY_LEFT),
++       KEY(3, 7, KEY_RIGHT),
++       KEY(2, 6, KEY_HOME),
++       KEY(3, 6, KEY_END),
++       KEY(6, 4, KEY_DELETE),
++       KEY(6, 6, KEY_BACK),
++       KEY(6, 3, KEY_CAPSLOCK),        /* KEY_LEFTSHIFT), */
++
++       KEY(4, 6, KEY_ENTER),           /* scroll push */
++       KEY(5, 7, KEY_ENTER),           /* keypad action */
++
++       KEY(0, 4, KEY_EMAIL),
++       KEY(5, 6, KEY_SEND),
++       KEY(4, 0, KEY_CALENDAR),
++       KEY(7, 6, KEY_RECORD),
++       KEY(6, 7, KEY_VOLUMEUP),
++       KEY(7, 7, KEY_VOLUMEDOWN),
++
++       KEY(0, 6, KEY_F22),     /* soft1 */
++       KEY(1, 6, KEY_F23),     /* soft2 */
++       KEY(0, 3, KEY_AUX),     /* contact */
++};
++
++static struct pxa27x_keypad_platform_data zylonite_keypad_info = {
++       .matrix_key_rows        = 8,
++       .matrix_key_cols        = 8,
++       .matrix_key_map         = zylonite_matrix_key_map,
++       .matrix_key_map_size    = ARRAY_SIZE(zylonite_matrix_key_map),
++
++       .enable_rotary0         = 1,
++       .rotary0_up_key         = KEY_UP,
++       .rotary0_down_key       = KEY_DOWN,
++
++       .debounce_interval      = 30,
++};
++
++static void __init zylonite_init_keypad(void)
++{
++       pxa_set_keypad_info(&zylonite_keypad_info);
++}
++#else
++static inline void zylonite_init_keypad(void) {}
++#endif
++
++
+ static void __init zylonite_init(void)
+ {
+       /* board-processor specific initialization */
+@@ -190,6 +257,7 @@
+       platform_device_register(&touch_device);
+       zylonite_init_lcd();
++      zylonite_init_keypad();
+ }
+ MACHINE_START(ZYLONITE, "PXA3xx Platform Development Kit (aka Zylonite)")
+Index: linux-2.6.23-z-input/arch/arm/mach-pxa/devices.h
+===================================================================
+--- linux-2.6.23-z-input.orig/arch/arm/mach-pxa/devices.h      2008-02-18 01:43:28.000000000 +0100
++++ linux-2.6.23-z-input/arch/arm/mach-pxa/devices.h   2008-02-18 01:43:28.000000000 +0100
+@@ -12,3 +12,4 @@
+ extern struct platform_device pxa27x_device_i2c_power;
+ extern struct platform_device pxa27x_device_ohci;
++extern struct platform_device pxa27x_device_keypad;
+Index: linux-2.6.23-z-input/arch/arm/mach-pxa/generic.c
+===================================================================
+--- linux-2.6.23-z-input.orig/arch/arm/mach-pxa/generic.c      2008-02-18 01:43:28.000000000 +0100
++++ linux-2.6.23-z-input/arch/arm/mach-pxa/generic.c   2008-02-18 01:43:28.000000000 +0100
+@@ -450,3 +450,34 @@
+       .name           = "sa1100-rtc",
+       .id             = -1,
+ };
++
++static struct resource pxa27x_resource_keypad[] = {
++       [0] = {
++               .start  = 0x41500000,
++               .end    = 0x4150004c,
++               .flags  = IORESOURCE_MEM,
++       },
++       [1] = {
++               .start  = IRQ_KEYPAD,
++               .end    = IRQ_KEYPAD,
++               .flags  = IORESOURCE_IRQ,
++       },
++};
++
++struct platform_device pxa27x_device_keypad = {
++       .name           = "pxa27x-keypad",
++       .id             = -1,
++       .resource       = pxa27x_resource_keypad,
++       .num_resources  = ARRAY_SIZE(pxa27x_resource_keypad),
++};
++
++void __init pxa_set_keypad_info(struct pxa27x_keypad_platform_data *info)
++{
++      int ret;
++
++      pxa27x_device_keypad.dev.platform_data = info;
++
++      ret = platform_device_register(&pxa27x_device_keypad);
++      if (ret)
++              dev_err(&pxa27x_device_keypad.dev, "unable to register device: %d\n", ret);
++}
+Index: linux-2.6.23-z-input/arch/arm/mach-pxa/pxa27x.c
+===================================================================
+--- linux-2.6.23-z-input.orig/arch/arm/mach-pxa/pxa27x.c       2008-02-18 01:43:28.000000000 +0100
++++ linux-2.6.23-z-input/arch/arm/mach-pxa/pxa27x.c    2008-02-18 01:43:28.000000000 +0100
+@@ -148,7 +148,7 @@
+       INIT_CKEN("USBCLK", USB,    48000000, 0, &pxa27x_device_ohci.dev),
+       INIT_CKEN("I2CCLK", PWRI2C, 13000000, 0, &pxa27x_device_i2c_power.dev),
+-      INIT_CKEN("KBDCLK", KEYPAD, 32768, 0, NULL),
++      INIT_CKEN("KBDCLK", KEYPAD, 32768, 0, &pxa27x_device_keypad.dev),
+       /*
+       INIT_CKEN("PWMCLK",  PWM0, 13000000, 0, NULL),
+Index: linux-2.6.23-z-input/arch/arm/mach-pxa/pxa3xx.c
+===================================================================
+--- linux-2.6.23-z-input.orig/arch/arm/mach-pxa/pxa3xx.c       2008-02-18 01:43:28.000000000 +0100
++++ linux-2.6.23-z-input/arch/arm/mach-pxa/pxa3xx.c    2008-02-19 01:32:40.000000000 +0100
+@@ -159,6 +159,7 @@
+ static struct clk pxa3xx_clks[] = {
+       INIT_CK("LCDCLK", LCD,    &clk_pxa3xx_hsio_ops, &pxa_device_fb.dev),
+       INIT_CK("CAMCLK", CAMERA, &clk_pxa3xx_hsio_ops, NULL),
++      INIT_CK("KBDCLK", KEYPAD, &clk_pxa3xx_hsio_ops, &pxa27x_device_keypad.dev),
+       INIT_CKEN("UARTCLK", FFUART, 14857000, 1, &pxa_device_ffuart.dev),
+       INIT_CKEN("UARTCLK", BTUART, 14857000, 1, &pxa_device_btuart.dev),
+Index: linux-2.6.23-z-input/include/asm-arm/arch-pxa/irqs.h
+===================================================================
+--- linux-2.6.23-z-input.orig/include/asm-arm/arch-pxa/irqs.h  2008-02-18 01:43:28.000000000 +0100
++++ linux-2.6.23-z-input/include/asm-arm/arch-pxa/irqs.h       2008-02-18 01:43:28.000000000 +0100
+@@ -13,7 +13,7 @@
+ #define PXA_IRQ(x)    (x)
+-#ifdef CONFIG_PXA27x
++#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
+ #define IRQ_SSP3      PXA_IRQ(0)      /* SSP3 service request */
+ #define IRQ_MSL               PXA_IRQ(1)      /* MSL Interface interrupt */
+ #define IRQ_USBH2     PXA_IRQ(2)      /* USB Host interrupt 1 (OHCI) */
+Index: linux-2.6.23-z-input/arch/arm/mach-pxa/pxa300.c
+===================================================================
+--- linux-2.6.23-z-input.orig/arch/arm/mach-pxa/pxa300.c       2008-02-19 01:33:58.000000000 +0100
++++ linux-2.6.23-z-input/arch/arm/mach-pxa/pxa300.c    2008-02-19 01:34:35.000000000 +0100
+@@ -23,8 +23,10 @@
+       MFP_ADDR_X(GPIO0,   GPIO2,   0x00b4),
+       MFP_ADDR_X(GPIO3,   GPIO26,  0x027c),
+-      MFP_ADDR_X(GPIO27,  GPIO127, 0x0400),
+-      MFP_ADDR_X(GPIO0_2, GPIO6_2, 0x02ec),
++      MFP_ADDR_X(GPIO27,  GPIO98,  0x0400),
++      MFP_ADDR_X(GPIO99,  GPIO127, 0x0600),
++      MFP_ADDR_X(GPIO0_2, GPIO1_2, 0x0674),
++      MFP_ADDR_X(GPIO2_2, GPIO6_2, 0x02dc),
+       MFP_ADDR(nBE0, 0x0204),
+       MFP_ADDR(nBE1, 0x0208),
diff --git a/packages/kexecboot/linux-kexecboot-2.6.23/zylonite_mtd-r0.patch b/packages/kexecboot/linux-kexecboot-2.6.23/zylonite_mtd-r0.patch
new file mode 100644 (file)
index 0000000..cb5a9c5
--- /dev/null
@@ -0,0 +1,4093 @@
+Gross hacks to make the Zylonite boot from flash in VGA.
+
+Flash driver forward ported to 2.6.14
+
+Index: linux-2.6.23/drivers/mtd/nand/Kconfig
+===================================================================
+--- linux-2.6.23.orig/drivers/mtd/nand/Kconfig 2007-10-09 21:31:38.000000000 +0100
++++ linux-2.6.23/drivers/mtd/nand/Kconfig      2008-02-13 00:59:45.000000000 +0000
+@@ -223,6 +223,10 @@
+       tristate "Support for NAND Flash on Sharp SL Series (C7xx + others)"
+       depends on ARCH_PXA
++config MTD_NAND_ZYLONITE
++      tristate "Support for NAND Flash on Zylonite"
++      depends on ARCH_PXA
++
+ config MTD_NAND_BASLER_EXCITE
+       tristate  "Support for NAND Flash on Basler eXcite"
+       depends on BASLER_EXCITE
+Index: linux-2.6.23/drivers/mtd/nand/Makefile
+===================================================================
+--- linux-2.6.23.orig/drivers/mtd/nand/Makefile        2007-10-09 21:31:38.000000000 +0100
++++ linux-2.6.23/drivers/mtd/nand/Makefile     2008-02-13 00:59:45.000000000 +0000
+@@ -19,6 +19,7 @@
+ obj-$(CONFIG_MTD_NAND_H1900)          += h1910.o
+ obj-$(CONFIG_MTD_NAND_RTC_FROM4)      += rtc_from4.o
+ obj-$(CONFIG_MTD_NAND_SHARPSL)                += sharpsl.o
++obj-$(CONFIG_MTD_NAND_ZYLONITE)               += mhn_nand.o
+ obj-$(CONFIG_MTD_NAND_TS7250)         += ts7250.o
+ obj-$(CONFIG_MTD_NAND_NANDSIM)                += nandsim.o
+ obj-$(CONFIG_MTD_NAND_CS553X)         += cs553x_nand.o
+Index: linux-2.6.23/drivers/mtd/nand/mhn_nand.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.23/drivers/mtd/nand/mhn_nand.c   2008-02-13 00:59:45.000000000 +0000
+@@ -0,0 +1,3869 @@
++/*
++ *  drivers/mtd/nand/mhn_nand.c
++ *
++ *  Copyright (C) 2005 Intel Coporation (chao.xie@intel.com)
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ *  Overview:
++ *   This is a device driver for the NAND flash device on zylonite board
++ *   which utilizes the Samsung K9K1216Q0C parts. This is a 64Mibit NAND
++ *   flash device.
++
++ *(C) Copyright 2006 Marvell International Ltd.
++ * All Rights Reserved
++ */
++
++#include <linux/slab.h>
++#include <linux/module.h>
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/nand.h>
++#include <linux/mtd/partitions.h>
++#include <linux/interrupt.h>
++#include <linux/device.h>
++#include <linux/platform_device.h>
++#include <linux/delay.h>
++#include <linux/dma-mapping.h>
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/delay.h>
++#include <asm/dma.h>
++#include <asm/arch/mfp.h>
++//#include <asm/arch/cpu-freq-voltage-mhn.h>
++
++//#define NDCR 0xf0000000
++//#define NDCR        (*((volatile u32 *)0xf0000000))
++//#define NDCR              __REG_2(0x43100000)  /* Data Flash Control register */
++#define NDCR_SPARE_EN             (0x1<<31)
++#define NDCR_ECC_EN               (0x1<<30)
++#define NDCR_DMA_EN               (0x1<<29)
++#define NDCR_ND_RUN               (0x1<<28)
++#define NDCR_DWIDTH_C             (0x1<<27)
++#define NDCR_DWIDTH_M             (0x1<<26)
++#define NDCR_PAGE_SZ              (0x1<<24)
++#define NDCR_NCSX         (0x1<<23)
++#define NDCR_ND_MODE              (0x3<<21)
++#define NDCR_NAND_MODE    0x0
++#define NDCR_CLR_PG_CNT           (0x1<<20)
++#define NDCR_CLR_ECC      (       0x1<<19)
++#define NDCR_RD_ID_CNT_MASK       (0x7<<16)
++#define NDCR_RD_ID_CNT(x)       (((x) << 16) & NDCR_RD_ID_CNT_MASK)
++#define NDCR_RA_START     (0x1<<15)
++#define NDCR_PG_PER_BLK   (0x1<<14)
++#define NDCR_ND_ARB_EN    (0x1<<12)
++
++//#define NDSR        (*((volatile u32 *)0xf0000014))
++//#define NDSR              __REG_2(0x43100014)  /* Data Controller Status Register */
++#define NDSR_RDY  (0x1<<11)
++#define NDSR_CS0_PAGED    (0x1<<10)
++#define NDSR_CS1_PAGED    (0x1<<9)
++#define NDSR_CS0_CMDD     (0x1<<8)
++#define NDSR_CS1_CMDD     (0x1<<7)
++#define NDSR_CS0_BBD      (0x1<<6)
++#define NDSR_CS1_BBD      (0x1<<5)
++#define NDSR_DBERR        (0x1<<4)
++#define NDSR_SBERR        (0x1<<3)
++#define NDSR_WRDREQ       (0x1<<2)
++#define NDSR_RDDREQ       (0x1<<1)
++#define NDSR_WRCMDREQ     (0x1)
++
++#define OSCR              __REG(0x40A00010)  /* OS Timer Counter Register */
++//#define NDCB0             __REG_2(0x43100048)  /* Data Controller Command Buffer0 */
++//#define NDCB1             __REG_2(0x4310004C)  /* Data Controller Command Buffer1 */
++//#define NDCB2             __REG_2(0x43100050)  /* Data Controller Command Buffer2 */
++#define NDCB0_AUTO_RS             (0x1<<25)
++#define NDCB0_CSEL                (0x1<<24)
++#define NDCB0_CMD_TYPE_MASK       (0x7<<21)
++#define   NDCB0_CMD_TYPE(x)       (((x) << 21) & NDCB0_CMD_TYPE_MASK)
++#define NDCB0_NC          (0x1<<20)
++#define NDCB0_DBC         (0x1<<19)
++#define NDCB0_ADDR_CYC_MASK       (0x7<<16)
++#define   NDCB0_ADDR_CYC(x)       (((x) << 16) & NDCB0_ADDR_CYC_MASK)
++#define NDCB0_CMD2_MASK           (0xff<<8)
++#define NDCB0_CMD1_MASK           (0xff)
++#define NDCB0_ADDR_CYC_SHIFT      (16)
++#define DCMD0             __REG(0x4000020c)  /* DMA Command Address Register Channel 0 */
++#define DCMD1             __REG(0x4000021c)  /* DMA Command Address Register Channel 1 */
++#define DCMD2             __REG(0x4000022c)  /* DMA Command Address Register Channel 2 */
++#define DCMD3             __REG(0x4000023c)  /* DMA Command Address Register Channel 3 */
++#define DCMD4             __REG(0x4000024c)  /* DMA Command Address Register Channel 4 */
++#define DCMD5             __REG(0x4000025c)  /* DMA Command Address Register Channel 5 */
++#define DCMD6             __REG(0x4000026c)  /* DMA Command Address Register Channel 6 */
++#define DCMD7             __REG(0x4000027c)  /* DMA Command Address Register Channel 7 */
++#define DCMD8             __REG(0x4000028c)  /* DMA Command Address Register Channel 8 */
++#define DCMD9             __REG(0x4000029c)  /* DMA Command Address Register Channel 9 */
++#define DCMD10            __REG(0x400002ac)  /* DMA Command Address Register Channel 10 */
++#define DCMD11            __REG(0x400002bc)  /* DMA Command Address Register Channel 11 */
++#define DCMD12            __REG(0x400002cc)  /* DMA Command Address Register Channel 12 */
++#define DCMD13            __REG(0x400002dc)  /* DMA Command Address Register Channel 13 */
++#define DCMD14            __REG(0x400002ec)  /* DMA Command Address Register Channel 14 */
++#define DCMD15            __REG(0x400002fc)  /* DMA Command Address Register Channel 15 */
++#define DCMD(x)           __REG2(0x4000020c, (x) << 4)
++#define DCMD_INCSRCADDR   (1 << 31)       /* Source Address Increment Setting. */
++#define DCMD_INCTRGADDR   (1 << 30)       /* Target Address Increment Setting. */
++#define DCMD_FLOWSRC      (1 << 29)       /* Flow Control by the source. */
++#define DCMD_FLOWTRG      (1 << 28)       /* Flow Control by the target. */
++#define DCMD_STARTIRQEN   (1 << 22)       /* Start Interrupt Enable */
++#define DCMD_ENDIRQEN     (1 << 21)       /* End Interrupt Enable */
++#define DCMD_ENDIAN       (1 << 18)       /* Device Endian-ness. */
++#define DCMD_BURST8       (1 << 16)       /* 8 byte burst */
++#define DCMD_BURST16      (2 << 16)       /* 16 byte burst */
++#define DCMD_BURST32      (3 << 16)       /* 32 byte burst */
++#define DCMD_WIDTH1       (1 << 14)       /* 1 byte width */
++#define DCMD_WIDTH2       (2 << 14)       /* 2 byte width (HalfWord) */
++#define DCMD_WIDTH4       (3 << 14)       /* 4 byte width (Word) */
++#define DCMD_LENGTH       0x01fff         /* length mask (max = 8K - 1) */
++#define DCMD_RXPCDR       (DCMD_INCTRGADDR|DCMD_FLOWSRC|DCMD_BURST32|DCMD_WIDTH4)
++#define DCMD_RXMCDR       (DCMD_INCTRGADDR|DCMD_FLOWSRC|DCMD_BURST32|DCMD_WIDTH4)
++#define DCMD_TXPCDR       (DCMD_INCSRCADDR|DCMD_FLOWTRG|DCMD_BURST32|DCMD_WIDTH4)
++#define DRCMR(n)  __REG2(0x40000100, (n)<<2)
++#define DRCMR97           __REG(0x40001184)  /* Request to Channel Map Register for NAND interface data transmit & receive Request */
++#define DRCMR98           __REG(0x40001188)  /* Reserved */
++#define DRCMR99           __REG(0x4000118C)  /* Request to Channel Map Register for NAND interface command transmit Request */
++#define DRCMRRXSADR       DRCMR2
++#define DRCMRTXSADR       DRCMR3
++#define DRCMRRXBTRBR      DRCMR4
++#define DRCMRTXBTTHR      DRCMR5
++#define DRCMRRXFFRBR      DRCMR6
++#define DRCMRTXFFTHR      DRCMR7
++#define DRCMRRXMCDR       DRCMR8
++#define DRCMRRXMODR       DRCMR9
++#define DRCMRTXMODR       DRCMR10
++#define DRCMRRXPCDR       DRCMR11
++#define DRCMRTXPCDR       DRCMR12
++#define DRCMRRXSSDR       DRCMR13
++#define DRCMRTXSSDR       DRCMR14
++#define DRCMRRXICDR       DRCMR17
++#define DRCMRTXICDR       DRCMR18
++#define DRCMRRXSTRBR      DRCMR19
++#define DRCMRTXSTTHR      DRCMR20
++#define DRCMRRXMMC        DRCMR21
++#define DRCMRTXMMC        DRCMR22
++#define DRCMRRXMMC2       DRCMR93
++#define DRCMRTXMMC2       DRCMR94
++#define DRCMRRXMMC3       DRCMR100
++#define DRCMRTXMMC3       DRCMR101
++#define DRCMRUDC(x)       DRCMR((x) + 24)
++#define DRCMR_MAPVLD      (1 << 7)        /* Map Valid (read / write) */
++#define DRCMR_CHLNUM      0x1f            /* mask for Channel Number (read / write) */
++#define DCSR0             __REG(0x40000000)  /* DMA Control / Status Register for Channel 0 */
++#define DCSR1             __REG(0x40000004)  /* DMA Control / Status Register for Channel 1 */
++#define DCSR2             __REG(0x40000008)  /* DMA Control / Status Register for Channel 2 */
++#define DCSR3             __REG(0x4000000c)  /* DMA Control / Status Register for Channel 3 */
++#define DCSR4             __REG(0x40000010)  /* DMA Control / Status Register for Channel 4 */
++#define DCSR5             __REG(0x40000014)  /* DMA Control / Status Register for Channel 5 */
++#define DCSR6             __REG(0x40000018)  /* DMA Control / Status Register for Channel 6 */
++#define DCSR7             __REG(0x4000001c)  /* DMA Control / Status Register for Channel 7 */
++#define DCSR8             __REG(0x40000020)  /* DMA Control / Status Register for Channel 8 */
++#define DCSR9             __REG(0x40000024)  /* DMA Control / Status Register for Channel 9 */
++#define DCSR10            __REG(0x40000028)  /* DMA Control / Status Register for Channel 10 */
++#define DCSR11            __REG(0x4000002c)  /* DMA Control / Status Register for Channel 11 */
++#define DCSR12            __REG(0x40000030)  /* DMA Control / Status Register for Channel 12 */
++#define DCSR13            __REG(0x40000034)  /* DMA Control / Status Register for Channel 13 */
++#define DCSR14            __REG(0x40000038)  /* DMA Control / Status Register for Channel 14 */
++#define DCSR15            __REG(0x4000003c)  /* DMA Control / Status Register for Channel 15 */
++#define DCSR16            __REG(0x40000040)  /* DMA Control / Status Register for Channel 16 */
++#define DCSR17            __REG(0x40000044)  /* DMA Control / Status Register for Channel 17 */
++#define DCSR18            __REG(0x40000048)  /* DMA Control / Status Register for Channel 18 */
++#define DCSR19            __REG(0x4000004c)  /* DMA Control / Status Register for Channel 19 */
++#define DCSR20            __REG(0x40000050)  /* DMA Control / Status Register for Channel 20 */
++#define DCSR21            __REG(0x40000054)  /* DMA Control / Status Register for Channel 21 */
++#define DCSR22            __REG(0x40000058)  /* DMA Control / Status Register for Channel 22 */
++#define DCSR23            __REG(0x4000005c)  /* DMA Control / Status Register for Channel 23 */
++#define DCSR24            __REG(0x40000060)  /* DMA Control / Status Register for Channel 24 */
++#define DCSR25            __REG(0x40000064)  /* DMA Control / Status Register for Channel 25 */
++#define DCSR26            __REG(0x40000068)  /* DMA Control / Status Register for Channel 26 */
++#define DCSR27            __REG(0x4000006c)  /* DMA Control / Status Register for Channel 27 */
++#define DCSR28            __REG(0x40000070)  /* DMA Control / Status Register for Channel 28 */
++#define DCSR29            __REG(0x40000074)  /* DMA Control / Status Register for Channel 29 */
++#define DCSR30            __REG(0x40000078)  /* DMA Control / Status Register for Channel 30 */
++#define DCSR31            __REG(0x4000007c)  /* DMA Control / Status Register for Channel 31 */
++#define DCSR(x)           __REG2(0x40000000, (x) << 2)
++#define DCSR_RUN  (1 << 31)       /* Run Bit (read / write) */
++#define DCSR_NODESC       (1 << 30)       /* No-Descriptor Fetch (read / write) */
++#define DCSR_STOPIRQEN    (1 << 29)       /* Stop Interrupt Enable (read / write) */
++#define DCSR_EORIRQEN     (1 << 28)       /* End of Receive Interrupt Enable (R/W) */
++#define DCSR_EORJMPEN     (1 << 27)       /* Jump to next descriptor on EOR */
++#define DCSR_EORSTOPEN    (1 << 26)       /* STOP on an EOR */
++#define DCSR_SETCMPST     (1 << 25)       /* Set Descriptor Compare Status */
++#define DCSR_CLRCMPST     (1 << 24)       /* Clear Descriptor Compare Status */
++#define DCSR_CMPST        (1 << 10)       /* The Descriptor Compare Status */
++#define DCSR_EORINTR      (1 << 9)        /* The end of Receive */
++#define DCSR_REQPEND      (1 << 8)        /* Request Pending (read-only) */
++#define DCSR_RASINTR      (1 << 4)        /* Request After Channel Stopped */
++#define DCSR_STOPSTATE    (1 << 3)        /* Stop State (read-only) */
++#define DCSR_ENDINTR      (1 << 2)        /* End Interrupt (read / write) */
++#define DCSR_STARTINTR    (1 << 1)        /* Start Interrupt (read / write) */
++#define DCSR_BUSERR       (1 << 0)        /* Bus Error Interrupt (read / write) */
++#define DDADR(x)  __REG2(0x40000200, (x) << 4)
++//#define __REG_2(x)        (*((volatile u32 *)io_p2v_2(x)))
++#define IRQ_NAND      PXA_IRQ(45)
++#define   CKEN_NAND       4       ///< NAND Flash Controller Clock Enable
++
++/* #define CONFIG_MTD_NAND_MONAHANS_DEBUG */
++#ifdef CONFIG_MTD_NAND_MONAHANS_DEBUG
++#define D1(x) do { \
++              printk(KERN_DEBUG "%s: ", __FUNCTION__); \
++              x; \
++      }while(0)
++
++#define       DPRINTK(fmt,args...) printk(KERN_DEBUG fmt, ##args )
++#define PRINT_BUF(buf, num)   print_buf(buf, num)
++#else
++#define D1(x)
++#define DPRINTK(fmt,args...)
++#define PRINT_BUF(buf, num)
++#endif
++
++/* DFC timing 0 register */
++#define DFC_TIMING_tRP                0
++#define DFC_TIMING_tRH                3
++#define DFC_TIMING_tWP                8
++#define DFC_TIMING_tWH                11
++#define DFC_TIMING_tCS                16
++#define DFC_TIMING_tCH                19
++
++/* DFC timing 1 register */
++#define DFC_TIMING_tAR                0
++#define DFC_TIMING_tWHR               4
++#define DFC_TIMING_tR         16
++
++/* max value for each timing setting in DFC */
++#define DFC_TIMING_MAX_tCH    7
++#define DFC_TIMING_MAX_tCS    7
++#define DFC_TIMING_MAX_tWH    7
++#define DFC_TIMING_MAX_tWP    7
++#define DFC_TIMING_MAX_tRH    7
++#define DFC_TIMING_MAX_tRP    7
++#define DFC_TIMING_MAX_tR     65535
++#define DFC_TIMING_MAX_tWHR   15
++#define DFC_TIMING_MAX_tAR    15
++
++/*
++ * The Data Flash Controller Flash timing structure
++ * For NAND flash used on Zylonite board(Samsung K9K1216Q0C),
++ * user should use value at end of each row of following member
++ * bracketed.
++ */
++struct dfc_flash_timing {
++      uint32_t   tCH; /* Enable signal hold time */
++      uint32_t   tCS; /* Enable signal setup time */
++      uint32_t   tWH; /* ND_nWE high duration */
++      uint32_t   tWP; /* ND_nWE pulse time */
++      uint32_t   tRH; /* ND_nRE high duration */
++      uint32_t   tRP; /* ND_nRE pulse width */
++      uint32_t   tR;  /* ND_nWE high to ND_nRE low for read */
++      uint32_t   tWHR;/* ND_nWE high to ND_nRE low delay for status read */
++      uint32_t   tAR; /* ND_ALE low to ND_nRE low delay */
++};
++
++/* DFC command type */
++enum {
++      DFC_CMD_READ            = 0x00000000,
++      DFC_CMD_PROGRAM         = 0x00200000,
++      DFC_CMD_ERASE           = 0x00400000,
++      DFC_CMD_READ_ID         = 0x00600000,
++      DFC_CMD_STATUS_READ     = 0x00800000,
++      DFC_CMD_RESET           = 0x00a00000
++};
++
++/*
++ * The Data Flash Controller Flash specification structure
++ * For NAND flash used on Zylonite board(Samsung K9K1216Q0C),
++ * user should use value at end of each row of following member
++ * bracketed.
++ */
++struct dfc_flash_info {
++      struct dfc_flash_timing timing; /* NAND Flash timing */
++
++      int      enable_arbiter;/* Data flash bus arbiter enable (ND_ARB_EN) */
++      uint32_t page_per_block;/* Pages per block (PG_PER_BLK) */
++      uint32_t row_addr_start;/* Row address start position (RA_START) */
++      uint32_t read_id_bytes; /* returned ID bytes(RD_ID_CNT) */
++      uint32_t dfc_mode;      /* NAND, CARBONDALE, PIXLEY... (ND_MODE) */
++      uint32_t ncsx;          /* Chip select don't care bit (NCSX) */
++      uint32_t page_size;     /* Page size in bytes (PAGE_SZ) */
++      uint32_t oob_size;      /* OOB size */
++      uint32_t flash_width;   /* Width of Flash memory (DWIDTH_M) */
++      uint32_t dfc_width;     /* Width of flash controller(DWIDTH_C) */
++      uint32_t num_blocks;    /* Number of physical blocks in Flash */
++      uint32_t chip_id;
++
++      /* command codes */
++      uint32_t read1;         /* Read */
++      uint32_t read2;         /* unused, DFC don't support yet */
++      uint32_t program;       /* two cycle command */
++      uint32_t read_status;
++      uint32_t read_id;
++      uint32_t erase;         /* two cycle command */
++      uint32_t reset;
++      uint32_t lock;          /* lock whole flash */
++      uint32_t unlock;        /* two cycle command, supporting partial unlock */
++      uint32_t lock_status;   /* read block lock status */
++
++      /* addr2ndcb1 - encode address cycles into register NDCB1 */
++      /* ndbbr2addr - convert register NDBBR to bad block address */
++      int (*addr2ndcb1)(uint16_t cmd, uint32_t addr, uint32_t *p);
++      int (*ndbbr2addr)(uint16_t cmd, uint32_t ndbbr,uint32_t *p);
++};
++
++enum {
++      DFC_FLASH_NULL = 0 ,
++      DFC_FLASH_Samsung_512Mb_X_16 = 1,
++      DFC_FLASH_Micron_1Gb_X_8 = 2,
++      DFC_FLASH_Micron_1Gb_X_16 = 3,
++      DFC_FLASH_STM_1Gb_X_16 = 4,
++      DFC_FLASH_STM_2Gb_X_16 = 5,
++      DFC_FLASH_END,
++};
++
++static int dfc_get_flash_info(int type, struct dfc_flash_info **flash_info);
++
++#define               DFC_NDCR        0
++#define               DFC_NDTR0CS0    1
++#define               DFC_NDTR1CS0    3
++#define               DFC_NDSR        5
++#define               DFC_NDPCR       6
++#define               DFC_NDBDR0      7
++#define               DFC_NDBDR1      8
++#define               DFC_NDDB        16
++#define               DFC_NDCB0       18
++#define               DFC_NDCB1       19
++#define               DFC_NDCB2       20
++
++/* The Data Flash Controller Mode structure */
++struct dfc_mode {
++      int   enable_dma;       /* DMA, or nonDMA mode */
++      int   enable_ecc;       /* ECC on/off */
++      int   enable_spare;     /* Spare enable */
++      int   chip_select;      /* CS0 or CS1 */
++};
++
++/* The Data Flash Controller Context structure */
++struct dfc_context {
++      unsigned char __iomem   *membase;       /* DFC register base */
++      struct dfc_mode         *dfc_mode;      /* DFC mode */
++      int                     data_dma_ch;    /* Data DMA channel number */
++      int                     cmd_dma_ch;     /* CMD  DMA channel number */
++      struct dfc_flash_info   *flash_info; /* Flash Spec */
++      struct mtd_info         *mtd;
++};
++
++#define NDCB0_DMA_ADDR        0x43100048
++#define NDDB_DMA_ADDR 0x43100040
++
++#define NDSR_MASK     0xFFF
++
++/* The following data is a rough evaluation */
++
++/* microsecond, for readID/readStatus/reset */
++#define NAND_OTHER_TIMEOUT            10
++/* microsecond, for readID/readStatus/reset */
++#define NAND_CMD_TIMEOUT              10
++
++#define BBT_BLOCK_BAD 0x03
++#define BBT_BLOCK_GOOD        0x00
++#define BBT_BLOCK_REV1        0x01
++#define BBT_BLOCK_REV2        0x02
++
++#define BUFLEN                (2048 + 64)
++
++/*
++ * DFC data size enumeration transfered from/to controller,
++ * including padding (zero)to be a multiple of 32.
++ */
++enum {
++      DFC_DATA_SIZE_STATUS = 8,       /* ReadStatus/ReadBlockLockStatus */
++      DFC_DATA_SIZE_ID = 7,   /* ReadID */
++
++      DFC_DATA_SIZE_32 = 32,
++      DFC_DATA_SIZE_512 = 512,        /* R/W disabling spare area */
++      DFC_DATA_SIZE_520 = 520,        /* Spare=1, ECC=1 */
++      DFC_DATA_SIZE_528 = 528,        /* Spare=1, ECC=0 */
++      DFC_DATA_SIZE_544 = 544,        /* R/W enabling spare area.(DMA mode)*/
++
++      DFC_DATA_SIZE_64 = 64,
++      DFC_DATA_SIZE_2048 = 2048,      /* R/W disabling spare area */
++      DFC_DATA_SIZE_2088 = 2088,      /* R/W enabling spare area with ecc */
++      DFC_DATA_SIZE_2112 = 2112,      /* R/W enabling spare area without ecc*/
++      DFC_DATA_SIZE_2096 = 2096,      /* R/W enabling spare area */
++      DFC_DATA_SIZE_UNUSED = 0xFFFF
++};
++
++/* DFC padding size enumeration transfered from/to controller */
++enum {
++      /*
++       * ReadStatus/ReadBlockLockStatus/ReadID/
++       * Read/Program disabling spare area(Both 512 and 2048)
++       * Read/Program enabling spare area, disabling ECC
++       */
++      DFC_PADDING_SIZE_0 = 0,
++
++      /* Read/program with SPARE_EN=1, ECC_EN=0, pgSize=512 */
++      DFC_PADDING_SIZE_16 = 16,
++      /* for read/program with SPARE_EN=1, ECC_EN=1, pgSize=512 and 2048 */
++      DFC_PADDING_SIZE_24 = 24,
++      DFC_PADDING_SIZE_UNUSED = 0xFFFF
++};
++
++static unsigned int flash_config = DFC_FLASH_NULL;
++
++void dfc_set_timing(struct dfc_context *context, struct dfc_flash_timing *t);
++void dfc_set_dma(struct dfc_context *context);
++void dfc_set_ecc(struct dfc_context *context);
++void dfc_set_spare(struct dfc_context *context);
++
++int dfc_get_pattern(struct dfc_context *context, uint16_t cmd,
++                      int *data_size, int *padding);
++
++static int dfc_wait_event(struct dfc_context *context, uint32_t event,
++              uint32_t *event_out, uint32_t timeout, int enable_int);
++
++int dfc_send_cmd(struct dfc_context *context, uint16_t cmd,
++              uint32_t addr, int num_pages);
++
++void dfc_stop(struct dfc_context *context);
++void dfc_read_fifo_partial(struct dfc_context *context, uint8_t *buffer,
++                      int nbytes, int data_size);
++void dfc_write_fifo_partial(struct dfc_context *context, uint8_t *buffer,
++                      int nbytes, int data_size);
++
++void dfc_read_fifo(struct dfc_context *context, uint8_t *buffer, int nbytes);
++void dfc_write_fifo(struct dfc_context *context, uint8_t *buffer, int nbytes);
++
++void dfc_read_badblock_addr(struct dfc_context *context, uint32_t *bbaddr);
++
++void dfc_clear_int(struct dfc_context *context, uint32_t int_mask);
++void dfc_enable_int(struct dfc_context *context, uint32_t int_mask);
++void dfc_disable_int(struct dfc_context *context, uint32_t int_mask);
++
++/* high level primitives */
++int dfc_init(struct dfc_context *context, int type);
++int dfc_init_no_gpio(struct dfc_context *context, int type);
++
++int dfc_reset_flash(struct dfc_context *context);
++
++int dfc_setup_cmd_dma(struct dfc_context *context,
++              uint16_t cmd, uint32_t addr, int num_pages,
++              uint32_t *buf, uint32_t buf_phys,
++              uint32_t next_desc_phys, uint32_t dma_int_en,
++              struct pxa_dma_desc *dma_desc);
++
++int dfc_setup_data_dma(struct dfc_context *context,
++              uint16_t cmd, uint32_t buf_phys,
++              uint32_t next_desc_phys, uint32_t dma_int_en,
++              struct pxa_dma_desc *dma_desc);
++
++void dfc_start_cmd_dma(struct dfc_context *context,
++                      struct pxa_dma_desc *dma_desc);
++void dfc_start_data_dma(struct dfc_context *context,
++                      struct pxa_dma_desc *dma_desc);
++static int monahans_df_dev_ready(struct mtd_info *mtd);
++
++#ifdef CONFIG_DVFM
++static int mhn_nand_dvfm_notifier(unsigned cmd, void *client_data, void *info);
++static struct mhn_fv_notifier dvfm_notifier = {
++      .name           = "monahans-nand-flash",
++      .priority       = 0,
++      .notifier_call  = mhn_nand_dvfm_notifier,
++};
++#endif
++
++static unsigned short search_rel_block(int block, struct mtd_info *mtd);
++
++/*****************************************************************************
++ * The DFC registers read/write routines
++ *****************************************************************************/
++static inline void dfc_write(struct dfc_context *context, int offset,
++              unsigned long value)
++{
++      offset <<= 2;
++      writel(value, context->membase + offset);
++}
++
++static inline unsigned int dfc_read(struct dfc_context *context, int offset)
++{
++      offset <<= 2;
++      return __raw_readl(context->membase + offset);
++}
++
++/****************************************************************************
++ * Flash Information
++ ***************************************************************************/
++
++static int Samsung512MbX16Addr2NDCB1(uint16_t cmd, uint32_t addr, uint32_t *p);
++static int Samsung512MbX16NDBBR2Addr(uint16_t cmd, uint32_t ndbbr, uint32_t *p);
++
++static struct dfc_flash_info samsung512MbX16 =
++{
++      .timing = {
++              .tCH = 10,      /* tCH, Enable signal hold time */
++              .tCS = 0,       /* tCS, Enable signal setup time */
++              .tWH = 20,      /* tWH, ND_nWE high duration */
++              .tWP = 40,      /* tWP, ND_nWE pulse time */
++              .tRH = 30,      /* tRH, ND_nRE high duration */
++              .tRP = 40,      /* tRP, ND_nRE pulse width */
++              /* tR = tR+tRR+tWB+1, ND_nWE high to ND_nRE low for read */
++              .tR = 11123,
++              /* tWHR, ND_nWE high to ND_nRE low delay for status read */
++              .tWHR = 110,
++              .tAR = 10,      /* tAR, ND_ALE low to ND_nRE low delay */
++      },
++      .enable_arbiter = 1,    /* Data flash bus arbiter enable */
++      .page_per_block = 32,   /* Pages per block */
++      .row_addr_start = 0,    /* Second cycle start, Row address start position */
++      .read_id_bytes = 2,     /* 2 bytes, returned ID bytes */
++      .dfc_mode = 0,          /* NAND mode */
++      .ncsx = 0,
++      .page_size = 512,       /* Page size in bytes */
++      .oob_size = 16,         /* OOB size in bytes */
++      .flash_width = 16,      /* Width of Flash memory */
++      .dfc_width = 16,        /* Width of flash controller */
++      .num_blocks = 4096,     /* Number of physical blocks in Flash */
++      .chip_id =  0x46ec,
++
++      /* command codes */
++      .read1 = 0x0000,        /* Read */
++      .read2 = 0x0050,        /* Read1 unused, current DFC don't support */
++      .program = 0x1080,      /* Write, two cycle command */
++      .read_status = 0x0070,  /* Read status */
++      .read_id = 0x0090,      /* Read ID */
++      .erase =  0xD060,       /* Erase, two cycle command */
++      .reset = 0x00FF,        /* Reset */
++      .lock = 0x002A,         /* Lock whole flash */
++      .unlock = 0x2423,       /* Unlock, two cycle command, supporting partial unlock */
++      .lock_status = 0x007A,  /* Read block lock status */
++      .addr2ndcb1 = Samsung512MbX16Addr2NDCB1,
++      .ndbbr2addr = Samsung512MbX16NDBBR2Addr,
++};
++
++static int Samsung512MbX16Addr2NDCB1(uint16_t cmd, uint32_t addr, uint32_t *p)
++{
++      uint32_t ndcb1 = 0;
++
++      if (addr >= 0x4000000) return -EINVAL;
++
++      if (cmd == samsung512MbX16.read1 || cmd == samsung512MbX16.program) {
++              ndcb1 = (addr & 0xFF) | ((addr >> 1) & 0x01FFFF00);
++      } else if (cmd == samsung512MbX16.erase) {
++              ndcb1 = ((addr >> 9) & 0x00FFFFFF);
++      }
++
++      *p = ndcb1;
++      return 0;
++
++}
++
++static int Samsung512MbX16NDBBR2Addr(uint16_t cmd, uint32_t ndbbr, uint32_t *p)
++{
++      *p = ndbbr << 9;
++      return 0;
++}
++
++static int Micron1GbX8Addr2NDCB1(uint16_t cmd, uint32_t addr, uint32_t *p);
++static int Micron1GbX8NDBBR2Addr(uint16_t cmd, uint32_t ndbbr, uint32_t *p);
++
++static struct dfc_flash_info micron1GbX8 =
++{
++      .timing = {
++              .tCH = 10,      /* tCH, Enable signal hold time */
++              .tCS = 25,      /* tCS, Enable signal setup time */
++              .tWH = 15,      /* tWH, ND_nWE high duration */
++              .tWP = 25,      /* tWP, ND_nWE pulse time */
++              .tRH = 15,      /* tRH, ND_nRE high duration */
++              .tRP = 25,      /* tRP, ND_nRE pulse width */
++              /* tR = tR+tRR+tWB+1, ND_nWE high to ND_nRE low for read */
++              .tR = 25000,
++              /* tWHR, ND_nWE high to ND_nRE low delay for status read */
++              .tWHR = 60,
++              .tAR = 10,      /* tAR, ND_ALE low to ND_nRE low delay */
++      },
++      .enable_arbiter = 1,    /* Data flash bus arbiter enable */
++      .page_per_block = 64,   /* Pages per block */
++      .row_addr_start = 1,    /* Second cycle start, Row address start position */
++      .read_id_bytes = 4,     /* Returned ID bytes */
++      .dfc_mode = 0,          /* NAND mode */
++      .ncsx = 0,
++      .page_size = 2048,      /* Page size in bytes */
++      .oob_size = 64,         /* OOB size in bytes */
++      .flash_width = 8,       /* Width of Flash memory */
++      .dfc_width = 8,         /* Width of flash controller */
++      .num_blocks = 1024,     /* Number of physical blocks in Flash */
++      .chip_id =  0xa12c,
++      /* command codes */
++      .read1 = 0x3000,        /* Read */
++      .read2 = 0x0050,        /* Read1 unused, current DFC don't support */
++      .program = 0x1080,      /* Write, two cycle command */
++      .read_status = 0x0070,  /* Read status */
++      .read_id = 0x0090,      /* Read ID */
++      .erase =  0xD060,       /* Erase, two cycle command */
++      .reset = 0x00FF,        /* Reset */
++      .lock = 0x002A,         /* Lock whole flash */
++      .unlock = 0x2423,       /* Unlock, two cycle command, supporting partial unlock */
++      .lock_status = 0x007A,  /* Read block lock status */
++      .addr2ndcb1 = Micron1GbX8Addr2NDCB1,
++      .ndbbr2addr = Micron1GbX8NDBBR2Addr,
++};
++
++static int Micron1GbX8Addr2NDCB1(uint16_t cmd, uint32_t addr, uint32_t *p)
++{
++      uint32_t ndcb1 = 0;
++      uint32_t page;
++
++      if (addr >= 0x8000000)
++              return -EINVAL;
++      page = addr / micron1GbX8.page_size;
++      addr =  (page / micron1GbX8.page_per_block) << 18 |
++              (page % micron1GbX8.page_per_block) << 12;
++
++      if (cmd == micron1GbX8.read1 || cmd == micron1GbX8.program) {
++              ndcb1 = (addr & 0xFFF) | ((addr << 4) & 0xFFFF0000);
++      }
++      else if (cmd == micron1GbX8.erase) {
++              ndcb1 = ((addr >> 18) << 6) & 0xFFFF;
++      }
++
++      *p = ndcb1;
++      return 0;
++}
++
++static int Micron1GbX8NDBBR2Addr(uint16_t cmd, uint32_t ndbbr, uint32_t *p)
++{
++      if (cmd == micron1GbX8.read1 || cmd == micron1GbX8.program) {
++              *p = ((ndbbr & 0xF) << 8) | ((ndbbr >> 8) << 16);
++      }
++      else if (cmd == micron1GbX8.erase) {
++              *p = (ndbbr >> 6) << 18;
++      }
++
++
++      return 0;
++}
++
++
++static int Micron1GbX16Addr2NDCB1(uint16_t cmd, uint32_t addr, uint32_t *p);
++static int Micron1GbX16NDBBR2Addr(uint16_t cmd, uint32_t ndbbr, uint32_t *p);
++
++static struct dfc_flash_info micron1GbX16 =
++{
++      .timing = {
++              .tCH = 10,      /* tCH, Enable signal hold time */
++              .tCS = 25,      /* tCS, Enable signal setup time */
++              .tWH = 15,      /* tWH, ND_nWE high duration */
++              .tWP = 25,      /* tWP, ND_nWE pulse time */
++              .tRH = 15,      /* tRH, ND_nRE high duration */
++              .tRP = 25,      /* tRP, ND_nRE pulse width */
++              /* tR = tR+tRR+tWB+1, ND_nWE high to ND_nRE low for read */
++              .tR = 25000,
++              /* tWHR, ND_nWE high to ND_nRE low delay for status read */
++              .tWHR = 60,
++              .tAR = 10,      /* tAR, ND_ALE low to ND_nRE low delay */
++      },
++      .enable_arbiter = 1,    /* Data flash bus arbiter enable */
++      .page_per_block = 64,   /* Pages per block */
++      .row_addr_start = 1,    /* Second cycle start, Row address start position */
++      .read_id_bytes = 4,     /* Returned ID bytes */
++      .dfc_mode = 0,          /* NAND mode */
++      .ncsx = 0,
++      .page_size = 2048,      /* Page size in bytes */
++      .oob_size = 64,         /* OOB size in bytes */
++      .flash_width = 16,      /* Width of Flash memory */
++      .dfc_width = 16,        /* Width of flash controller */
++      .num_blocks = 1024,     /* Number of physical blocks in Flash */
++      .chip_id =  0xb12c,
++
++      /* command codes */
++      .read1 = 0x3000,        /* Read */
++      .read2 = 0x0050,        /* Read1 unused, current DFC don't support */
++      .program = 0x1080,      /* Write, two cycle command */
++      .read_status = 0x0070,  /* Read status */
++      .read_id = 0x0090,      /* Read ID */
++      .erase =  0xD060,       /* Erase, two cycle command */
++      .reset = 0x00FF,        /* Reset */
++      .lock = 0x002A,         /* Lock whole flash */
++      .unlock = 0x2423,       /* Unlock, two cycle command, supporting partial unlock */
++      .lock_status = 0x007A,  /* Read block lock status */
++      .addr2ndcb1 = Micron1GbX16Addr2NDCB1,
++      .ndbbr2addr = Micron1GbX16NDBBR2Addr,
++};
++
++static int Micron1GbX16Addr2NDCB1(uint16_t cmd, uint32_t addr, uint32_t *p)
++{
++      uint32_t ndcb1 = 0;
++      uint32_t page;
++
++      if (addr >= 0x8000000)
++              return -EINVAL;
++      page = addr / micron1GbX16.page_size;
++      addr =  (page / micron1GbX16.page_per_block) << 17 |
++              (page % micron1GbX16.page_per_block) << 11;
++
++      if (cmd == micron1GbX16.read1 || cmd == micron1GbX16.program) {
++              ndcb1 = (addr & 0x7FF) | ((addr << 5) & 0xFFFF0000);
++      }
++      else if (cmd == micron1GbX16.erase) {
++              ndcb1 = ((addr >> 17) << 6) & 0xFFFF;
++      }
++      *p = ndcb1;
++      return 0;
++}
++
++static int Micron1GbX16NDBBR2Addr(uint16_t cmd, uint32_t ndbbr, uint32_t *p)
++{
++      if (cmd == micron1GbX16.read1 || cmd == micron1GbX16.program) {
++              *p = ((ndbbr & 0x7) << 8) | ((ndbbr >> 8) << 16);
++      }
++      else if (cmd == micron1GbX16.erase) {
++              *p = (ndbbr >> 6) << 17;
++      }
++
++      return 0;
++}
++
++static int STM1GbX16Addr2NDCB1(uint16_t cmd, uint32_t addr, uint32_t *p);
++static int STM1GbX16NDBBR2Addr(uint16_t cmd, uint32_t ndbbr, uint32_t *p);
++
++static struct dfc_flash_info stm1GbX16 =
++{
++      .timing = {
++              .tCH = 10,      /* tCH, Enable signal hold time */
++              .tCS = 10,      /* tCS, Enable signal setup time */
++              .tWH = 20,      /* tWH, ND_nWE high duration */
++              .tWP = 25,      /* tWP, ND_nWE pulse time */
++              .tRH = 20,      /* tRH, ND_nRE high duration */
++              .tRP = 25,      /* tRP, ND_nRE pulse width */
++              /* tR = tR+tRR+tWB+1, ND_nWE high to ND_nRE low for read */
++              .tR = 25000,
++              /* tWHR, ND_nWE high to ND_nRE low delay for status read */
++              .tWHR = 60,
++              .tAR = 10,      /* tAR, ND_ALE low to ND_nRE low delay */
++      },
++      .enable_arbiter = 1,    /* Data flash bus arbiter enable */
++      .page_per_block = 64,   /* Pages per block */
++      .row_addr_start = 1,    /* Second cycle start, Row address start position */
++      .read_id_bytes = 4,     /* Returned ID bytes */
++      .dfc_mode = 0,          /* NAND mode */
++      .ncsx = 0,
++      .page_size = 2048,      /* Page size in bytes */
++      .oob_size = 64,         /* OOB size in bytes */
++      .flash_width = 16,      /* Width of Flash memory */
++      .dfc_width = 16,        /* Width of flash controller */
++      .num_blocks = 1024,     /* Number of physical blocks in Flash */
++      .chip_id =  0xb120,
++
++      /* command codes */
++      .read1 = 0x3000,        /* Read */
++      .read2 = 0x0050,        /* Read1 unused, current DFC don't support */
++      .program = 0x1080,      /* Write, two cycle command */
++      .read_status = 0x0070,  /* Read status */
++      .read_id = 0x0090,      /* Read ID */
++      .erase =  0xD060,       /* Erase, two cycle command */
++      .reset = 0x00FF,        /* Reset */
++      .lock = 0x002A,         /* Lock whole flash */
++      .unlock = 0x2423,       /* Unlock, two cycle command, supporting partial unlock */
++      .lock_status = 0x007A,  /* Read block lock status */
++      .addr2ndcb1 = STM1GbX16Addr2NDCB1,
++      .ndbbr2addr = STM1GbX16NDBBR2Addr,
++};
++
++static int STM1GbX16Addr2NDCB1(uint16_t cmd, uint32_t addr, uint32_t *p)
++{
++      uint32_t ndcb1 = 0;
++      uint32_t page;
++
++      if (addr >= 0x8000000)
++              return -EINVAL;
++      page = addr / stm1GbX16.page_size;
++      addr =  (page / stm1GbX16.page_per_block) << 17 |
++              (page % stm1GbX16.page_per_block) << 11;
++
++      if (cmd == stm1GbX16.read1 || cmd == stm1GbX16.program) {
++              ndcb1 = (addr & 0x7FF) | ((addr << 5) & 0xFFFF0000);
++      }
++      else if (cmd == stm1GbX16.erase) {
++              ndcb1 = ((addr >> 17) << 6) & 0xFFFF;
++      }
++      *p = ndcb1;
++      return 0;
++}
++
++static int STM1GbX16NDBBR2Addr(uint16_t cmd, uint32_t ndbbr, uint32_t *p)
++{
++      if (cmd == stm1GbX16.read1 || cmd == stm1GbX16.program) {
++              *p = ((ndbbr & 0x7) << 8) | ((ndbbr >> 8) << 16);
++      }
++      else if (cmd == stm1GbX16.erase) {
++              *p = (ndbbr >> 6) << 17;
++      }
++
++      return 0;
++}
++
++static int STM2GbX16Addr2NDCB1(uint16_t cmd, uint32_t addr, uint32_t *p);
++static int STM2GbX16NDBBR2Addr(uint16_t cmd, uint32_t ndbbr, uint32_t *p);
++
++static struct dfc_flash_info stm2GbX16 =
++{
++      .timing = {
++              .tCH = 10,      /* tCH, Enable signal hold time */
++              .tCS = 10,      /* tCS, Enable signal setup time */
++              .tWH = 20,      /* tWH, ND_nWE high duration */
++              .tWP = 25,      /* tWP, ND_nWE pulse time */
++              .tRH = 20,      /* tRH, ND_nRE high duration */
++              .tRP = 25,      /* tRP, ND_nRE pulse width */
++              /* tR = tR+tRR+tWB+1, ND_nWE high to ND_nRE low for read */
++              .tR = 25000,
++              /* tWHR, ND_nWE high to ND_nRE low delay for status read */
++              .tWHR = 60,
++              .tAR = 10,      /* tAR, ND_ALE low to ND_nRE low delay */
++      },
++      .enable_arbiter = 1,    /* Data flash bus arbiter enable */
++      .page_per_block = 64,   /* Pages per block */
++      .row_addr_start = 1,    /* Second cycle start, Row address start position */
++      .read_id_bytes = 4,     /* Returned ID bytes */
++      .dfc_mode = 0,          /* NAND mode */
++      .ncsx = 0,
++      .page_size = 2048,      /* Page size in bytes */
++      .oob_size = 64,         /* OOB size in bytes */
++      .flash_width = 16,      /* Width of Flash memory */
++      .dfc_width = 16,        /* Width of flash controller */
++      .num_blocks = 2048,     /* Number of physical blocks in Flash */
++      .chip_id =  0xca20,
++
++      /* command codes */
++      .read1 = 0x3000,        /* Read */
++      .read2 = 0x0050,        /* Read1 unused, current DFC don't support */
++      .program = 0x1080,      /* Write, two cycle command */
++      .read_status = 0x0070,  /* Read status */
++      .read_id = 0x0090,      /* Read ID */
++      .erase =  0xD060,       /* Erase, two cycle command */
++      .reset = 0x00FF,        /* Reset */
++      .lock = 0x002A,         /* Lock whole flash */
++      .unlock = 0x2423,       /* Unlock, two cycle command, supporting partial unlock */
++      .lock_status = 0x007A,  /* Read block lock status */
++      .addr2ndcb1 = STM2GbX16Addr2NDCB1,
++      .ndbbr2addr = STM2GbX16NDBBR2Addr,
++};
++
++static int STM2GbX16Addr2NDCB1(uint16_t cmd, uint32_t addr, uint32_t *p)
++{
++      uint32_t ndcb1 = 0;
++      uint32_t page;
++
++      if (addr >= 0x8000000)
++              return -EINVAL;
++      page = addr / stm2GbX16.page_size;
++      addr =  (page / stm2GbX16.page_per_block) << 17 |
++              (page % stm2GbX16.page_per_block) << 11;
++
++      if (cmd == stm2GbX16.read1 || cmd == stm2GbX16.program) {
++              ndcb1 = (addr & 0x7FF) | ((addr << 5) & 0xFFFF0000);
++      }
++      else if (cmd == stm2GbX16.erase) {
++              ndcb1 = ((addr >> 17) << 6) & 0xFFFF;
++      }
++      *p = ndcb1;
++      return 0;
++}
++
++static int STM2GbX16NDBBR2Addr(uint16_t cmd, uint32_t ndbbr, uint32_t *p)
++{
++      if (cmd == stm2GbX16.read1 || cmd == stm2GbX16.program) {
++              *p = ((ndbbr & 0x7) << 8) | ((ndbbr >> 8) << 16);
++      }
++      else if (cmd == stm2GbX16.erase) {
++              *p = (ndbbr >> 6) << 17;
++      }
++
++      return 0;
++}
++
++static struct {
++      int type;
++      struct dfc_flash_info *flash_info;
++} type_info[] = {
++      { DFC_FLASH_Samsung_512Mb_X_16, &samsung512MbX16},
++      { DFC_FLASH_Micron_1Gb_X_8, &micron1GbX8},
++      { DFC_FLASH_Micron_1Gb_X_16, &micron1GbX16},
++      { DFC_FLASH_STM_1Gb_X_16, &stm1GbX16},
++      { DFC_FLASH_STM_2Gb_X_16, &stm2GbX16},
++      { DFC_FLASH_NULL, NULL},
++};
++
++int dfc_get_flash_info(int type, struct dfc_flash_info **flash_info)
++{
++      uint32_t i = 0;
++
++      while(type_info[i].type != DFC_FLASH_NULL) {
++              if (type_info[i].type == type) {
++                      *flash_info = type_info[i].flash_info;
++                      return 0;
++              }
++              i++;
++      }
++      *flash_info = NULL;
++      return -EINVAL;
++}
++
++/******************************************************************************
++  dfc_set_timing
++
++  Description:
++      This function sets flash timing property in DFC timing register
++      according to input timing value embodied in context structure.
++      It is called once during the hardware initialization.
++  Input Parameters:
++  Output Parameters:
++      None
++  Returns:
++      None
++*******************************************************************************/
++//#if defined(CONFIG_CPU_MONAHANS_L) || defined(CONFIG_CPU_MONAHANS_LV)
++#define DFC_CLOCK     208
++//#else
++//#define DFC_CLOCK   104
++//#endif
++#define CLOCK_NS      DFC_CLOCK/1000
++
++void dfc_set_timing(struct dfc_context *context, struct dfc_flash_timing *t)
++{
++      struct dfc_flash_timing timing = *t;
++
++      uint32_t  r0 = 0;
++      uint32_t  r1 = 0;
++
++      /*
++       * num of clock cycles = time (ns) / one clock sycle (ns) + 1
++       * - integer division will truncate the result, so add a 1 in all cases
++       * - subtract the extra 1 cycle added to all register timing values
++       */
++      timing.tCH = min(((int) (timing.tCH * CLOCK_NS) + 1),
++                      DFC_TIMING_MAX_tCH);
++      timing.tCS = min(((int) (timing.tCS * CLOCK_NS) + 1),
++                      DFC_TIMING_MAX_tCS);
++      timing.tWH = min(((int) (timing.tWH * CLOCK_NS) + 1),
++                      DFC_TIMING_MAX_tWH);
++      timing.tWP = min(((int) (timing.tWP * CLOCK_NS) + 1),
++                      DFC_TIMING_MAX_tWP);
++      timing.tRH = min(((int) (timing.tRH * CLOCK_NS) + 1),
++                      DFC_TIMING_MAX_tRH);
++      timing.tRP = min(((int) (timing.tRP * CLOCK_NS) + 1),
++                      DFC_TIMING_MAX_tRP);
++
++      r0 = (timing.tCH << DFC_TIMING_tCH) |
++           (timing.tCS << DFC_TIMING_tCS) |
++           (timing.tWH << DFC_TIMING_tWH) |
++           (timing.tWP << DFC_TIMING_tWP) |
++           (timing.tRH << DFC_TIMING_tRH) |
++           (timing.tRP << DFC_TIMING_tRP);
++
++      dfc_write(context, DFC_NDTR0CS0, r0);
++
++      timing.tR   = min(((int) (timing.tR   * CLOCK_NS) + 1),
++                      DFC_TIMING_MAX_tR);
++      timing.tWHR = min(((int) (timing.tWHR * CLOCK_NS) + 1),
++                      DFC_TIMING_MAX_tWHR);
++      timing.tAR  = min(((int) (timing.tAR  * CLOCK_NS) + 1),
++                      DFC_TIMING_MAX_tAR);
++
++      r1 = (timing.tR   << DFC_TIMING_tR)   |
++           (timing.tWHR << DFC_TIMING_tWHR) |
++           (timing.tAR  << DFC_TIMING_tAR);
++
++      dfc_write(context, DFC_NDTR1CS0, r1);
++      return;
++}
++
++/******************************************************************************
++  dfc_set_dma
++
++  Description:
++              Enables or Disables DMA in line with setting in DFC mode of context
++              structure. DMA mode of DFC. Performs a read-modify-write operation that
++              only changes the driven DMA_EN bit field In DMA mode, all commands and
++              data are transferred by DMA.  DMA can be enable/disable on the fly.
++  Input Parameters:
++      context -Pointer to DFC context structure
++      Output Parameters:
++              None
++      Returns:
++              None
++*******************************************************************************/
++void
++dfc_set_dma(struct dfc_context* context)
++{
++      uint32_t ndcr;
++
++      ndcr = dfc_read(context, DFC_NDCR);
++      if (context->dfc_mode->enable_dma)
++              ndcr |= NDCR_DMA_EN;
++      else
++              ndcr &= ~NDCR_DMA_EN;
++
++      dfc_write(context, DFC_NDCR, ndcr);
++
++      /* Read again to make sure write work */
++      ndcr = dfc_read(context, DFC_NDCR);
++      return;
++}
++
++
++/******************************************************************************
++  dfc_set_ecc
++
++  Description:
++              This function enables or disables hardware ECC capability of DFC in line
++              with setting in DFC mode of context structure.
++  Input Parameters:
++      context -Pointer to DFC context structure
++      Output Parameters:
++              None
++      Returns:
++              None
++*******************************************************************************/
++void
++dfc_set_ecc(struct dfc_context* context)
++{
++      uint32_t ndcr;
++
++      ndcr = dfc_read(context, DFC_NDCR);
++      if (context->dfc_mode->enable_ecc)
++              ndcr |= NDCR_ECC_EN;
++      else
++              ndcr &= ~NDCR_ECC_EN;
++
++      dfc_write(context, DFC_NDCR, ndcr);
++
++      /* Read again to make sure write work */
++      ndcr = dfc_read(context, DFC_NDCR);
++      return;
++}
++
++/******************************************************************************
++  dfc_set_spare
++
++  Description:
++              This function enables or disables accesses to spare area of NAND Flash
++              through DFC in line with setting in DFC mode of context structure.
++  Input Parameters:
++      context -Pointer to DFC context structure
++  Output Parameters:
++      None
++  Returns:
++      None
++*******************************************************************************/
++void
++dfc_set_spare(struct dfc_context* context)
++{
++      uint32_t ndcr;
++
++      ndcr = dfc_read(context, DFC_NDCR);
++      if (context->dfc_mode->enable_spare)
++              ndcr |= NDCR_SPARE_EN;
++      else
++              ndcr &= ~NDCR_SPARE_EN;
++
++      dfc_write(context, DFC_NDCR, ndcr);
++
++      /* Read again to make sure write work */
++      ndcr = dfc_read(context, DFC_NDCR);
++      return;
++}
++
++static unsigned int get_delta (unsigned int start)
++{
++    unsigned int stop = OSCR;
++    return (stop - start);
++}
++
++static int dfc_wait_event(struct dfc_context *context, uint32_t event,
++              uint32_t *event_out, uint32_t timeout, int enable_int)
++{
++      uint32_t ndsr;
++      uint32_t to = 3 * timeout;      /* 3 ticks ~ 1us */
++      int status;
++      int start = OSCR;
++
++      if (enable_int)
++              dfc_enable_int(context, event);
++
++      while (1) {
++              ndsr = dfc_read(context, DFC_NDSR);
++              ndsr &= NDSR_MASK;
++              if (ndsr & event) {
++                      /* event happened */
++                      *event_out = ndsr & event;
++                      dfc_clear_int(context, *event_out);
++                      status = 0;
++                      break;
++              } else if (get_delta(start) > to) {
++                      status = -ETIME;
++                      break;
++              }
++      }
++
++      if (enable_int)
++              dfc_disable_int(context, event);
++      return status;
++}
++
++/******************************************************************************
++  dfc_get_pattern
++
++  Description:
++      This function is used to retrieve buffer size setting for a transaction
++      based on cmd.
++  Input Parameters:
++      context - Pointer to DFC context structure
++      cmd
++        Specifies type of command to be sent to NAND flash .The LSB of this
++        parameter defines the first command code for 2-cycles command. The
++        MSB defines the second command code for 2-cycles command. If MSB is
++        set to zero, this indicates that one cycle command
++      Output Parameters:
++      data_size
++        It is used to retrieve  length of data transferred to/from DFC,
++        which includes padding bytes
++      padding
++        It is used to retrieve how many padding bytes there should be
++        in buffer of data_size.
++      Returns:
++      0
++        If size setting is returned successfully
++      -EINVAL
++        If page size specified in flash spec of context structure is not 512 or
++        2048;If specified command index is not read1/program/erase/reset/readID/
++        readStatus.
++*******************************************************************************/
++int dfc_get_pattern(struct dfc_context *context, uint16_t cmd,
++                      int *data_size, int *padding)
++{
++      struct dfc_mode* dfc_mode = context->dfc_mode;
++      struct dfc_flash_info * flash_info = context->flash_info;
++      uint32_t page_size = context->flash_info->page_size; /* 512 or 2048 */
++
++      if (cmd == flash_info->read1 ||
++              cmd == flash_info->program) {
++              if (512 == page_size) {
++                      /* add for DMA */
++                      if (dfc_mode->enable_dma) {
++                              *data_size = DFC_DATA_SIZE_544;
++                              if (dfc_mode->enable_ecc)
++                                      *padding = DFC_PADDING_SIZE_24;
++                              else
++                                      *padding = DFC_PADDING_SIZE_16;
++                      } else if (!dfc_mode->enable_spare) {
++                              *data_size = DFC_DATA_SIZE_512;
++                              *padding = DFC_PADDING_SIZE_0;
++                      } else {
++
++                              if (dfc_mode->enable_ecc)
++                                      *data_size = DFC_DATA_SIZE_520;
++                              else
++                                      *data_size = DFC_DATA_SIZE_528;
++
++                              *padding = DFC_PADDING_SIZE_0;
++                      }
++              } else if (2048 == page_size) {
++                      /* add for DMA */
++                      if (dfc_mode->enable_dma) {
++                              *data_size = DFC_DATA_SIZE_2112;
++                              if (dfc_mode->enable_ecc)
++                                      *padding = DFC_PADDING_SIZE_24;
++                              else
++                                      *padding = DFC_PADDING_SIZE_0;
++                      } else if (!dfc_mode->enable_spare) {
++                              *data_size = DFC_DATA_SIZE_2048;
++                              *padding = DFC_PADDING_SIZE_0;
++                      } else {
++
++                              if (dfc_mode->enable_ecc)
++                                      *data_size = DFC_DATA_SIZE_2088;
++                              else
++                                      *data_size = DFC_DATA_SIZE_2112;
++
++                              *padding = DFC_PADDING_SIZE_0;
++                      }
++              } else /* if the page_size is neither 512 or 2048 */
++                      return -EINVAL;
++      } else if (cmd == flash_info->read_id) {
++              *data_size = DFC_DATA_SIZE_ID;
++              *padding = DFC_PADDING_SIZE_0;
++      } else if(cmd == flash_info->read_status) {
++              *data_size = DFC_DATA_SIZE_STATUS;
++              *padding = DFC_PADDING_SIZE_0;
++      } else if (cmd == flash_info->erase || cmd == flash_info->reset) {
++              *data_size = DFC_DATA_SIZE_UNUSED;
++              *padding = DFC_PADDING_SIZE_UNUSED;
++      } else
++              return -EINVAL;
++      return 0;
++}
++
++
++/******************************************************************************
++  dfc_send_cmd
++
++  Description:
++      This function configures DFC to send command through DFC to NAND flash
++  Input Parameters:
++      context
++        Pointer to DFC context structure
++      cmd
++        Specifies type of command to be sent to NAND flash .The LSB of this
++        parameter defines the first command code for 2-cycles command. The
++        MSB defines the second command code for 2-cycles command. If MSB is
++        set to zero, this indicates that one cycle command
++      addr
++        Address sent out to the flash device withthis command. For page read/
++        program commands , 4-cycles address is sent. For erase command only
++        3-cycles address is sent. If it is equal to 0xFFFFFFFF, the address
++        should not be used.
++      num_pages
++        It specifies the number of pages of data to be transferred for
++        a program or read commands. Unused for any other commands than
++        read/program.
++
++  Output Parameters:
++      None
++  Returns:
++      0
++        If size setting is returned successfully
++      -EINVAL
++        If specified command index is not read1/program/erase/reset/readID/
++        readStatus.
++*******************************************************************************/
++int dfc_send_cmd(struct dfc_context *context, uint16_t cmd,
++                      uint32_t addr, int num_pages)
++{
++      struct dfc_flash_info *flash_info = context->flash_info;
++      struct dfc_mode *dfc_mode = context->dfc_mode;
++      uint8_t  cmd2;
++      uint32_t event_out;
++      uint32_t ndcb0=0, ndcb1=0, ndcb2=0, ndcr;
++      int status;
++
++      /* It is a must to set ND_RUN firstly, then write command buffer
++       * If conversely,it does not work
++       */
++      dfc_write(context, DFC_NDSR, NDSR_MASK);
++
++      /* Set ND_RUN */
++      ndcr = dfc_read(context, DFC_NDCR);
++      dfc_write(context, DFC_NDCR, (ndcr | NDCR_ND_RUN));
++
++      // Wait for write command request
++      status = dfc_wait_event(context, NDSR_WRCMDREQ,
++              &event_out, NAND_CMD_TIMEOUT, 0);
++
++      if (status) /* Timeout */
++              return status;
++
++      cmd2 = (cmd>>8) & 0xFF;
++      ndcb0 = cmd | (dfc_mode->chip_select<<24) | ((cmd2?1:0)<<19);
++
++      if (cmd == flash_info->read1) {
++              if (0xFFFFFFFF != addr) {
++                      ndcb0 |= NDCB0_ADDR_CYC(4);
++                      status = flash_info->addr2ndcb1(cmd, addr, &ndcb1);
++                      if (status)
++                              return status;
++                      ndcb2 = (num_pages - 1) << 8;
++              }
++      } else if (cmd == flash_info->program) {
++              ndcb0 |= NDCB0_CMD_TYPE(1) | NDCB0_AUTO_RS;
++              ndcb0 |= NDCB0_ADDR_CYC(4);
++              status = flash_info->addr2ndcb1(cmd, addr, &ndcb1);
++              if (status)
++                      return status;
++              ndcb2 = (num_pages-1) << 8;
++      } else if (cmd == flash_info->erase) {
++              ndcb0 |= NDCB0_CMD_TYPE(2) | NDCB0_AUTO_RS;
++              ndcb0 |= NDCB0_ADDR_CYC(3);
++              status = flash_info->addr2ndcb1(cmd, addr, &ndcb1);
++              if (status)
++                      return status;
++      } else if (cmd == flash_info->read_id) {
++              ndcb0 |= NDCB0_CMD_TYPE(3);
++      } else if(cmd == flash_info->read_status) {
++              ndcb0 |= NDCB0_CMD_TYPE(4);
++      } else if(cmd == flash_info->reset) {
++              ndcb0 |= NDCB0_CMD_TYPE(5);
++      } else if (cmd == flash_info->lock) {
++              ndcb0 |= NDCB0_CMD_TYPE(5);
++      } else
++              return -EINVAL;
++
++      /* Write to DFC command register */
++      dfc_write(context, DFC_NDCB0, ndcb0);
++      dfc_write(context, DFC_NDCB0, ndcb1);
++      dfc_write(context, DFC_NDCB0, ndcb2);
++
++      return 0;
++}
++
++/******************************************************************************
++  dfc_stop
++
++  Description:
++      This function clears ND_RUN bit of NDCR.
++  Input Parameters:
++      context--Pointer to DFC context structure
++  Output Parameters:
++      None
++  Returns:
++      None
++*******************************************************************************/
++void dfc_stop(struct dfc_context *context)
++{
++      unsigned int ndcr;
++      ndcr = dfc_read(context, DFC_NDCR);
++      dfc_write(context, DFC_NDCR, (ndcr & ~NDCR_ND_RUN));
++      ndcr = dfc_read(context, DFC_NDCR);
++
++      return;
++}
++
++int dfc_setup_cmd_dma(struct dfc_context *context,
++              uint16_t cmd, uint32_t addr, int num_pages,
++              uint32_t *buf, uint32_t buf_phys,
++              uint32_t next_desc_phys, uint32_t dma_int_en,
++              struct pxa_dma_desc *dma_desc)
++{
++      struct dfc_flash_info *flash_info = context->flash_info;
++      struct dfc_mode *dfc_mode = context->dfc_mode;
++      uint8_t  cmd2;
++      uint32_t event_out;
++      uint32_t ndcb0=0, ndcb1=0, ndcb2=0, ndcr;
++      int status;
++
++      /*
++       * It is a must to set ND_RUN firstly, then write command buffer
++       * If conversely,it does not work
++       */
++      dfc_write(context, DFC_NDSR, NDSR_MASK);
++
++      /* Set ND_RUN */
++      ndcr = dfc_read(context, DFC_NDCR);
++      ndcr |= NDCR_ND_RUN;
++      dfc_write(context, DFC_NDCR, ndcr);
++
++      /* Wait for write command request */
++      status = dfc_wait_event(context, NDSR_WRCMDREQ,
++              &event_out, NAND_CMD_TIMEOUT, 0);
++
++      if (status)
++              return status; /* Timeout */
++
++      cmd2 = (cmd>>8) & 0xFF;
++      ndcb0 = cmd | (dfc_mode->chip_select<<24) | ((cmd2?1:0)<<19);
++
++      if (cmd == flash_info->read1) {
++              if (0xFFFFFFFF != addr) {
++                      ndcb0 |= NDCB0_ADDR_CYC(4);
++                      status = flash_info->addr2ndcb1(cmd, addr, &ndcb1);
++                      if (status)
++                              return status;
++                      ndcb2 = (num_pages-1) << 8;
++              }
++      } else if (cmd == flash_info->program) {
++              ndcb0 |= NDCB0_CMD_TYPE(1) | NDCB0_AUTO_RS;
++              ndcb0 |= NDCB0_ADDR_CYC(4);
++
++              status = flash_info->addr2ndcb1(cmd, addr, &ndcb1);
++              if (status)
++                      return status;
++              ndcb2 = (num_pages-1) << 8;
++      } else if (cmd == flash_info->erase) {
++              ndcb0 |= NDCB0_CMD_TYPE(2) | NDCB0_AUTO_RS;
++              ndcb0 |= NDCB0_ADDR_CYC(3);
++
++              status = flash_info->addr2ndcb1(cmd, addr, &ndcb1);
++              if (status)
++                      return status;
++      } else if (cmd == flash_info->read_id) {
++              ndcb0 |= NDCB0_CMD_TYPE(3);
++      } else if (cmd == flash_info->read_status) {
++              ndcb0 |= NDCB0_CMD_TYPE(4);
++      } else if (cmd == flash_info->reset) {
++              ndcb0 |= NDCB0_CMD_TYPE(5);
++      } else if (cmd == flash_info->lock) {
++              ndcb0 |= NDCB0_CMD_TYPE(5);
++      } else
++              return -EINVAL;
++
++      *((uint32_t *)buf) = ndcb0;
++      *((uint32_t *)buf + 1) = ndcb1;
++      *((uint32_t *)buf + 2) = ndcb2;
++
++      dma_int_en &= (DCMD_STARTIRQEN | DCMD_ENDIRQEN);
++
++      dma_desc->ddadr = next_desc_phys;
++      dma_desc->dsadr = buf_phys;
++      dma_desc->dtadr = NDCB0_DMA_ADDR;
++      dma_desc->dcmd  = DCMD_INCSRCADDR | DCMD_FLOWTRG | dma_int_en |
++                        DCMD_WIDTH4 | DCMD_BURST16 | 12;
++      return 0;
++}
++
++int dfc_setup_data_dma(struct dfc_context* context,
++              uint16_t cmd, uint32_t buf_phys,
++              uint32_t next_desc_phys, uint32_t dma_int_en,
++              struct pxa_dma_desc* dma_desc)
++{
++      struct dfc_flash_info * flash_info = context->flash_info;
++      int data_size, padding;
++
++      dfc_get_pattern(context, cmd, &data_size, &padding);
++
++      dma_desc->ddadr = next_desc_phys;
++      dma_int_en &= (DCMD_STARTIRQEN | DCMD_ENDIRQEN);
++
++      if (cmd == flash_info->program) {
++
++              dma_desc->dsadr = buf_phys;
++              dma_desc->dtadr = NDDB_DMA_ADDR;
++              dma_desc->dcmd  = DCMD_INCSRCADDR | DCMD_FLOWTRG | dma_int_en |
++                                DCMD_WIDTH4 | DCMD_BURST32 | data_size;
++
++      } else if (cmd == flash_info->read1 || cmd == flash_info->read_id ||
++                 cmd == flash_info->read_status) {
++
++              dma_desc->dsadr = NDDB_DMA_ADDR;
++              dma_desc->dtadr = buf_phys;
++              dma_desc->dcmd  = DCMD_INCTRGADDR | DCMD_FLOWSRC | dma_int_en |
++                                DCMD_WIDTH4 | DCMD_BURST32 | data_size;
++      }
++      else
++              return -EINVAL;
++      return 0;
++}
++
++void dfc_start_cmd_dma(struct dfc_context* context, struct pxa_dma_desc* dma_desc)
++{
++      DRCMR99 = DRCMR_MAPVLD | context->cmd_dma_ch;   /* NAND CMD DRCMR */
++      DDADR(context->cmd_dma_ch) = (uint32_t)dma_desc;
++      DCSR(context->cmd_dma_ch) |= DCSR_RUN;
++}
++
++void dfc_start_data_dma(struct dfc_context* context, struct pxa_dma_desc* dma_desc)
++{
++      DRCMR97 = DRCMR_MAPVLD | context->data_dma_ch;
++      DDADR(context->data_dma_ch) = (uint32_t)dma_desc;
++      DCSR(context->data_dma_ch) |= DCSR_RUN;
++}
++
++/******************************************************************************
++  dfc_read_fifo_partial
++
++  Description:
++      This function reads data from data buffer of DFC.Bytes can be any less than
++      or equal to data_size, the left is ignored by ReadFIFO though they will be
++      read from NDDB to clear data buffer.
++  Input Parameters:
++      context
++        Pointer to DFC context structure
++      nbytes
++        Indicating how much data should be read into buffer.
++      data_size
++        Specifing length of data transferred to/from DFC, which includes
++        padding bytes
++  Output Parameters:
++      pBuffer
++        Pointer to the data buffer where data should be placed.
++      Returns:
++        None
++*******************************************************************************/
++void dfc_read_fifo_partial(struct dfc_context *context, uint8_t *buffer,
++              int nbytes, int data_size)
++{
++      uint32_t data = 0;
++      uint32_t i = 0;
++      uint32_t bytes_multi;
++      uint32_t bytes_remain;
++
++
++      if (1 == data_size) {
++              data = dfc_read(context, DFC_NDDB) & 0xFF;
++              *buffer++ = (uint8_t)data;
++      } else if (2 == data_size) {
++              data = dfc_read(context, DFC_NDDB) & 0xFFFF;
++              *buffer++ = data & 0xFF;
++              *buffer++ = (data >> 8) & 0xFF;
++      } else {
++              bytes_multi = (nbytes & 0xFFFFFFFC);
++              bytes_remain = nbytes & 0x03;
++
++              i = 0;
++              /* Read the bytes_multi*4 bytes data */
++              while (i < bytes_multi) {
++                      data = dfc_read(context, DFC_NDDB);
++                      /* FIXME: we don't know whether the buffer
++                       * align to 4 bytes or not. Cast the buffer
++                       * to int is not safe here. Especially under
++                       * gcc 4.x. Used memcpy here. But the memcpy
++                       * may be not correct on BE architecture.
++                       * --by Yin, Fengwei
++                       */
++                      memcpy(buffer, &data, sizeof(data));
++                      i += sizeof(data);
++                      buffer += sizeof(data);
++              }
++
++              /* Read the left bytes_remain bytes data */
++              if (bytes_remain) {
++                      data = dfc_read(context, DFC_NDDB);
++                      for (i = 0; i < bytes_remain; i++)
++                              *buffer++ = (uint8_t)((data >> (8*i)) & 0xFF);
++              }
++
++              /* When read the remain bytes, we always read 4 bytes data
++               * to DFC. So the data_size should subtract following number.
++               */
++              data_size -= bytes_multi + (bytes_remain ? sizeof(data) : 0);
++
++              /* We need Read data_size bytes data totally */
++              while (data_size > 0) {
++                      data = dfc_read(context, DFC_NDDB);
++                      data_size -= sizeof(data);
++              }
++
++/*
++              while(i < ((uint32_t)data_size) ) {
++                      if (i < bytes_multi) {
++                              temp = (uint32_t *)buffer;
++                              *temp = dfc_reg->nddb;
++                      } else if (i == bytes_multi && bytes_remain){
++                              uint32_t j = 0;
++                              data = dfc_reg->nddb;
++                              while (j++ < bytes_remain) {
++                                      *buffer++ = (uint8_t)   \
++                                              ((data>>(8*j)) & 0xFF);
++                              }
++                      } else {
++                              data = dfc_reg->nddb;
++                      }
++                      i += 4;
++                      buffer += 4;
++              }
++*/
++      }
++      return;
++}
++
++/******************************************************************************
++  dfc_write_fifo_partial
++
++  Description:
++      Write to data buffer of DFC from a buffer. Bytes can be same as
++      data_size, also can be data_size-padding, but can¡¯t be random value,
++      the left will be automatically padded by WriteFIFO.
++  Input Parameters:
++      context
++        Pointer to DFC context structure
++      bytes
++        Indicating how much data should be read into buffer.
++      data_size
++        Specifing length of data transferred to/from DFC, which includes
++        padding bytes
++      buffer
++        Pointer to the data buffer where data will be taken from to be written
++        to DFC data buffer
++  Output Parameters:
++      None
++  Returns:
++      None
++*******************************************************************************/
++void dfc_write_fifo_partial(struct dfc_context *context, uint8_t *buffer,
++              int nbytes, int data_size)
++{
++      uint32_t i = 0;
++
++      uint32_t bytes_multi = (nbytes & 0xFFFFFFFC);
++      uint32_t bytes_remain = nbytes & 0x03;
++      uint32_t temp;
++      /*
++       * caller guarantee buffer contains appropriate data thereby
++       * it is impossible for nbytes not to be a multiple of 4 byte
++       */
++
++      /* Write the bytes_multi*4 bytes data */
++      while (i < bytes_multi) {
++              temp = buffer[0] | buffer[1] << 8 |
++                              buffer[2] << 16 | buffer[3] << 24;
++              dfc_write(context, DFC_NDDB, temp);
++              buffer += 4;
++              i += 4;
++      }
++
++      /* Write the left bytes_remain bytes data */
++      if (bytes_remain) {
++              temp = 0xFFFFFFFF;
++              for (i = 0; i < bytes_remain; i++)
++                      temp &= *buffer++ << i*8;
++
++              dfc_write(context, DFC_NDDB, temp);
++      }
++
++      /* When write the remain bytes, we always write 4 bytes data
++       * to DFC. So the data_size should subtract following number.
++       */
++      data_size -= bytes_multi + (bytes_remain ? sizeof(temp) : 0);
++
++      while (data_size > 0) {
++              dfc_write(context, DFC_NDDB, 0xFFFFFFFF);
++              data_size -= 4;
++      }
++
++/*
++      while (i < ((uint32_t)data_size)) {
++              if (i < bytes_multi) {
++                      temp = (uint32_t *)buffer;
++                      dfc_reg->nddb = *temp;
++              }
++              else if (i == bytes_multi && bytes_remain) {
++                              uint32_t j = 0, data = 0xFFFFFFFF;
++                              while (j < bytes_remain) {
++                                data &= (uint8_t)(*buffer) << j;
++                                buffer++;
++                                j++;
++                              }
++                      dfc_reg->nddb = data;
++              }
++              else {
++                      dfc_reg->nddb = 0xFFFFFFFF;
++              }
++              i += 4;
++              buffer += 4;
++      }
++*/
++
++      return;
++}
++
++/******************************************************************************
++  dfc_read_fifo
++  Description:
++      This function reads data from data buffer of DFC.Bytes can be any less
++      than or equal to data_size, the left is ignored by ReadFIFO though they
++      will be read from NDDB to clear data buffer.
++  Input Parameters:
++      context
++        Pointer to DFC context structure
++      nbytes
++        Indicating how much data should be read into buffer.
++      data_size
++        Specifing length of data transferred to/from DFC, which includes
++        padding bytes
++  Output Parameters:
++      buffer
++        Pointer to the data buffer where data should be placed.
++  Returns:
++      None
++*******************************************************************************/
++
++void dfc_read_fifo(struct dfc_context *context, uint8_t *buffer, int nbytes)
++{
++      uint32_t i = 0;
++
++      uint32_t bytes_multi = (nbytes & 0xFFFFFFFC);
++      uint32_t bytes_remain = nbytes & 0x03;
++      uint32_t temp;
++
++      /* Read the bytes_multi*4 bytes data */
++      while (i < bytes_multi) {
++              temp = dfc_read(context, DFC_NDDB);
++              /* FIXME: we don't know whether the buffer
++               * align to 4 bytes or not. Cast the buffer
++               * to int is not safe here. Especially under
++               * gcc 4.x. Used memcpy here. But the memcpy
++               * may be not correct on BE architecture.
++               * --by Yin, Fengwei
++               */
++              memcpy(buffer, &temp, sizeof(temp));
++              i += sizeof(temp);
++              buffer += sizeof(temp);
++      }
++
++      /* Read the left bytes_remain bytes data */
++      temp = dfc_read(context, DFC_NDDB);
++      for (i = 0; i < bytes_remain; i++) {
++              *buffer++ = (uint8_t)((temp >> (8*i)) & 0xFF);
++      }
++
++/*
++      while (i < bytes_multi) {
++          temp = (uint32_t *)buffer;
++          *temp = dfc_reg->nddb;
++          i += 4;
++          buffer += 4;
++      }
++
++      if (bytes_remain) {
++              data = dfc_reg->nddb;
++              for (i = 0; i < bytes_remain; i++) {
++                      *buffer++ = (uint8_t)((data>>(8*i)) & 0xFF);
++              }
++      }
++*/
++
++      return;
++}
++
++/******************************************************************************
++  dfc_write_fifo
++  Description:
++      Write to data buffer of DFC from a buffer.Bytes can be same as data_size,
++      also can be data_size-padding, but can¡¯t be random value, the left will
++      be automatically padded by WriteFIFO.
++  Input Parameters:
++      context
++        Pointer to DFC context structure
++      nbytes
++        Indicating how much data should be read into buffer.
++      data_size
++        Specifing length of data transferred to/from DFC, which includes
++        padding bytes
++      buffer
++        Pointer to the data buffer where data will be taken from to be written to
++        DFC data buffer
++  Output Parameters:
++      None
++  Returns:
++      None
++*******************************************************************************/
++void dfc_write_fifo(struct dfc_context *context, uint8_t *buffer, int nbytes)
++{
++      uint32_t bytes_multi = (nbytes & 0xFFFFFFFC);
++      uint32_t bytes_remain = nbytes & 0x03;
++      uint32_t i=0;
++      uint32_t temp;
++
++      /* Write the bytes_multi*4 bytes data */
++      while (i < bytes_multi) {
++              temp = buffer[0] | buffer[1] << 8 |
++                              buffer[2] << 16 | buffer[3] << 24;
++              dfc_write(context, DFC_NDDB, temp);
++              buffer += 4;
++              i += 4;
++      }
++
++      /* Write the left bytes_remain bytes data */
++      temp = 0xFFFFFFFF;
++      for (i = 0; i < bytes_remain; i++)
++              temp &= *buffer++ << i*8;
++      dfc_write(context, DFC_NDDB, temp);
++
++/*
++      while (i < nbytes) {
++          temp = (uint32_t *)buffer;
++          dfc_reg->nddb = *temp;
++          i += 4;
++          buffer += 4;
++      }
++*/
++}
++
++/******************************************************************************
++  dfc_read_badblock_addr
++
++  Description:
++      This function reads bad block address in units of block starting from 0
++      if bad block is detected. It takes into the account if the operation is
++      for CS0 or CS1  depending on settings of chip_select parameter of DFC
++      Mode structure.
++  Input Parameters:
++      context
++        Pointer to DFC context structure
++  Output Parameters:
++      pBadBlockAddr
++        Used to retrieve bad block address back to caller if bad block is
++        detected
++  Returns:
++      None
++*******************************************************************************/
++void dfc_read_badblock_addr(struct dfc_context *context, uint32_t *bbaddr)
++{
++      uint32_t ndbdr;
++      if (0 == context->dfc_mode->chip_select)
++              ndbdr = dfc_read(context, DFC_NDBDR0);
++      else
++              ndbdr = dfc_read(context, DFC_NDBDR1);
++
++      if (512 == context->flash_info->page_size) {
++              ndbdr = (ndbdr >> 5) & 0xFFF;
++              *bbaddr = ndbdr;
++      } else if (2048 == context->flash_info->page_size) {
++              /* 16 bits LB */
++              ndbdr = (ndbdr >> 8);
++              *bbaddr = ndbdr;
++      }
++      return;
++}
++
++/******************************************************************************
++  dfc_enable_int
++
++  Description:
++      This function is used to enable DFC interrupts. The bits in int_mask
++      will be used to unmask NDCR register to enable corresponding interrupts.
++  Input Parameters:
++      context
++        Pointer to DFC context structure
++      int_mask
++        Specifies what interrupts to enable
++  Output Parameters:
++      None
++  Returns:
++      None
++*******************************************************************************/
++void dfc_enable_int(struct dfc_context *context, uint32_t int_mask)
++{
++      uint32_t ndcr;
++
++      ndcr = dfc_read(context, DFC_NDCR);
++      ndcr &= ~int_mask;
++      dfc_write(context, DFC_NDCR, ndcr);
++
++      ndcr = dfc_read(context, DFC_NDCR);
++      return;
++}
++
++/******************************************************************************
++  dfc_disable_int
++
++  Description:
++      This function is used to disable DFC interrupts.
++      The bits inint_mask will be used to mask NDCR register to disable
++      corresponding interrupts.
++  Input Parameters:
++      context
++        Pointer to DFC context structure
++      int_mask
++        Specifies what interrupts to disable
++  Output Parameters:
++      None
++  Returns:
++      None
++*******************************************************************************/
++void dfc_disable_int(struct dfc_context *context, uint32_t int_mask)
++{
++      uint32_t ndcr;
++
++      ndcr = dfc_read(context, DFC_NDCR);
++      ndcr |= int_mask;
++      dfc_write(context, DFC_NDCR, ndcr);
++
++      ndcr = dfc_read(context, DFC_NDCR);
++      return;
++}
++
++/******************************************************************************
++  dfc_clear_int
++
++  Description:
++      This function is used to disable DFC interrupts.
++      The bits in int_mask will be used to clear corresponding interrupts
++      in NDCR register
++  Input Parameters:
++      context
++        Pointer to DFC context structure
++      int_mask
++        Specifies what interrupts to clear
++  Output Parameters:
++      None
++  Returns:
++      None
++*******************************************************************************/
++void dfc_clear_int(struct dfc_context *context, uint32_t int_mask)
++{
++      dfc_write(context, DFC_NDSR, int_mask);
++
++      dfc_read(context, DFC_NDSR);
++      return;
++}
++
++/*
++ * high level primitives
++ */
++
++/******************************************************************************
++  dfc_init
++
++  Description:
++      This function does entire DFC initialization according to the NAND
++      flash type currently used with platform, including setting MFP, set
++      flash timing, set DFC mode, configuring specified flash parameters
++      in DFC, clear ECC logic and page count register.
++  Input Parameters:
++      context
++        Pointer to DFC context structure
++  Output Parameters:
++      None
++  Returns:
++      0
++        if MFPRs are set correctly
++      -EINVAL
++        if specified flash is not support by check bytes per page and pages per
++        block
++******************************************************************************/
++
++static mfp_cfg_t pxa300_nand_cfg[] = {
++      /* NAND */
++      MFP_CFG_X(DF_INT_RnB, AF0, DS10X, PULL_LOW),
++      MFP_CFG_X(DF_nRE_nOE, AF1, DS10X, PULL_LOW),
++      MFP_CFG_X(DF_nWE, AF1, DS10X, PULL_LOW),
++      MFP_CFG_X(DF_CLE_nOE, AF0, DS10X, PULL_LOW),
++      MFP_CFG_X(DF_nADV1_ALE, AF1, DS10X, PULL_LOW),
++      MFP_CFG_X(DF_nCS0, AF1, DS10X, PULL_LOW),
++      MFP_CFG_X(DF_nCS1, AF0, DS10X, PULL_LOW),
++      MFP_CFG_X(DF_IO0, AF1, DS08X, PULL_LOW),
++      MFP_CFG_X(DF_IO1, AF1, DS08X, PULL_LOW),
++      MFP_CFG_X(DF_IO2, AF1, DS08X, PULL_LOW),
++      MFP_CFG_X(DF_IO3, AF1, DS08X, PULL_LOW),
++      MFP_CFG_X(DF_IO4, AF1, DS08X, PULL_LOW),
++      MFP_CFG_X(DF_IO5, AF1, DS08X, PULL_LOW),
++      MFP_CFG_X(DF_IO6, AF1, DS08X, PULL_LOW),
++      MFP_CFG_X(DF_IO7, AF1, DS08X, PULL_LOW),
++      MFP_CFG_X(DF_IO8, AF1, DS08X, PULL_LOW),
++      MFP_CFG_X(DF_IO9, AF1, DS08X, PULL_LOW),
++      MFP_CFG_X(DF_IO10, AF1, DS08X, PULL_LOW),
++      MFP_CFG_X(DF_IO11, AF1, DS08X, PULL_LOW),
++      MFP_CFG_X(DF_IO12, AF1, DS08X, PULL_LOW),
++      MFP_CFG_X(DF_IO13, AF1, DS08X, PULL_LOW),
++      MFP_CFG_X(DF_IO14, AF1, DS08X, PULL_LOW),
++};
++
++#define ARRAY_AND_SIZE(x)     (x), ARRAY_SIZE(x)
++
++int dfc_init(struct dfc_context* context, int type)
++{
++      int status;
++      struct dfc_flash_info * flash_info;
++      uint32_t ndcr = 0x00000FFF; /* disable all interrupts */
++
++      status = dfc_get_flash_info(type, &flash_info);
++      if (status)
++              return status;
++      context->flash_info = flash_info;
++
++      pxa3xx_mfp_config(ARRAY_AND_SIZE(pxa300_nand_cfg));
++      //enable_dfc_pins();
++
++      dfc_set_timing(context, &context->flash_info->timing);
++
++      if (flash_info->enable_arbiter)
++              ndcr |= NDCR_ND_ARB_EN;
++
++      if (64 == flash_info->page_per_block)
++              ndcr |= NDCR_PG_PER_BLK;
++      else if (32 != flash_info->page_per_block)
++              return -EINVAL;
++
++      if (flash_info->row_addr_start)
++              ndcr |= NDCR_RA_START;
++
++      ndcr |=  (flash_info->read_id_bytes)<<16;
++
++      ndcr |= (flash_info->dfc_mode) << 21;
++
++      if (flash_info->ncsx)
++              ndcr |= NDCR_NCSX;
++
++      if (2048 == flash_info->page_size)
++              ndcr |= NDCR_PAGE_SZ;
++      else if (512 != flash_info->page_size)
++              return -EINVAL;
++
++      if (16 == flash_info->flash_width)
++              ndcr |= NDCR_DWIDTH_M;
++      else if (8 != flash_info->flash_width)
++              return -EINVAL;
++
++      if (16 == flash_info->dfc_width)
++              ndcr |= NDCR_DWIDTH_C;
++      else if (8 != flash_info->dfc_width)
++              return -EINVAL;
++
++      dfc_write(context, DFC_NDCR, ndcr);
++
++      dfc_set_dma(context);
++      dfc_set_ecc(context);
++      dfc_set_spare(context);
++
++      return 0;
++}
++
++/******************************************************************************
++  dfc_init_no_gpio
++
++  Description:
++      This function does entire DFC initialization according to the NAND
++      flash type currently used with platform, including set flash timing,
++      set DFC mode, configuring specified flash parameters in DFC, clear
++      ECC logic and page count register. The only difference with dfc_init
++      is that it does not set MFP&GPIO, very useful in OS loader
++  Input Parameters:
++      context
++        Pointer to DFC context structure
++  Output Parameters:
++      None
++  Returns:
++      0
++        if MFPRs are set correctly
++      -EINVAL
++        if specified flash is not support by check bytes per page and pages
++        per block
++******************************************************************************/
++int dfc_init_no_gpio(struct dfc_context* context, int type)
++{
++      struct dfc_flash_info * flash_info;
++      uint32_t ndcr = 0x00000FFF; /* disable all interrupts */
++      int status;
++
++      status = dfc_get_flash_info(type, &flash_info);
++      if (status)
++              return status;
++      context->flash_info = flash_info;
++
++      dfc_set_timing(context, &context->flash_info->timing);
++
++      if (flash_info->enable_arbiter)
++              ndcr |= NDCR_ND_ARB_EN;
++
++      if (64 == flash_info->page_per_block)
++              ndcr |= NDCR_PG_PER_BLK;
++      else if (32 != flash_info->page_per_block)
++              return -EINVAL;
++
++      if (flash_info->row_addr_start)
++              ndcr |= NDCR_RA_START;
++
++      ndcr |=  (flash_info->read_id_bytes)<<16;
++
++      ndcr |= (flash_info->dfc_mode) << 21;
++
++      if (flash_info->ncsx)
++              ndcr |= NDCR_NCSX;
++
++      if (2048 == flash_info->page_size)
++              ndcr |= NDCR_PAGE_SZ;
++      else if (512 != flash_info->page_size)
++              return -EINVAL;
++
++      if (16 == flash_info->flash_width)
++              ndcr |= NDCR_DWIDTH_M;
++      else if (8 != flash_info->flash_width)
++              return -EINVAL;
++
++      if (16 == flash_info->dfc_width)
++              ndcr |= NDCR_DWIDTH_C;
++      else if (8 != flash_info->dfc_width)
++              return -EINVAL;
++
++      dfc_write(context, DFC_NDCR, ndcr);
++
++      dfc_set_dma(context);
++      dfc_set_ecc(context);
++      dfc_set_spare(context);
++
++      return 0;
++}
++
++/*
++ * This macro will be used in following NAND operation functions.
++ * It is used to clear command buffer to ensure cmd buffer is empty
++ * in case of operation is timeout
++ */
++#define ClearCMDBuf()         do {                                    \
++                              dfc_stop(context);              \
++                              udelay(NAND_OTHER_TIMEOUT);     \
++                      } while (0)
++
++/******************************************************************************
++  dfc_reset_flash
++
++  Description:
++      It reset the flash. The function can be called at any time when the
++      device is in Busy state during random read/program/erase mode and
++      reset operation will abort all these operations. After reset operation
++      the device is ready to wait for next command
++  Input Parameters:
++      context
++        Pointer to DFC context structure
++  Output Parameters:
++      None
++  Returns:
++      0
++        execution succeeds
++      -ETIME
++        if timeout
++*******************************************************************************/
++int dfc_reset_flash(struct dfc_context *context)
++{
++      struct dfc_flash_info *flash_info = context->flash_info;
++      uint32_t event, event_out;
++      unsigned long timeo;
++      int status;
++
++      /* Send command */
++      dfc_send_cmd(context, (uint16_t)flash_info->reset, 0xFFFFFFFF, 0);
++
++      event = (context->dfc_mode->chip_select)? \
++                      NDSR_CS1_CMDD : NDSR_CS0_CMDD;
++
++      /* Wait for CMDDM(command done successfully) */
++      status = dfc_wait_event(context, event, &event_out,
++              NAND_OTHER_TIMEOUT, 0);
++
++      if (status) {
++              ClearCMDBuf();
++              return status;
++      }
++
++
++      /* Wait until flash device is stable or timeout (10ms) */
++      timeo = jiffies + HZ;
++      do {
++              if (monahans_df_dev_ready(context->mtd))
++                      break;
++      } while (time_before(jiffies, timeo));
++
++      return 0;
++}
++
++int dfc_readid(struct dfc_context *context, uint32_t *id)
++{
++      struct dfc_flash_info *flash_info = context->flash_info;
++      uint32_t event_out;
++      int status;
++      char tmp[DFC_DATA_SIZE_ID];
++
++      /* Send command */
++      status = dfc_send_cmd(context, (uint16_t)flash_info->read_id,
++                      0xFFFFFFFF, 0);
++      if (status) {
++              ClearCMDBuf();
++              return status;
++      }
++
++      /* Wait for CMDDM(command done successfully) */
++      status = dfc_wait_event(context, NDSR_RDDREQ, &event_out,
++              NAND_OTHER_TIMEOUT, 0);
++      if (status) {
++              ClearCMDBuf();
++              return status;
++      }
++      dfc_read_fifo_partial(context, (unsigned char *)tmp,
++                      context->flash_info->read_id_bytes, DFC_DATA_SIZE_ID);
++
++      *id = tmp[0] | (tmp[1] << 8);
++      return 0;
++}
++
++#define ERR_NONE              0x0
++#define ERR_DMABUSERR         (-0x01)
++#define ERR_SENDCMD           (-0x02)
++#define ERR_DBERR             (-0x03)
++#define ERR_BBERR             (-0x04)
++#define ERR_BUSY              (-0x05)
++
++#define STATE_CMD_SEND                0x1
++#define STATE_CMD_HANDLE      0x2
++#define STATE_DMA_TRANSFER    0x3
++#define STATE_DMA_DONE                0x4
++#define STATE_READY           0x5
++#define STATE_SUSPENDED               0x6
++#define       STATE_DATA_TRANSFER     0x7
++
++#define NAND_RELOC_MAX                127
++#define NAND_RELOC_HEADER     0x524e
++#define MAX_CHIP              1
++#define NAND_CMD_DMA_LEN      12
++
++#define MAX_TIM_SIZE  0x1000
++#define MAX_BBT_SLOTS 24
++
++struct reloc_item {
++      unsigned short from;
++      unsigned short to;
++};
++
++struct reloc_table {
++      unsigned short header;
++      unsigned short total;
++      struct reloc_item reloc[NAND_RELOC_MAX];
++};
++
++struct monahans_dfc_info {
++      unsigned int            state;
++      struct dfc_context      *context;
++#ifdef CONFIG_MTD_NAND_MONAHANS_DMA
++      dma_addr_t              data_buf_addr;
++      char                    *data_buf;
++      int                     data_dma;
++      struct pxa_dma_desc     *data_desc;
++      dma_addr_t              data_desc_addr;
++      dma_addr_t              cmd_buf_addr;
++      char                    *cmd_buf;
++      int                     cmd_dma;
++      struct pxa_dma_desc     *cmd_desc;
++      dma_addr_t              cmd_desc_addr;
++      u64                     dma_mask;
++#else
++      char                    *data_buf;
++#endif
++      u32                     current_slot;
++      struct reloc_table      table;
++      unsigned int            table_init;
++      /* relate to the command */
++      unsigned int            cmd;
++      unsigned int            addr;
++      unsigned int            column;
++      int                     retcode;
++      unsigned int            buf_count;
++      struct completion       cmd_complete;
++};
++
++static struct dfc_mode dfc_mode =
++{
++#ifdef CONFIG_MTD_NAND_MONAHANS_DMA
++      1,      /* enable DMA */
++#else
++      0,
++#endif
++      1,      /* enable ECC */
++      1,      /* enable SPARE */
++      0,      /* CS0 */
++};
++
++
++struct dfc_context dfc_context =
++{
++      0,      /* Initialized at function monahans_df_init() */
++      &dfc_mode,
++      0,      /* data dma channel */
++      0,      /* cmd dma channel */
++      NULL,   /* &zylonite_flashinfo */
++};
++
++
++/*
++ * MTD structure for Zylonite board
++ */
++static struct mtd_info *monahans_mtd = NULL;
++
++/*
++ * BootRom and XDB will use last 127 block, and they will keep all the status
++ * of the bootloader and image, so skip the first 2M size and last 2M size
++ */
++static struct mtd_partition partition_info[] = {
++      {
++              name:           "Bootloader",
++//#ifdef      CONFIG_CPU_MONAHANS_LV
++              size:           0x00060000,
++//#else
++//            size:           0x00040000,
++//#endif
++              offset:         0,
++              mask_flags:     MTD_WRITEABLE  /* force read-only */
++      },{
++              name:           "Kernel",
++              size:           0x00200000,
++//#ifdef      CONFIG_CPU_MONAHANS_LV
++              offset:         0x00060000,
++//#else
++//            offset:         0x00040000,
++//#endif
++              mask_flags:     MTD_WRITEABLE  /* force read-only */
++      },{
++              name:           "Filesystem",
++              size:           0x05000000,
++//#ifdef      CONFIG_CPU_MONAHANS_LV
++              offset:         0x00260000,
++//#else
++//            offset:         0x00240000,
++//#endif
++      }, {
++              name:           "MassStorage",
++              size:           0x0, /* It will be set at probe function */
++              offset:         MTDPART_OFS_APPEND /* Append after fs section */
++      }, {
++              name:           "BBT",
++              size:           0x0, /* It will be set at probe function */
++              offset:         MTDPART_OFS_APPEND,/* Append after fs section */
++              mask_flags:     MTD_WRITEABLE  /* force read-only */
++      }
++};
++
++#define               PART_NUM        ARRAY_SIZE(partition_info)
++
++/* MHN_OBM_V2 is related to BBT in MOBM V2
++ * MHN_OBM_V3 is related to BBT in MOBM V3
++ */
++enum {
++      MHN_OBM_NULL = 0,
++      MHN_OBM_V1,
++      MHN_OBM_V2,
++      MHN_OBM_V3,
++      MHN_OBM_INVAL
++} MHN_OBM_TYPE;
++
++static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
++static uint8_t scan_main_bbt_pattern[] = { 'p', 'x', 'a', '1' };
++static uint8_t scan_mirror_bbt_pattern[] = { '0', 'a', 'x', 'p' };
++
++static struct nand_bbt_descr monahans_bbt_default = {
++      .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
++                      | NAND_BBT_2BIT | NAND_BBT_VERSION,
++      .maxblocks = 2,
++      .len = 2,
++      .offs = 0,
++      .pattern = scan_ff_pattern,
++};
++
++static struct nand_bbt_descr monahans_bbt_main = {
++      .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
++                      | NAND_BBT_2BIT | NAND_BBT_VERSION,
++      .veroffs = 6,
++      .maxblocks = 2,
++        .offs = 2,
++        .len = 4,
++        .pattern = scan_main_bbt_pattern,
++};
++
++static struct nand_bbt_descr monahans_bbt_mirror = {
++      .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
++                      | NAND_BBT_2BIT | NAND_BBT_VERSION,
++      .veroffs = 6,
++      .maxblocks = 2,
++        .offs = 2,
++        .len = 4,
++        .pattern = scan_mirror_bbt_pattern,
++};
++
++#if 0
++static struct nand_bbt_descr monahans_bbt_main = {
++      .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
++                      | NAND_BBT_2BIT | NAND_BBT_VERSION,
++      .veroffs = 2,
++      .maxblocks = 2,
++        .offs =               0x0,
++        .len =                        2,
++        .pattern =            scan_ff_pattern
++};
++static struct nand_bbt_descr monahans_bbt_mirror = {
++      .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
++                      | NAND_BBT_2BIT | NAND_BBT_VERSION,
++      .veroffs = 2,
++      .maxblocks = 2,
++        .offs = 0x0,
++        .len = 2,
++        .pattern = scan_ff_pattern
++};
++#endif
++
++static struct nand_ecclayout monahans_lb_nand_oob = {
++      .eccbytes = 24,
++      .eccpos = {
++              40, 41, 42, 43, 44, 45, 46, 47,
++              48, 49, 50, 51, 52, 53, 54, 55,
++              56, 57, 58, 59, 60, 61, 62, 63},
++      .oobfree = { {2, 38} }
++};
++
++/*
++ * Monahans OOB size is only 8 bytes, and the rest 8 bytes is controlled by
++ * hardware for ECC. We construct virutal ECC buffer. Acutally, ECC is 6 bytes
++ * and the remain 2 bytes are reserved.
++ */
++static struct nand_ecclayout monahans_sb_nand_oob = {
++      .eccbytes = 6,
++      .eccpos = {8, 9, 10, 11, 12, 13 },
++      .oobfree = { {2, 6} }
++};
++
++
++static inline int is_buf_blank(u8 * buf, int size)
++{
++      int i = 0;
++      while(i < size) {
++              if (*((unsigned long *)(buf + i)) != 0xFFFFFFFF)
++                      return 0;
++              i += 4;
++      }
++      if (i > size) {
++              i -= 4;
++              while( i < size) {
++                      if(*(buf + i) != 0xFF)
++                              return 0;
++                      i++;
++              }
++      }
++      return 1;
++}
++
++static void print_buf(char *buf, int num)
++{
++      int i = 0;
++
++      while (i < num) {
++              printk(KERN_ERR "0x%08x: %02x %02x %02x %02x %02x %02x %02x"
++              " %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
++              (unsigned int) (i),  buf[i], buf[i+1], buf[i+2],
++              buf[i+3], buf[i+4], buf[i+5], buf[i+6], buf[i+7],
++              buf[i+8], buf[i+9], buf[i+10],buf[i+11], buf[i+12],
++              buf[i+13], buf[i+14], buf[i+15]);
++              i += 16;
++      }
++}
++
++static int inline enable_dfc_dma(struct dfc_context *context, int enable)
++{
++      int ret = dfc_mode.enable_dma;
++      unsigned long ndcr;
++
++      if (!enable) {
++              ndcr = dfc_read(context, DFC_NDCR);
++              ndcr &= ~NDCR_DMA_EN;
++              dfc_write(context, DFC_NDCR, ndcr);
++              dfc_mode.enable_dma = 0;
++      } else {
++              ndcr = dfc_read(context, DFC_NDCR);
++              ndcr |= NDCR_DMA_EN;
++              dfc_write(context, DFC_NDCR, ndcr);
++              dfc_mode.enable_dma = 1;
++      }
++      return ret;
++}
++
++
++static void inline dump_info(struct monahans_dfc_info *info)
++{
++      if (!info)
++              return;
++
++      printk(KERN_ERR "cmd:0x%x; addr:0x%x; retcode:%d; state:%d \n",
++              info->cmd, info->addr, info->retcode, info->state);
++}
++
++static void inline  enable_hw_ecc(struct dfc_context* context, int enable)
++{
++      unsigned long ndcr;
++
++      if (!enable) {
++              ndcr = dfc_read(context, DFC_NDCR);
++              ndcr &= ~NDCR_ECC_EN;
++              dfc_write(context, DFC_NDCR, ndcr);
++              dfc_mode.enable_ecc = 0;
++      }
++      else {
++              ndcr = dfc_read(context, DFC_NDCR);
++              ndcr |= NDCR_ECC_EN;
++              dfc_write(context, DFC_NDCR, ndcr);
++              dfc_mode.enable_ecc = 1;
++      }
++}
++
++/*
++ * Now, we are not sure that the NDSR_RDY mean the flash is ready.
++ * Need more test.
++ */
++static int monahans_df_dev_ready(struct mtd_info *mtd)
++{
++      struct monahans_dfc_info *info = (struct monahans_dfc_info *)
++                              (((struct nand_chip *)(mtd->priv))->priv);
++
++      struct dfc_context* context = info->context;
++
++      return ((dfc_read(context, DFC_NDSR) & NDSR_RDY));
++}
++
++/* each read, we can only read 4bytes from NDDB, we must buffer it */
++static u_char monahans_df_read_byte(struct mtd_info *mtd)
++{
++      char retval = 0xFF;
++      struct monahans_dfc_info *info = (struct monahans_dfc_info *)
++                              (((struct nand_chip *)(mtd->priv))->priv);
++
++      if (info->column < info->buf_count) {
++              /* Has just send a new command? */
++              retval = info->data_buf[info->column++];
++      }
++      return retval;
++}
++
++static void monahans_df_write_byte(struct mtd_info *mtd, u8 byte)
++{
++      struct monahans_dfc_info *info = (struct monahans_dfc_info *)
++                              (((struct nand_chip *)(mtd->priv))->priv);
++      info->data_buf[info->column++] = byte;
++}
++
++static u16 monahans_df_read_word(struct mtd_info *mtd)
++{
++      u16 retval = 0xFFFF;
++      struct monahans_dfc_info *info = (struct monahans_dfc_info *)
++                              (((struct nand_chip *)(mtd->priv))->priv);
++
++      if (!(info->column & 0x01) && info->column < info->buf_count) {
++              retval = *((u16 *)(info->data_buf+info->column));
++              info->column += 2;
++      }
++      return retval;
++}
++
++static void monahans_df_write_word(struct mtd_info *mtd, u16 word)
++{
++      struct monahans_dfc_info *info = (struct monahans_dfc_info *)
++                              (((struct nand_chip *)(mtd->priv))->priv);
++
++      if (!(info->column & 0x01) && info->column < info->buf_count) {
++              *((u16 *)(info->data_buf+info->column)) = word;
++              info->column += 2;
++      }
++}
++
++static void monahans_df_read_buf(struct mtd_info *mtd, u_char *buf, int len)
++{
++      struct monahans_dfc_info *info = (struct monahans_dfc_info *)
++                              (((struct nand_chip *)(mtd->priv))->priv);
++      int real_len = min((unsigned int)len, info->buf_count - info->column);
++
++      memcpy(buf, info->data_buf + info->column, real_len);
++      info->column += real_len;
++}
++
++static void monahans_df_write_buf(struct mtd_info *mtd,
++              const u_char *buf, int len)
++{
++      struct monahans_dfc_info *info = (struct monahans_dfc_info *)
++                              (((struct nand_chip *)(mtd->priv))->priv);
++      int real_len = min((unsigned int)len, info->buf_count - info->column);
++
++      memcpy(info->data_buf + info->column, buf, real_len);
++      info->column += real_len;
++}
++
++static int monahans_df_verify_buf(struct mtd_info *mtd,
++              const u_char *buf, int len)
++{
++      return 0;
++}
++
++#ifdef CONFIG_MTD_NAND_MONAHANS_DMA
++static void monahans_dfc_cmd_dma_irq(int channel, void *data,
++              struct pt_regs *regs)
++{
++      unsigned int dcsr;
++      struct monahans_dfc_info *info = (struct monahans_dfc_info *)data;
++      struct dfc_context* context = info->context;
++      struct dfc_mode* dfc_mode = context->dfc_mode;
++      unsigned int intm;
++
++      dcsr = DCSR(channel);
++      DCSR(channel) = dcsr;
++
++      intm = (dfc_mode->chip_select) ? \
++              (NDSR_CS1_BBD | NDSR_CS1_CMDD) : (NDSR_CS0_BBD | NDSR_CS0_CMDD);
++
++      D1(printk("cmd dma interrupt, channel:%d, DCSR:0x%08x\n", \
++                      channel, dcsr));
++
++      if (dcsr & DCSR_BUSERR) {
++              info->retcode = ERR_DMABUSERR;
++              complete(&info->cmd_complete);
++      } else {
++              if ((info->cmd == NAND_CMD_READ0) ||
++                              (info->cmd == NAND_CMD_READOOB)|| \
++                              (info->cmd == NAND_CMD_READID) || \
++                              (info->cmd == NAND_CMD_STATUS)) {
++                      dfc_enable_int(context, NDSR_RDDREQ | NDSR_DBERR);
++              } else if (info->cmd == NAND_CMD_PAGEPROG)
++                      dfc_enable_int(context, NDSR_WRDREQ);
++              else if (info->cmd == NAND_CMD_ERASE1)
++                      dfc_enable_int(context, intm);
++      }
++
++      return;
++}
++
++
++static void monahans_dfc_data_dma_irq(int channel, void *data,
++              struct pt_regs *regs)
++{
++      unsigned int dcsr, intm;
++      struct monahans_dfc_info *info = (struct monahans_dfc_info *)data;
++      struct dfc_context* context = info->context;
++      struct dfc_mode* dfc_mode = context->dfc_mode;
++
++      dcsr = DCSR(channel);
++      DCSR(channel) = dcsr;
++
++      intm = (dfc_mode->chip_select) ? \
++              (NDSR_CS1_BBD | NDSR_CS1_CMDD) : (NDSR_CS0_BBD | NDSR_CS0_CMDD);
++
++      D1(printk("data dma interrupt, channel:%d, DCSR:0x%08x\n",
++                      channel, dcsr));
++      if (dcsr & DCSR_BUSERR) {
++              info->retcode = ERR_DMABUSERR;
++              complete(&info->cmd_complete);
++      }
++
++      if (info->cmd == NAND_CMD_PAGEPROG) {
++              /* DMA interrupt may be interrupted by other IRQs*/
++              info->state = STATE_DMA_DONE;
++              dfc_enable_int(context, intm);
++      } else {
++              info->state = STATE_READY;
++              complete(&info->cmd_complete);
++      }
++
++}
++#endif
++
++static irqreturn_t monahans_dfc_irq(int irq, void *devid)
++{
++      unsigned int status, event, intm, cmd;
++      struct monahans_dfc_info *info = (struct monahans_dfc_info *)devid;
++      struct dfc_context* context = info->context;
++      struct dfc_mode* dfc_mode = context->dfc_mode;
++
++      intm =  (dfc_mode->chip_select) ? \
++              (NDSR_CS1_BBD | NDSR_CS1_CMDD) : (NDSR_CS0_BBD | NDSR_CS0_CMDD);
++      event = (dfc_mode->chip_select) ? \
++              (NDSR_CS1_BBD | NDSR_CS1_CMDD) : (NDSR_CS0_BBD | NDSR_CS0_CMDD);
++
++      status = dfc_read(context, DFC_NDSR);
++      D1(printk("DFC irq, NDSR:0x%x\n", status));
++      if (status & (NDSR_RDDREQ | NDSR_DBERR)) {
++              if (status & NDSR_DBERR) {
++                      info->retcode = ERR_DBERR;
++              }
++
++              dfc_disable_int(context, NDSR_RDDREQ | NDSR_DBERR);
++              dfc_clear_int(context, NDSR_RDDREQ | NDSR_DBERR);
++              if (info->cmd == NAND_CMD_READID)
++                      cmd = context->flash_info->read_id;
++              else if (info->cmd == NAND_CMD_STATUS)
++                      cmd = context->flash_info->read_status;
++              else if (info->cmd == NAND_CMD_READ0 ||
++                              info->cmd == NAND_CMD_READOOB)
++                      cmd = context->flash_info->read1;
++              else {
++                      printk(KERN_ERR "No according command:0x%x happens\n",
++                                      info->cmd);
++                      goto out;
++              }
++#ifdef CONFIG_MTD_NAND_MONAHANS_DMA
++              info->state = STATE_DMA_TRANSFER;
++              dfc_start_data_dma(context,
++                              (struct pxa_dma_desc*)info->data_desc_addr);
++#else
++              info->state = STATE_DATA_TRANSFER;
++              complete(&info->cmd_complete);
++#endif
++      } else if (status & NDSR_WRDREQ) {
++              dfc_disable_int(context, NDSR_WRDREQ);
++              dfc_clear_int(context, NDSR_WRDREQ);
++#ifdef CONFIG_MTD_NAND_MONAHANS_DMA
++              info->state = STATE_DMA_TRANSFER;
++              dfc_start_data_dma(context,
++                              (struct pxa_dma_desc*)info->data_desc_addr);
++#else
++              info->state = STATE_DATA_TRANSFER;
++              complete(&info->cmd_complete);
++#endif
++      } else if (status & event) {
++              if (status & NDSR_CS0_BBD) {
++                      info->retcode = ERR_BBERR;
++              }
++
++              dfc_disable_int(context, intm);
++              dfc_clear_int(context, event);
++              info->state = STATE_READY;
++              complete(&info->cmd_complete);
++      }
++out:
++      return IRQ_HANDLED;
++}
++
++static int dfc_send_command(struct mtd_info *mtd, unsigned int cmd,
++                              unsigned int addr, unsigned int num_pages,
++                              unsigned int event)
++{
++
++      struct monahans_dfc_info *info = (struct monahans_dfc_info *)
++                      (((struct nand_chip *)(mtd->priv))->priv);
++      struct dfc_context* context = info->context;
++      int status;
++      int ret;
++
++      D1(printk("ready send command, cmd:0x%x, at address:0x%x,"
++              " num_pages:%d, wait event:0x%x\n", cmd, addr, num_pages, event));
++
++      info->state = STATE_CMD_SEND;
++#ifdef CONFIG_MTD_NAND_MONAHANS_DMA
++      status = dfc_setup_cmd_dma(context, cmd, addr, num_pages,
++                      (uint32_t *)info->cmd_buf, info->cmd_buf_addr,
++                      DDADR_STOP, DCMD_ENDIRQEN, info->cmd_desc);
++#else
++      status = dfc_send_cmd(context, cmd, addr, num_pages);
++#endif
++      if (status) {
++              info->retcode = ERR_SENDCMD;
++              dfc_stop(context);
++              udelay(20);
++              printk(KERN_ERR "fail send command\n");
++              return info->retcode;
++      }
++      info->state = STATE_CMD_HANDLE;
++#ifdef CONFIG_MTD_NAND_MONAHANS_DMA
++      dfc_setup_data_dma(context, cmd, info->data_buf_addr,
++                      DDADR_STOP, DCMD_ENDIRQEN, info->data_desc);
++      dfc_start_cmd_dma(context, (struct pxa_dma_desc*)info->cmd_desc_addr);
++#endif
++#ifndef CONFIG_MTD_NAND_MONAHANS_DMA
++      dfc_enable_int(context, event);
++#endif
++      ret = wait_for_completion_timeout(&info->cmd_complete, 2*HZ);
++      if (!ret){
++              printk(KERN_ERR "Command time out\n");
++              dump_info(info);
++      }
++      D1(printk("command return, cmd:0x%x, retcode:%d\n",
++                      info->cmd, info->retcode));
++      return 0;
++}
++
++static void monahans_df_command(struct mtd_info *mtd, unsigned command,
++              int column, int page_addr )
++{
++      struct nand_chip *this = (struct nand_chip *)(mtd->priv);
++      struct monahans_dfc_info *info =
++                      (struct monahans_dfc_info *)(this->priv);
++      struct dfc_context *context = info->context;
++      struct dfc_flash_info * flash_info = context->flash_info;
++      int ret, pages_shift;
++      int status;
++#ifndef CONFIG_MTD_NAND_MONAHANS_DMA
++      int datasize;
++              int paddingsize;
++#endif
++      unsigned int to;
++
++      D1(printk("command:0x%x at address:0x%x, column:0x%x\n",
++                      command, page_addr, column));
++
++      if (info->state != STATE_READY) {
++              printk(KERN_ERR "CHIP is not ready.\n");
++              dump_info(info);
++              info->retcode = ERR_BUSY;
++              return;
++      }
++      info->retcode = ERR_NONE;
++      pages_shift = this->phys_erase_shift - this->page_shift;
++      if (info->table_init) {
++              to = search_rel_block((page_addr >> pages_shift), mtd);
++      if (to) {
++                      page_addr = (to << pages_shift) | (page_addr
++                                      & ((1 << pages_shift) - 1));
++              }
++      }
++
++      switch ( command ) {
++      case NAND_CMD_READOOB:
++              /*
++               * DFC has mark the last 8 bytes OOB data if HARDEARE_ECC is
++               * enabled. We must first disable the HARDWARE_ECC for getting
++               * all the 16 bytes OOB
++               */
++              enable_hw_ecc(context, 0);
++              info->buf_count = mtd->writesize + mtd->oobsize;
++              info->column = mtd->writesize + column;
++              info->cmd = command;
++              info->addr = page_addr << this->page_shift;
++              ret = dfc_send_command(mtd, flash_info->read1, info->addr,
++                              1, NDSR_RDDREQ | NDSR_DBERR);
++#ifndef CONFIG_MTD_NAND_MONAHANS_DMA
++              dfc_get_pattern(info->context, flash_info->read1, &datasize,
++                              &paddingsize);
++              dfc_read_fifo_partial(info->context, info->data_buf,
++                              min(info->buf_count, datasize), datasize);
++              info->state = STATE_READY;
++#endif
++              /* We only are OOB, so if the data has error, does not matter */
++              if (info->retcode == ERR_DBERR)
++                      info->retcode = ERR_NONE;
++              enable_hw_ecc(context, 1);
++              break;
++
++      case NAND_CMD_READ0:
++              enable_hw_ecc(context, 1);
++              info->column = column;
++              info->cmd = command;
++              info->buf_count = mtd->writesize + mtd->oobsize;
++              memset(info->data_buf, 0xFF, info->buf_count);
++              info->addr = page_addr << this->page_shift;
++
++              ret = dfc_send_command(mtd, flash_info->read1, info->addr,
++                              1, NDSR_RDDREQ | NDSR_DBERR);
++#ifndef CONFIG_MTD_NAND_MONAHANS_DMA
++              dfc_get_pattern(info->context, flash_info->read1, &datasize,
++                              &paddingsize);
++              dfc_read_fifo_partial(info->context, info->data_buf,
++                              min(info->buf_count, datasize), datasize);
++              info->state = STATE_READY;
++#endif
++              /* When the data buf is blank, the DFC will report DB error */
++              if (info->retcode == ERR_DBERR && is_buf_blank(info->data_buf,
++                              mtd->writesize))
++                      info->retcode = ERR_NONE;
++
++              if (info->retcode == ERR_DBERR) {
++                      printk(KERN_ERR "DB error at address 0x%x\n",
++                              info->addr);
++                      print_buf(info->data_buf, info->buf_count);
++              }
++              break;
++      case NAND_CMD_SEQIN:
++              /* Write only OOB? */
++
++              info->cmd = command;
++              if (column >= mtd->writesize) {
++                      info->buf_count = mtd->writesize + mtd->oobsize;
++                      enable_hw_ecc(context, 0);
++              } else {
++                      info->buf_count = mtd->writesize + mtd->oobsize;
++                      enable_hw_ecc(context, 1);
++              }
++              memset(info->data_buf, 0xFF, mtd->writesize + mtd->oobsize);
++              info->column = column;
++              info->addr = page_addr << this->page_shift;
++              break;
++      case NAND_CMD_PAGEPROG:
++              /* prevois command is NAND_CMD_SEIN ?*/
++              if (info->cmd != NAND_CMD_SEQIN) {
++                      info->cmd = command;
++                      info->retcode = ERR_SENDCMD;
++                      printk(KERN_ERR "Monahans NAND device: "
++                              "No NAND_CMD_SEQIN executed before.\n");
++                      enable_hw_ecc(context, 1);
++                      break;
++              }
++              info->cmd = command;
++              ret = dfc_send_command(mtd, flash_info->program, info->addr,
++                              1, NDSR_WRDREQ);
++
++#ifndef CONFIG_MTD_NAND_MONAHANS_DMA
++              if (ret != 0)
++                      break;
++
++              dfc_get_pattern(info->context, flash_info->program, &datasize,
++                              &paddingsize);
++              dfc_write_fifo_partial(info->context, info->data_buf, datasize,
++                              datasize);
++
++              if (info->context->dfc_mode->chip_select)
++                      dfc_enable_int(info->context,
++                              NDSR_CS1_BBD | NDSR_CS1_CMDD);
++              else
++                      dfc_enable_int(info->context,
++                              NDSR_CS0_BBD | NDSR_CS0_CMDD);
++
++              ret = wait_for_completion_timeout(&info->cmd_complete, 2*HZ);
++              if (!ret){
++                      printk(KERN_ERR "Programm Command time out\n");
++                      dump_info(info);
++              }
++
++              if (info->retcode == ERR_BBERR) {
++                      mtd->block_markbad(mtd, info->addr);
++              }
++#endif
++              break;
++      case NAND_CMD_ERASE1:
++              info->cmd = command;
++              info->addr = (page_addr >> pages_shift) << this->phys_erase_shift;
++
++              if (info->context->dfc_mode->chip_select)
++                      ret = dfc_send_command(mtd, flash_info->erase,
++                              info->addr, 0, NDSR_CS1_BBD | NDSR_CS1_CMDD);
++              else
++                      ret = dfc_send_command(mtd, flash_info->erase,
++                              info->addr, 0, NDSR_CS0_BBD | NDSR_CS0_CMDD);
++
++              if (info->retcode == ERR_BBERR) {
++                      mtd->block_markbad(mtd, info->addr);
++              }
++              break;
++      case NAND_CMD_ERASE2:
++              break;
++      case NAND_CMD_READID:
++              info->cmd = command;
++              info->buf_count = flash_info->read_id_bytes;
++              info->column = 0;
++              info->addr = 0xFFFFFFFF;
++              ret = dfc_send_command(mtd, flash_info->read_id, info->addr,
++                              0, NDSR_RDDREQ);
++#ifndef CONFIG_MTD_NAND_MONAHANS_DMA
++              dfc_get_pattern(info->context, flash_info->read_id, &datasize,
++                              &paddingsize);
++              dfc_read_fifo_partial(info->context, info->data_buf,
++                              info->buf_count, datasize);
++              info->state = STATE_READY;
++#endif
++              D1(printk("ReadID, [1]:0x%x, [2]:0x%x\n",
++                      info->data_buf[0], info->data_buf[1]));
++              break;
++      case NAND_CMD_STATUS:
++              info->cmd = command;
++              info->buf_count = 1;
++              info->column = 0;
++              info->addr = 0xFFFFFFFF;
++              ret = dfc_send_command(mtd, flash_info->read_status,
++                      info->addr, 0, NDSR_RDDREQ);
++#ifndef CONFIG_MTD_NAND_MONAHANS_DMA
++              dfc_get_pattern(info->context, flash_info->read_status,
++                      &datasize, &paddingsize);
++              dfc_read_fifo_partial(info->context, info->data_buf,
++                      info->buf_count, datasize);
++              info->state = STATE_READY;
++#endif
++              break;
++
++      case NAND_CMD_RESET:
++              status = dfc_reset_flash(&dfc_context);
++              if (status) {
++                      printk(KERN_WARNING "Monahans NAND device:"
++                              "NAND_CMD_RESET error\n");
++              }
++              break;
++      default:
++              printk(KERN_WARNING "Monahans NAND device:"
++                      "Non-support the command.\n");
++              break;
++      }
++
++      if (info->retcode != ERR_NONE)
++              dfc_stop(info->context);
++}
++
++static void monahans_df_select_chip(struct mtd_info *mtd, int chip)
++{
++      struct monahans_dfc_info *info = (struct monahans_dfc_info *)
++                      (((struct nand_chip *)(mtd->priv))->priv);
++
++      if (chip <= MAX_CHIP)
++              info->context->dfc_mode->chip_select = chip;
++      else
++              printk(KERN_ERR "Monahans NAND device:"
++                      "not select the NAND chips!\n");
++}
++
++static int monahans_df_waitfunc(struct mtd_info *mtd,
++              struct nand_chip *this)
++{
++      struct monahans_dfc_info *info = (struct monahans_dfc_info *)
++                      (((struct nand_chip *)(mtd->priv))->priv);
++
++      /* monahans_df_send_command has waited for command complete */
++      if (this->state == FL_WRITING || this->state == FL_ERASING) {
++              if (info->retcode == ERR_NONE)
++                      return 0;
++              else {
++                      /*
++                       * any error make it return 0x01 which will tell
++                       * the caller the erase and write fail
++                       */
++                      return 0x01;
++              }
++      }
++
++      return 0;
++}
++
++static int monahans_df_calculate_ecc(struct mtd_info *mtd,
++              const u_char *dat, u_char *ecc_code)
++{
++      return 0;
++}
++
++static int monahans_df_correct_data(struct mtd_info *mtd,
++              u_char *dat, u_char *read_ecc, u_char *calc_ecc)
++{
++      struct monahans_dfc_info *info = (struct monahans_dfc_info *)
++                      (((struct nand_chip *)(mtd->priv))->priv);
++
++      /*
++       * Any error include ERR_SEND_CMD, ERR_DBERR, ERR_BUSERR, we
++       * consider it as a ecc error which will tell the caller the
++       * read fail We have distinguish all the errors, but the
++       * nand_read_ecc only check this function return value
++       */
++      if (info->retcode != ERR_NONE)
++              return -1;
++
++      return 0;
++}
++
++static void monahans_df_enable_hwecc(struct mtd_info *mtd, int mode)
++{
++      return;
++}
++
++/*
++ * The relocation table management is different between MOBM V2 and V3.
++ *
++ * MOBM V2 is applied on chips taped out before MhnLV A0.
++ * MOBM V3 is applied on chips taped out after MhnLV A0. It's also applied
++ * on MhnLV A0.
++ */
++static int calc_obm_ver(void)
++{
++      unsigned int    cpuid;
++      /* read CPU ID */
++      __asm__ (
++              "mrc p15, 0, %0, c0, c0, 0\n"
++              : "=r" (cpuid)
++      );
++      /* It's not xscale chip. */
++      if ((cpuid & 0xFFFF0000) != 0x69050000)
++              return MHN_OBM_INVAL;
++      /* It's MhnP Ax */
++      if ((cpuid & 0x0000FFF0) == 0x00006420)
++              return MHN_OBM_V2;
++      /* It's MhnP Bx */
++      if ((cpuid & 0x0000FFF0) == 0x00006820) {
++              if ((cpuid & 0x0F) <= 5)
++                      return MHN_OBM_V2;
++              else
++                      return MHN_OBM_V3;
++      }
++      /* It's MhnL Ax */
++      if ((cpuid & 0x0000FFF0) == 0x00006880) {
++              if ((cpuid & 0x0F) == 0)
++                      return MHN_OBM_V2;
++              else
++                      return MHN_OBM_V3;
++      }
++      /* It's MhnLV Ax */
++      if ((cpuid & 0x0000FFF0) == 0x00006890)
++              return MHN_OBM_V3;
++      return MHN_OBM_INVAL;
++}
++
++
++/*
++ * MOBM maintains a relocation table. It's used to replace bad blocks.
++ * If block A is bad, it will use block B instead.
++ * There're 127 relocated blocks. All of them reside in the bottom of NAND
++ * flash. So they're reserved and can't be calculated in mtd size and chip
++ * size.
++ */
++static int read_reloc_table(struct mtd_info *mtd)
++{
++      struct nand_chip *this = NULL;
++      struct monahans_dfc_info *info = NULL;
++      struct dfc_context *context = NULL;
++      struct reloc_table *table = NULL;
++      int page, maxslot;
++      int obm, valid;
++
++      obm = calc_obm_ver();
++      this = (struct nand_chip *)(mtd->priv);
++      info = (struct monahans_dfc_info *)(this->priv);
++      context = info->context;
++
++      mtd->size -= (NAND_RELOC_MAX * mtd->erasesize);
++      this->chipsize -= (NAND_RELOC_MAX << this->phys_erase_shift);
++      page = (1 << (this->phys_erase_shift - this->page_shift)) - 1;
++
++      this->select_chip(mtd, 0);
++      valid = 0;
++      if (obm == MHN_OBM_V2) {
++              /* On MOBM V2, the relocation table resides in the last page
++               * of the first block.
++               */
++              memset(info->data_buf, 0, BUFLEN);
++              monahans_df_command(mtd, NAND_CMD_READ0, 0, page);
++      memcpy(((unsigned char *)&(info->table)), info->data_buf,
++                      sizeof(struct reloc_table));
++              if (info->table.header == NAND_RELOC_HEADER)
++                      valid = 1;
++      } else if (obm == MHN_OBM_V3) {
++              /* On MOBM V3, there're several relocation tables in the first
++               * block.
++               * When new bad blocks are found, a new relocation table will
++               * be generated and written back to the first block. But the
++               * original relocation table won't be erased. Even if the new
++               * relocation table is written wrong, system can still find an
++               * old one.
++               * One page contains one slot.
++               */
++              maxslot = 1 << (this->phys_erase_shift - this->page_shift);
++              page = maxslot - MAX_BBT_SLOTS;
++              for (; page < maxslot; page++) {
++                      monahans_df_command(mtd, NAND_CMD_READ0, 0, page);
++                      table = (struct reloc_table *)info->data_buf;
++                      if (info->retcode == ERR_NONE) {
++                              if (table->header != NAND_RELOC_HEADER) {
++                                      continue;
++      } else {
++                                      memcpy(((unsigned char *)&(info->table)),
++                                              table, sizeof(struct reloc_table));
++                                      valid = 1;
++                                      break;
++                              }
++                      }
++      }
++
++      } else {
++              printk(KERN_ERR "The version of MOBM isn't supported\n");
++      }
++      if (valid) {
++              memcpy(((unsigned char *)&(info->table)), info->data_buf,
++                      sizeof(struct reloc_table));
++              printk(KERN_DEBUG "relocation table at page:%d\n", page);
++              PRINT_BUF((unsigned char *)&(info->table),
++                      sizeof(struct reloc_table));
++      info->table_init = 1;
++      } else {
++              /* There should be a valid relocation table slot at least. */
++              printk(KERN_ERR "NO VALID relocation table can be \
++                              recognized\n");
++              printk(KERN_ERR "CAUTION: It may cause unpredicated error\n");
++              printk(KERN_ERR "Please re-initialize the NAND flash.\n");
++              memset((unsigned char *)&(info->table), 0,
++                              sizeof(struct reloc_table));
++              info->table_init = 0;
++              return -EINVAL;
++      }
++      return 0;
++}
++
++/* add the relocation entry into the relocation table
++ * It's valid on MOBM V3.
++ * If the relocated block is bad, an new entry will be added into the
++ * bottom of the relocation table.
++ */
++static int update_rel_table(struct mtd_info *mtd, int block)
++{
++      struct nand_chip *this = NULL;
++      struct monahans_dfc_info *info = NULL;
++      struct reloc_table *table = NULL;
++      int obm, reloc_block;
++
++      this = (struct nand_chip *)(mtd->priv);
++      info = (struct monahans_dfc_info *)(this->priv);
++      obm = calc_obm_ver();
++      if (obm == MHN_OBM_V3) {
++              table = &info->table;
++              if (info->table_init == 0) {
++                      printk(KERN_ERR "Error: the initial relocation \
++                                      table can't be read\n");
++                      memset(table, 0, sizeof(struct reloc_table));
++                      table->header = NAND_RELOC_HEADER;
++                      info->table_init = 1;
++              }
++              if (table->total == 0) {
++                      /* Point to the first relocated block.
++                       * It resides in the last block of flash.
++                       * the relocation entry has calculated in
++                       * chipsize
++                       */
++                      reloc_block = (this->chipsize
++                                      >> this->phys_erase_shift)
++                                      + NAND_RELOC_MAX - 1;
++              } else if (table->total < NAND_RELOC_MAX) {
++                      reloc_block = table->reloc[table->total - 1].to - 1;
++              } else {
++                      printk(KERN_ERR "Relocation table exceed max number, \
++                              cannot mark block 0x%x as bad block\n", block);
++                      return -ENOSPC;
++              }
++              /* Make sure that reloc_block is pointing to a valid block */
++              for (; ; reloc_block--) {
++                      /* The relocate table is full */
++                      if (reloc_block < (this->chipsize
++                                      >> this->phys_erase_shift))
++                              return -ENOSPC;
++                      this->cmdfunc(mtd, NAND_CMD_ERASE1, 0, reloc_block
++                                      << (this->phys_erase_shift
++                                      - this->page_shift));
++                      if (info->retcode == ERR_NONE)
++                              break;
++              }
++              /* Create the relocated block information in the table */
++              table->reloc[table->total].from = block;
++              table->reloc[table->total].to = reloc_block;
++              table->total++;
++      }
++      return 0;
++}
++
++/* Write the relocation table back to device, if there's room. */
++static int sync_rel_table(struct mtd_info *mtd, int *idx)
++{
++      struct nand_chip *this = NULL;
++      struct monahans_dfc_info *info = NULL;
++      int obm, start_page, len;
++
++      if (*idx >= MAX_BBT_SLOTS) {
++              printk(KERN_ERR "Can't write relocation table to device \
++                              any more.\n");
++              return -1;
++      }
++      if (*idx < 0) {
++              printk(KERN_ERR "Wrong Slot is specified.\n");
++              return -1;
++      }
++      this = (struct nand_chip *)(mtd->priv);
++      info = (struct monahans_dfc_info *)(this->priv);
++      len = 4;
++      len += info->table.total << 2;
++      obm = calc_obm_ver();
++      if (obm == MHN_OBM_V3) {
++              /* write to device */
++              start_page = 1 << (this->phys_erase_shift - this->page_shift);
++              start_page = start_page - 1 - *idx;
++              memset(&(info->data_buf), 0xFF, BUFLEN);
++              memcpy(&(info->data_buf), &(info->table), len);
++
++              printk(KERN_DEBUG "DUMP relocation table before write. \
++                              page:0x%x\n", start_page);
++              monahans_df_command(mtd, NAND_CMD_SEQIN, 0, start_page);
++              monahans_df_command(mtd, NAND_CMD_PAGEPROG, 0, start_page);
++              /* write to idx */
++              (*idx)++;
++              /* dump it */
++              memset(&(info->data_buf), 0, BUFLEN);
++              monahans_df_command(mtd, NAND_CMD_READOOB, 0, start_page);
++              PRINT_BUF(info->data_buf, len);
++      }
++      return 0;
++}
++
++
++/* Find the relocated block of the bad one.
++ * If it's a good block, return 0. Otherwise, return a relocated one.
++ * idx points to the next relocation entry
++ * If the relocated block is bad, an new entry will be added into the
++ * bottom of the relocation table.
++ */
++static unsigned short search_rel_block(int block, struct mtd_info *mtd)
++{
++      struct nand_chip *this = NULL;
++      struct monahans_dfc_info *info = NULL;
++      struct reloc_table *table = NULL;
++      int i, max, reloc_block = 0;
++
++      this = (struct nand_chip *)(mtd->priv);
++      info = (struct monahans_dfc_info *)(this->priv);
++      table = &(info->table);
++      if ((block <= 0) || (block > this->chipsize)
++                      || (info->table_init == 0) || (table->total == 0))
++              return 0;
++      if (table->total > NAND_RELOC_MAX)
++              table->total = NAND_RELOC_MAX;
++      max = table->total;
++      for (i = 0; i < max; i++) {
++              if (block == table->reloc[i].from)
++                      reloc_block = table->reloc[i].to;
++      }
++      return reloc_block;
++}
++
++/*
++ * Check whether the block is a bad one.
++ * At first, it will search the relocation table.
++ * If necessary, it will search the BBT. Because relocation table can only
++ * maintain limited record. If there're more bad blocks, they can't be
++ * recorded in relocation table. They can only be recorded in BBT.
++ */
++static int monahans_df_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
++{
++      struct nand_chip *this = NULL;
++      int page, block, reloc_block, chipnr, res = 0;
++      u16 bad;
++
++      /* At here, we only support one flash chip */
++      this = (struct nand_chip *)mtd->priv;
++      block = (int)(ofs >> this->phys_erase_shift);
++      /* search the block in the relocation table */
++      reloc_block = search_rel_block(block, mtd);
++      if (reloc_block) {
++              ofs = ((reloc_block << this->phys_erase_shift) |
++                      (ofs & ((1 << this->phys_erase_shift) - 1)));
++      }
++
++      /* search BBT
++       * Maybe the relocation table is full, but some bad blocks aren't
++       * recordered in it.
++       * The below code are copied from nand_block_bad().
++       */
++      if (getchip) {
++              page = (int)(ofs >> this->page_shift);
++              chipnr = (int)(ofs >> this->chip_shift);
++
++              /* Select the NAND chips */
++              this->select_chip(mtd, chipnr);
++      } else
++              page = (int)ofs;
++
++      if (this->options & NAND_BUSWIDTH_16) {
++              this->cmdfunc(mtd, NAND_CMD_READOOB, this->badblockpos & 0xFE,
++                              page & this->pagemask);
++              bad = cpu_to_le16(this->read_word(mtd));
++              if (this->badblockpos & 0x1)
++                      bad >>= 1;
++              if ((bad & 0xFF) != 0xFF)
++                      res = 1;
++      } else {
++              this->cmdfunc(mtd, NAND_CMD_READOOB, this->badblockpos,
++                              page & this->pagemask);
++              if (this->read_byte(mtd) != 0xFF)
++                      res = 1;
++      }
++
++      return res;
++}
++
++static int monahans_df_block_markbad(struct mtd_info *mtd, loff_t ofs)
++{
++      struct nand_chip *this = NULL;
++      struct monahans_dfc_info *info = NULL;
++      unsigned char buf[2] = {0, 0};
++      int block, reloc_block, page, ret;
++
++      this = (struct nand_chip *)mtd->priv;
++      info = (struct monahans_dfc_info *)(this->priv);
++      /* Get block number */
++      block = ((int)ofs) >> this->bbt_erase_shift;
++      ret = update_rel_table(mtd, block);
++      if (!ret) {
++              sync_rel_table(mtd, &(info->current_slot));
++              return 0;
++              } else {
++              reloc_block = search_rel_block(block, mtd);
++              if (reloc_block)
++                      block = reloc_block;
++              if (this->bbt)
++                      this->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1);
++      }
++
++      /* Do we have a flash based bad block table ? */
++      if (this->options & NAND_USE_FLASH_BBT)
++              return nand_update_bbt(mtd, ofs);
++
++      /* mark the bad block flag at the first two pages */
++      page = block << (this->phys_erase_shift - this->page_shift);
++      ofs = mtd->writesize + this->badblockpos;
++      this->cmdfunc(mtd, NAND_CMD_SEQIN, ofs, page);
++      this->write_buf(mtd, buf, 2);
++      this->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
++      page++;
++      this->cmdfunc(mtd, NAND_CMD_SEQIN, ofs, page);
++      this->write_buf(mtd, buf, 2);
++      this->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
++      return 0;
++}
++
++static int dump_bbt_flash(struct mtd_info *mtd)
++{
++      struct nand_chip *this = NULL;
++      struct monahans_dfc_info *info = NULL;
++      int block, page, totlen;
++
++      this = (struct nand_chip *)mtd->priv;
++      info = (struct monahans_dfc_info *)this->priv;
++      block = (this->chipsize >> this->phys_erase_shift) - 1;
++      totlen = (this->chipsize >> this->phys_erase_shift) >> 2;
++      printk(KERN_ERR "totlen:0x%x\n", totlen);
++      this->select_chip(mtd, 0);
++      if (this->bbt_td) {
++              printk(KERN_ERR "BBT page:0x%x\n", this->bbt_td->pages[0]);
++              page = this->bbt_td->pages[0];
++              if (this->bbt_td->pages[0] <= 0) {
++                      page = block << (this->phys_erase_shift
++                              - this->page_shift);
++              }
++              while (totlen > 0) {
++                      printk(KERN_ERR "page:0x%x\n", page);
++                      monahans_df_command(mtd, NAND_CMD_READ0, 0, page);
++                      printk(KERN_ERR "read result:0x%x\n", info->retcode);
++                      PRINT_BUF(info->data_buf, BUFLEN);
++                      totlen -= (1 << this->page_shift);
++                      page++;
++              }
++      }
++      if (this->bbt_md) {
++              printk(KERN_ERR "BBT page:0x%x\n", this->bbt_md->pages[0]);
++              page = this->bbt_md->pages[0];
++              if (this->bbt_td->pages[0] <= 0) {
++                      page = block << (this->phys_erase_shift
++                              - this->page_shift);
++                      }
++              while (totlen > 0) {
++                      printk(KERN_ERR "page:0x%x\n", page);
++                      monahans_df_command(mtd, NAND_CMD_READ0, 0, page);
++                      printk(KERN_ERR "read result:0x%x\n", info->retcode);
++                      PRINT_BUF(info->data_buf, BUFLEN);
++                      totlen -= (1 << this->page_shift);
++                      page++;
++              }
++
++      }
++      return 0;
++}
++
++static int dump_bbt_mem(struct mtd_info *mtd)
++{
++      struct nand_chip *this = NULL;
++
++      this = (struct nand_chip *)mtd->priv;
++      PRINT_BUF(this->bbt, 225);
++      return 0;
++}
++
++static int monahans_df_scan_bbt(struct mtd_info *mtd)
++{
++      struct nand_chip *this = NULL;
++      int ret;
++
++      this = (struct nand_chip *)mtd->priv;
++      ret = read_reloc_table(mtd);
++      if (ret) {
++              printk(KERN_ERR "Failed to get relocation table\n");
++              printk(KERN_ERR "Try to build a new BBT. It may result \
++                              unpredicated error.\n");
++              /* Create new memory based and flash based BBT */
++      }
++      nand_scan_bbt(mtd, &monahans_bbt_default);
++      //dump_bbt_flash(mtd);
++      dump_bbt_mem(mtd);
++      return 0;
++#if 0
++      /* Read flashed based BBT from device */
++      return (nand_scan_bbt(mtd, &monahans_bbt_main));
++#endif
++}
++
++
++static int monahans_df_probe(struct platform_device *pdev)
++{
++      struct nand_chip *this;
++      struct monahans_dfc_info *info;
++      int status = -1;
++      unsigned int data_buf_len;
++#ifdef CONFIG_MTD_NAND_MONAHANS_DMA
++      unsigned int buf_len;
++#endif
++      int i, ret = 0;
++
++      printk(KERN_ERR "Nand driver probe\n");
++
++      dfc_context.membase = ioremap_nocache(0x43100000, 0x100000);
++      if (!dfc_context.membase)
++              printk(KERN_ERR "Couldn't ioremap\n");
++
++      pxa_set_cken(CKEN_NAND, 1);
++
++      for (i = DFC_FLASH_NULL + 1; i < DFC_FLASH_END; i++)
++      {
++              uint32_t id;
++
++              status = dfc_init(&dfc_context, i);
++              if (status)
++                      continue;
++              status = dfc_readid(&dfc_context, &id);
++              if (status)
++                      continue;
++              printk(KERN_DEBUG "id:0x%x, chipid:0x%x\n",
++                      id, dfc_context.flash_info->chip_id);
++              if (id == dfc_context.flash_info->chip_id)
++                      break;
++      }
++
++      if(i == DFC_FLASH_END) {
++              printk(KERN_ALERT "Monahans NAND device:"
++                      "Nand Flash initialize failure!\n");
++              ret = -ENXIO;
++              goto out;
++      }
++      flash_config = i;
++
++      monahans_mtd = kzalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip) +
++                      sizeof(struct monahans_dfc_info) , GFP_KERNEL);
++      if (!monahans_mtd) {
++              printk (KERN_ERR "Monahans NAND device:"
++                      "Unable to allocate NAND MTD device structure.\n");
++              ret = -ENOMEM;
++              goto out;
++        }
++
++      /* Get pointer to private data */
++      this = (struct nand_chip *)((void *)monahans_mtd + sizeof(struct mtd_info));
++      info = (struct monahans_dfc_info *)((void *)this + sizeof(struct nand_chip));
++      dfc_context.mtd = monahans_mtd;
++
++      monahans_mtd->priv = this;
++      this->priv = info;
++      data_buf_len = dfc_context.flash_info->page_size +
++              dfc_context.flash_info->oob_size;
++      info->state = STATE_READY;
++      init_completion(&info->cmd_complete);
++      info->table_init = 0;
++      memset(&info->table, 0x0, sizeof(struct reloc_table));
++      printk(KERN_DEBUG "%s: this->controller: 0x%x, &this->controller: 0x%x\n",__func__, (unsigned int)this->controller, (unsigned int)&(this->controller));
++#ifdef CONFIG_MTD_NAND_MONAHANS_DMA
++      info->dma_mask = 0xffffffffUL;
++
++      dev->dma_mask = &info->dma_mask;
++      dev->coherent_dma_mask = 0xffffffffUL;
++
++      /* alloc dma data buffer for data
++       * buffer + 2*descriptor + command buffer
++       */
++      buf_len = ALIGN(2*sizeof(struct pxa_dma_desc), 32) +
++              ALIGN(data_buf_len, 32) + ALIGN(NAND_CMD_DMA_LEN, 32);
++
++      printk(KERN_INFO "Try to allocate dma buffer(len:%d)"
++              "for data buffer + 2*descriptor + command buffer\n", buf_len);
++      info->data_desc = (struct pxa_dma_desc*)dma_alloc_writecombine(dev,
++                      buf_len, &info->data_desc_addr, GFP_KERNEL);
++      if (!info->data_desc) {
++              printk(KERN_ERR "Monahans NAND device:"
++                      "Unable to alloc dma buffer\n");
++              ret = -ENOMEM;
++              goto free_mtd;
++      }
++
++      info->cmd_desc = (struct pxa_dma_desc*)((char *)info->data_desc +
++                      sizeof(struct pxa_dma_desc));
++      info->cmd_desc_addr = (dma_addr_t)((char *)info->data_desc_addr +
++                      sizeof(struct pxa_dma_desc));
++      info->data_buf = (char *)info->data_desc +
++              ALIGN(2*sizeof(struct pxa_dma_desc), 32);
++      info->data_buf_addr = (dma_addr_t)((char *)info->data_desc_addr +
++              ALIGN(2*sizeof(struct pxa_dma_desc), 32));
++      info->cmd_buf = (char *)info->data_buf + ALIGN(data_buf_len, 32);
++      info->cmd_buf_addr = (dma_addr_t)((char *)info->data_buf_addr +
++                      ALIGN(data_buf_len, 32));
++
++      D1(printk("Get dma buffer for data dma descriptor, virt:0x%x, phys0x:%x\n",
++              (unsigned int)info->data_desc, info->data_desc_addr));
++      D1(printk("Get dma buffer for command dma descriptors, virt:0x%x,"
++              "phys0x:%x\n", (unsigned int)info->cmd_desc, info->cmd_desc_addr));
++      D1(printk("Get dma buffer for data, virt:0x%x, phys0x:%x\n",
++              (unsigned int)info->data_buf, info->data_buf_addr));
++      D1(printk("Get dma buffer for command, virt:0x%x, phys0x:%x\n",
++              (unsigned int)info->cmd_buf, info->cmd_buf_addr));
++
++      D1(printk("Try to allocate dma channel for data\n"));
++
++      info->data_dma = pxa_request_dma("NAND DATA", DMA_PRIO_LOW,
++                      monahans_dfc_data_dma_irq, info);
++      if (info->data_dma < 0) {
++              printk(KERN_ERR "Monahans NAND device:"
++                      "Unable to alloc dma channel for data\n");
++              ret = info->data_dma;
++              goto free_buf;
++      }
++      D1(printk("Get dma channel:%d for data\n", info->data_dma));
++
++      D1(printk("Try to allocate dma channel for command\n"));
++      info->cmd_dma = pxa_request_dma("NAND CMD", DMA_PRIO_LOW,
++                      monahans_dfc_cmd_dma_irq, info);
++      if (info->cmd_dma < 0) {
++              printk(KERN_ERR "Monahans NAND device:"
++                      "Unable to alloc dma channel for command\n");
++              ret = info->cmd_dma;
++              goto free_data_dma;
++      }
++      D1(printk("Get dma channel:%d for command\n", info->cmd_dma));
++
++      dfc_context.cmd_dma_ch  = info->cmd_dma;
++      dfc_context.data_dma_ch = info->data_dma;
++#else
++      printk(KERN_DEBUG "Try to allocate data buffer(len:%d)\n", data_buf_len);
++      info->data_buf = kmalloc(data_buf_len, GFP_KERNEL);
++      if (!info->data_buf) {
++              printk(KERN_ERR "Monahans NAND device:"
++                      "Unable to alloc data buffer\n");
++              ret = -ENOMEM;
++              goto free_mtd;
++      }
++#endif
++
++      D1(printk("Try to request irq:%d\n", IRQ_NAND));
++      ret = request_irq(IRQ_NAND, monahans_dfc_irq, 0, pdev->name, info);
++      if (ret < 0) {
++              printk(KERN_ERR "Monahans NAND device: Unable to request irq\n");
++#ifdef CONFIG_MTD_NAND_MONAHANS_DMA
++              goto free_cmd_dma;
++#else
++              goto free_buf;
++#endif
++      }
++
++      D1(printk("Success request irq\n"));
++
++      /* set address of NAND IO lines */
++      this->options = (dfc_context.flash_info->flash_width == 16)? \
++                      NAND_BUSWIDTH_16: 0 | NAND_USE_FLASH_BBT;
++
++      /* this->IO_ADDR_R = this->IO_ADDR_W = NDDB */
++      this->waitfunc = monahans_df_waitfunc;
++      this->select_chip = monahans_df_select_chip;
++      this->dev_ready = monahans_df_dev_ready;
++      this->cmdfunc = monahans_df_command;
++      this->read_word= monahans_df_read_word;
++      /*this->write_word= monahans_df_write_word;*/
++      this->read_byte = monahans_df_read_byte;
++      this->read_buf = monahans_df_read_buf;
++      this->write_buf = monahans_df_write_buf;
++      this->verify_buf = monahans_df_verify_buf;
++      this->ecc.hwctl = monahans_df_enable_hwecc;
++      this->ecc.calculate = monahans_df_calculate_ecc;
++      this->ecc.correct = monahans_df_correct_data;
++      this->block_bad = monahans_df_block_bad;
++      this->block_markbad = monahans_df_block_markbad;
++      this->scan_bbt = monahans_df_scan_bbt;
++      this->chip_delay= 25;
++      this->bbt_td = &monahans_bbt_main;
++      this->bbt_md = &monahans_bbt_mirror;
++
++      /* If the NAND flash is small block flash, only 512-byte pagesize
++       * is supported.
++       * Adjust parameters of BBT what is depended on large block nand
++       * flash or small block nand flash.
++       */
++      if (dfc_context.flash_info->oob_size > 16) {
++              this->ecc.layout = &monahans_lb_nand_oob;
++              this->ecc.mode = NAND_ECC_HW;
++              this->ecc.size = 2048;
++              this->ecc.bytes = 24;
++              this->bbt_td->offs = 2;
++              this->bbt_td->veroffs = 6;
++              this->bbt_md->offs = 2;
++              this->bbt_md->veroffs = 6;
++              this->badblockpos = NAND_LARGE_BADBLOCK_POS;
++              monahans_bbt_default.offs = NAND_LARGE_BADBLOCK_POS;
++              monahans_bbt_default.len = 2;
++              /* when scan_bbt() is executed, bbt version can get */
++              monahans_bbt_default.veroffs = 2;
++      } else {
++              this->ecc.layout = &monahans_sb_nand_oob;
++              this->ecc.mode = NAND_ECC_HW;
++              this->ecc.size = 512;
++              this->ecc.bytes = 6;
++              this->bbt_td->offs = 8;
++              this->bbt_td->veroffs = 12;
++              this->bbt_md->offs = 8;
++              this->bbt_md->veroffs = 12;
++              this->badblockpos = NAND_SMALL_BADBLOCK_POS;
++              monahans_bbt_default.offs = NAND_SMALL_BADBLOCK_POS;
++              monahans_bbt_default.len = 1;
++              monahans_bbt_default.veroffs = 8;
++      }
++
++      info->context = &dfc_context;
++      /* TODO: allocate dma buffer and channel */
++
++      platform_set_drvdata(pdev, monahans_mtd);
++
++      if (nand_scan(monahans_mtd, 1)) {
++              printk(KERN_ERR "Nand scan failed\n");
++              ret = -ENXIO;
++              goto free_irq;
++      }
++
++      /* There is a potential limitation that no more partition can be
++       * added between MassStorage and BBT(last block).
++       *
++       * The last 127 blocks is reserved for relocation table, they aren't
++       * statistical data of mtd size and chip size.
++       *
++       * BBT partitions contains 4 blocks. Two blocks are used to store
++       * main descriptor, the other two are used to store mirror descriptor.
++       */
++      partition_info[PART_NUM - 1].size = (monahans_bbt_main.maxblocks
++                                      + monahans_bbt_mirror.maxblocks)
++                                      << this->phys_erase_shift;
++      partition_info[PART_NUM - 1].offset = this->chipsize
++                                      - partition_info[PART_NUM - 1].size;
++      partition_info[PART_NUM - 2].offset = partition_info[PART_NUM - 3].offset
++                                      + partition_info[PART_NUM - 3].size;
++      partition_info[PART_NUM - 2].size = this->chipsize
++                                      - partition_info[PART_NUM - 2].offset
++                                      - partition_info[PART_NUM - 1].size;
++      add_mtd_partitions(monahans_mtd, partition_info, PART_NUM);
++
++#ifdef CONFIG_DVFM
++        dvfm_notifier.client_data = info;
++        mhn_fv_register_notifier(&dvfm_notifier);
++#endif
++
++      return 0;
++
++free_irq:
++      free_irq(IRQ_NAND, info);
++#ifdef CONFIG_MTD_NAND_MONAHANS_DMA
++free_cmd_dma:
++      pxa_free_dma(info->cmd_dma);
++free_data_dma:
++      pxa_free_dma(info->data_dma);
++free_buf:
++      dma_free_writecombine(dev, buf_len, info->data_desc, info->data_desc_addr);
++#else
++free_buf:
++      kfree(info->data_buf);
++#endif
++free_mtd:
++      kfree(monahans_mtd);
++out:
++      return ret;
++
++}
++
++static int __devexit monahans_df_remove(struct platform_device *dev)
++{
++      struct mtd_info *mtd = (struct mtd_info *)platform_get_drvdata(dev);
++      struct monahans_dfc_info *info = (struct monahans_dfc_info *)
++                      (((struct nand_chip *)(mtd->priv))->priv);
++#ifdef CONFIG_MTD_NAND_MONAHANS_DMA
++      unsigned int data_buf_len = dfc_context.flash_info->page_size +
++                      dfc_context.flash_info->oob_size;
++      unsigned int buf_len = ALIGN(2*sizeof(struct pxa_dma_desc), 32) +
++                      ALIGN(data_buf_len, 32) + ALIGN(NAND_CMD_DMA_LEN, 32);
++#endif
++
++#ifdef CONFIG_DVFM
++        mhn_fv_unregister_notifier(&dvfm_notifier);
++#endif
++
++      platform_set_drvdata(dev, NULL);
++
++      del_mtd_device(mtd);
++      del_mtd_partitions(mtd);
++      free_irq(IRQ_NAND, info);
++#ifdef CONFIG_MTD_NAND_MONAHANS_DMA
++      pxa_free_dma(info->cmd_dma);
++      pxa_free_dma(info->data_dma);
++      dma_free_writecombine(dev, buf_len, info->data_desc,
++              info->data_desc_addr);
++#else
++      kfree(info->data_buf);
++#endif
++      kfree(mtd);
++
++      return 0;
++}
++
++#ifdef CONFIG_PM
++static int monahans_df_suspend(struct platform_device *dev, pm_message_t state, u32 level)
++{
++      struct mtd_info *mtd = (struct mtd_info *)platform_get_drvdata(dev);
++      struct monahans_dfc_info *info = (struct monahans_dfc_info *)
++                      (((struct nand_chip *)(mtd->priv))->priv);
++
++      if( SUSPEND_DISABLE == level){ /*SUSPEND_NOTIFY*/
++              if (info->state != STATE_READY) {
++                      printk(KERN_ERR "current state is %d\n", info->state);
++                      return -EAGAIN;
++              }
++              info->state = STATE_SUSPENDED;
++              /*
++               * The PM code need read the mobm from NAND.
++               * So the NAND clock can't be stop here.
++               * The PM code will cover this.
++               */
++              /* pxa_set_cken(CKEN_NAND, 0); */
++      }
++      return 0;
++}
++
++static int monahans_df_resume(struct platform_device *dev, u32 level)
++{
++      struct mtd_info *mtd = (struct mtd_info *)platform_get_drvdata(dev);
++      struct monahans_dfc_info *info = (struct monahans_dfc_info *)
++                      (((struct nand_chip *)(mtd->priv))->priv);
++      int status;
++
++      if(RESUME_ENABLE == level){
++              if (info->state != STATE_SUSPENDED)
++                      printk(KERN_WARNING "Error State after resume back\n");
++
++              info->state = STATE_READY;
++
++              pxa_set_cken(CKEN_NAND, 1);
++
++              status = dfc_init(&dfc_context, flash_config);
++              if (status) {
++                      printk(KERN_ALERT "Monahans NAND device:"
++                              "Nand Flash initialize failure!\n");
++                      return -ENXIO;
++              }
++      }
++      return 0;
++}
++#endif
++
++#ifdef CONFIG_DVFM
++static int mhn_nand_dvfm_notifier(unsigned cmd, void *client_data, void *info)
++{
++      struct monahans_dfc_info *dfc_info =
++                      (struct monahans_dfc_info *)client_data;
++
++      switch (cmd) {
++      case FV_NOTIFIER_QUERY_SET :
++              if (dfc_info->state != STATE_READY)
++                      return -1;
++              break;
++
++      case FV_NOTIFIER_PRE_SET :
++              break;
++
++      case FV_NOTIFIER_POST_SET :
++              break;
++      }
++
++      return 0;
++}
++#endif
++
++static struct platform_driver monahans_df_driver = {
++      .probe          = monahans_df_probe,
++      .remove         = __devexit_p(monahans_df_remove),
++#ifdef CONFIG_PM
++      .suspend        = monahans_df_suspend,
++      .resume         = monahans_df_resume,
++#endif
++      .driver         = {
++              .name           = "monahans-nand-flash",
++      }
++};
++
++static void __exit monahans_df_cleanup(void)
++{
++      printk(KERN_ERR "Nand driver registered\n");
++      platform_driver_unregister(&monahans_df_driver);
++}
++
++static int __init monahans_df_init(void)
++{
++      return platform_driver_register(&monahans_df_driver);
++}
++
++module_init(monahans_df_init);
++module_exit(monahans_df_cleanup);
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Jingqing.xu (jingqing.xu@intel.com)");
++MODULE_DESCRIPTION("Glue logic layer for NAND flash on monahans DFC");
++
++
+Index: linux-2.6.23/arch/arm/mach-pxa/zylonite.c
+===================================================================
+--- linux-2.6.23.orig/arch/arm/mach-pxa/zylonite.c     2008-02-13 00:59:45.000000000 +0000
++++ linux-2.6.23/arch/arm/mach-pxa/zylonite.c  2008-02-13 09:11:02.000000000 +0000
+@@ -29,6 +29,8 @@
+ #include "generic.h"
+ int gpio_backlight;
++int gpio_vsync;
++int gpio_vsync1;
+ int gpio_eth_irq;
+ int lcd_id;
+@@ -54,6 +56,16 @@
+       .resource       = smc91x_resources,
+ };
++static struct platform_device nand_device = {
++      .name           = "monahans-nand-flash",
++      .id             = -1,
++};
++
++static struct platform_device touch_device = {
++      .name           = "pxa2xx-touch",
++      .id             = -1,
++};
++
+ #if defined(CONFIG_FB_PXA) || (CONFIG_FB_PXA_MODULES)
+ static void zylonite_backlight_power(int on)
+ {
+@@ -96,7 +108,7 @@
+ };
+ static struct pxafb_mode_info sharp_ls037_modes[] = {
+-      [0] = {
++      [1] = {
+               .pixclock       = 158000,
+               .xres           = 240,
+               .yres           = 320,
+@@ -109,8 +121,8 @@
+               .lower_margin   = 3,
+               .sync           = 0,
+       },
+-      [1] = {
+-              .pixclock       = 39700,
++      [0] = {
++              .pixclock       = 45000,
+               .xres           = 480,
+               .yres           = 640,
+               .bpp            = 16,
+@@ -137,6 +149,11 @@
+       /* backlight GPIO: output, default on */
+       gpio_direction_output(gpio_backlight, 1);
++      gpio_direction_output(gpio_vsync, 0);
++      gpio_direction_output(gpio_vsync1, 0);
++
++      printk(KERN_ERR "LCD ID is %x\n", lcd_id);
++
+       if (lcd_id & 0x20) {
+               set_pxa_fb_info(&zylonite_sharp_lcd_info);
+               return;
+@@ -169,6 +186,8 @@
+       smc91x_resources[1].start = gpio_to_irq(gpio_eth_irq);
+       smc91x_resources[1].end   = gpio_to_irq(gpio_eth_irq);
+       platform_device_register(&smc91x_device);
++      platform_device_register(&nand_device);
++      platform_device_register(&touch_device);
+       zylonite_init_lcd();
+ }
+Index: linux-2.6.23/arch/arm/mach-pxa/zylonite_pxa300.c
+===================================================================
+--- linux-2.6.23.orig/arch/arm/mach-pxa/zylonite_pxa300.c      2008-02-13 00:59:45.000000000 +0000
++++ linux-2.6.23/arch/arm/mach-pxa/zylonite_pxa300.c   2008-02-13 14:01:13.000000000 +0000
+@@ -62,12 +62,12 @@
+       GPIO110_UART3_RXD,
+       /* AC97 */
+-      GPIO23_AC97_nACRESET,
++      /*GPIO23_AC97_nACRESET,
+       GPIO24_AC97_SYSCLK,
+       GPIO29_AC97_BITCLK,
+       GPIO25_AC97_SDATA_IN_0,
+       GPIO27_AC97_SDATA_OUT,
+-      GPIO28_AC97_SYNC,
++      GPIO28_AC97_SYNC,*/
+       /* Keypad */
+       GPIO107_KP_DKIN_0,
+@@ -104,6 +104,41 @@
+       /* Ethernet */
+       GPIO2_nCS3,
+       GPIO99_GPIO,
++
++      /* NAND */
++      MFP_CFG_X(DF_INT_RnB, AF0, DS10X, PULL_LOW),
++      MFP_CFG_X(DF_nRE_nOE, AF1, DS10X, PULL_LOW),
++      MFP_CFG_X(DF_nWE, AF1, DS10X, PULL_LOW),
++      MFP_CFG_X(DF_CLE_nOE, AF0, DS10X, PULL_LOW),
++      MFP_CFG_X(DF_nADV1_ALE, AF1, DS10X, PULL_LOW),
++      MFP_CFG_X(DF_nCS0, AF1, DS10X, PULL_LOW),
++      MFP_CFG_X(DF_nCS1, AF0, DS10X, PULL_LOW),
++      MFP_CFG_X(DF_IO0, AF1, DS08X, PULL_LOW),
++      MFP_CFG_X(DF_IO1, AF1, DS08X, PULL_LOW),
++      MFP_CFG_X(DF_IO2, AF1, DS08X, PULL_LOW),
++      MFP_CFG_X(DF_IO3, AF1, DS08X, PULL_LOW),
++      MFP_CFG_X(DF_IO4, AF1, DS08X, PULL_LOW),
++      MFP_CFG_X(DF_IO5, AF1, DS08X, PULL_LOW),
++      MFP_CFG_X(DF_IO6, AF1, DS08X, PULL_LOW),
++      MFP_CFG_X(DF_IO7, AF1, DS08X, PULL_LOW),
++      MFP_CFG_X(DF_IO8, AF1, DS08X, PULL_LOW),
++      MFP_CFG_X(DF_IO9, AF1, DS08X, PULL_LOW),
++      MFP_CFG_X(DF_IO10, AF1, DS08X, PULL_LOW),
++      MFP_CFG_X(DF_IO11, AF1, DS08X, PULL_LOW),
++      MFP_CFG_X(DF_IO12, AF1, DS08X, PULL_LOW),
++      MFP_CFG_X(DF_IO13, AF1, DS08X, PULL_LOW),
++      MFP_CFG_X(DF_IO14, AF1, DS08X, PULL_LOW),
++
++      /* AC97 */
++      MFP_CFG_X(GPIO23, AF1, DS03X, PULL_LOW),
++      MFP_CFG_X(GPIO27, AF1, DS03X, PULL_LOW),
++      MFP_CFG_X(GPIO28, AF1, DS03X, PULL_LOW),
++      MFP_CFG_X(GPIO29, AF1, DS03X, PULL_LOW),
++      MFP_CFG_X(GPIO25, AF1, DS03X, PULL_LOW),
++
++      MFP_CFG_X(GPIO26, AF0, DS01X, PULL_LOW), /* Interrupt */
++      MFP_CFG_X(GPIO24, AF0, DS03X, PULL_LOW), /*SYSCLK external */
++      MFP_CFG_X(GPIO11, AF0, DS01X, PULL_LOW),
+ };
+ static mfp_cfg_t pxa310_mfp_cfg[] __initdata = {
+@@ -163,6 +198,9 @@
+               pxa3xx_mfp_write(lcd_detect_pins[i], mfpr_save[i]);
+ }
++extern int gpio_vsync;
++extern int gpio_vsync1;
++
+ void __init zylonite_pxa300_init(void)
+ {
+       if (cpu_is_pxa300() || cpu_is_pxa310()) {
+@@ -174,6 +212,8 @@
+               /* GPIO pin assignment */
+               gpio_backlight = mfp_to_gpio(MFP_PIN_GPIO20);
++              gpio_vsync = mfp_to_gpio(GPIO76_LCD_VSYNC);
++              gpio_vsync1 = mfp_to_gpio(GPIO71_LCD_LDD_17);
+       }
+       if (cpu_is_pxa300()) {
+Index: linux-2.6.23/drivers/video/pxafb.c
+===================================================================
+--- linux-2.6.23.orig/drivers/video/pxafb.c    2008-02-13 00:59:45.000000000 +0000
++++ linux-2.6.23/drivers/video/pxafb.c 2008-02-13 00:59:45.000000000 +0000
+@@ -1543,9 +1543,9 @@
+         if (inf->lccr0 & LCCR0_INVALID_CONFIG_MASK)
+                 dev_warn(&dev->dev, "machine LCCR0 setting contains illegal bits: %08x\n",
+                         inf->lccr0 & LCCR0_INVALID_CONFIG_MASK);
+-        if (inf->lccr3 & LCCR3_INVALID_CONFIG_MASK)
+-                dev_warn(&dev->dev, "machine LCCR3 setting contains illegal bits: %08x\n",
+-                        inf->lccr3 & LCCR3_INVALID_CONFIG_MASK);
++        //if (inf->lccr3 & LCCR3_INVALID_CONFIG_MASK)
++        //        dev_warn(&dev->dev, "machine LCCR3 setting contains illegal bits: %08x\n",
++        //                inf->lccr3 & LCCR3_INVALID_CONFIG_MASK);
+         if (inf->lccr0 & LCCR0_DPD &&
+           ((inf->lccr0 & LCCR0_PAS) != LCCR0_Pas ||
+            (inf->lccr0 & LCCR0_SDS) != LCCR0_Sngl ||
+Index: linux-2.6.23/include/asm-arm/arch-pxa/mfp-pxa300.h
+===================================================================
+--- linux-2.6.23.orig/include/asm-arm/arch-pxa/mfp-pxa300.h    2008-02-13 00:59:45.000000000 +0000
++++ linux-2.6.23/include/asm-arm/arch-pxa/mfp-pxa300.h 2008-02-13 00:59:45.000000000 +0000
+@@ -175,13 +175,13 @@
+ #define GPIO68_LCD_LDD_14     MFP_CFG_DRV(GPIO68, AF1, DS01X)
+ #define GPIO69_LCD_LDD_15     MFP_CFG_DRV(GPIO69, AF1, DS01X)
+ #define GPIO70_LCD_LDD_16     MFP_CFG_DRV(GPIO70, AF1, DS01X)
+-#define GPIO71_LCD_LDD_17     MFP_CFG_DRV(GPIO71, AF1, DS01X)
++#define GPIO71_LCD_LDD_17     MFP_CFG_DRV(GPIO71, AF0, DS01X)
+ #define GPIO62_LCD_CS_N               MFP_CFG_DRV(GPIO62, AF2, DS01X)
+ #define GPIO72_LCD_FCLK               MFP_CFG_DRV(GPIO72, AF1, DS01X)
+ #define GPIO73_LCD_LCLK               MFP_CFG_DRV(GPIO73, AF1, DS01X)
+ #define GPIO74_LCD_PCLK               MFP_CFG_DRV(GPIO74, AF1, DS01X)
+ #define GPIO75_LCD_BIAS               MFP_CFG_DRV(GPIO75, AF1, DS01X)
+-#define GPIO76_LCD_VSYNC      MFP_CFG_DRV(GPIO76, AF2, DS01X)
++#define GPIO76_LCD_VSYNC      MFP_CFG_DRV(GPIO76, AF0, DS01X)
+ #define GPIO15_LCD_CS_N               MFP_CFG_DRV(GPIO15,  AF2, DS01X)
+ #define GPIO127_LCD_CS_N      MFP_CFG_DRV(GPIO127, AF1, DS01X)
diff --git a/packages/kexecboot/linux-kexecboot-2.6.23/zylonite_touch-r0.patch b/packages/kexecboot/linux-kexecboot-2.6.23/zylonite_touch-r0.patch
new file mode 100644 (file)
index 0000000..1c00696
--- /dev/null
@@ -0,0 +1,1548 @@
+Index: linux-2.6.23/drivers/input/touchscreen/Kconfig
+===================================================================
+--- linux-2.6.23.orig/drivers/input/touchscreen/Kconfig        2008-02-13 01:12:29.000000000 +0000
++++ linux-2.6.23/drivers/input/touchscreen/Kconfig     2008-02-13 01:13:20.000000000 +0000
+@@ -54,6 +54,12 @@
+         To compile this driver as a module, choose M here: the
+         module will be called corgi_ts.
++config TOUCHSCREEN_ZYLONITE
++      tristate "Zylonite touchscreen driver"
++      default y
++      help
++        Say Y here for the Zylonite touchscreen driver
++
+ config TOUCHSCREEN_FUJITSU
+       tristate "Fujitsu serial touchscreen"
+       select SERIO
+Index: linux-2.6.23/drivers/input/touchscreen/Makefile
+===================================================================
+--- linux-2.6.23.orig/drivers/input/touchscreen/Makefile       2008-02-13 01:12:29.000000000 +0000
++++ linux-2.6.23/drivers/input/touchscreen/Makefile    2008-02-13 01:13:38.000000000 +0000
+@@ -19,3 +19,4 @@
+ obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN)    += touchwin.o
+ obj-$(CONFIG_TOUCHSCREEN_UCB1400)     += ucb1400_ts.o
+ obj-$(CONFIG_TOUCHSCREEN_TSC2101)     += tsc2101_ts.o
++obj-$(CONFIG_TOUCHSCREEN_ZYLONITE)    += zylonite-ts.o
+Index: linux-2.6.23/drivers/input/touchscreen/zylonite-ts.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.23/drivers/input/touchscreen/zylonite-ts.c       2008-02-13 16:19:15.000000000 +0000
+@@ -0,0 +1,1517 @@
++/*
++ *  drivers/input/touchscreen/mhn_audio_touch.c.
++ *
++ *  Author:   bridge.wu@marvell.com
++ *  Created:  Nov 17, 2006
++ *  Copyright:        Marvell Corporation.
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License version 2 as
++ *  published by the Free Software Foundation.
++ */
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/device.h>
++#include <linux/platform_device.h>
++#include <linux/interrupt.h>
++#include <linux/delay.h>
++
++#include <sound/driver.h>
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/initval.h>
++
++#include <asm/semaphore.h>
++#include <asm/hardware.h>
++#include <asm/arch/pxa-regs.h>
++#include <asm/arch/gpio.h>
++#include <asm/arch/mfp.h>
++//#include <asm/arch/ipmc.h>
++#include <linux/suspend.h>
++#include <linux/spinlock.h>
++
++//#include <asm/arch/codec/acodec.h>
++//#include <asm/arch/mhn_audio_plat.h>
++
++#define OSCC               __REG(0x41350000)  /* Oscillator Configuration Register */
++#define AC97_DIV      __REG(0x41340014)
++
++#define ALSA_ZY_CARD_DEBUG
++#undef ALSA_ZY_CARD_DEBUG
++
++#define WM_9713_ID  0x4C13 /* this should be the 7E register value */
++
++#ifdef ALSA_ZY_CARD_DEBUG
++#define dbg(format, arg...) printk(KERN_DEBUG format, ##arg)
++#else
++#define dbg(format, arg...)
++#endif
++
++#define DEBUG
++#undef DEBUG
++#ifdef DEBUG
++unsigned int start_time;
++unsigned int end_time;
++unsigned int time;
++#define PRINT_TIME() do {\
++        time = ((end_time > start_time))?\
++                (end_time - start_time)*100/325:\
++                (0xffffffff - start_time + end_time)*100/325;\
++        printk("\n%s:%dus\n", __FUNCTION__, time);\
++} while(0)
++#endif
++
++
++
++
++/* 9713 specific
++ *    Register Name                   Index
++ */
++#define RESET                         0X00
++#define SPEAKER_VOLUME                        0X02
++#define HEADPHONE_VOLUME              0X04
++#define OUT3_OUT4_VOLUME              0X06
++#define MONOVOL_MONOINPGA_ROUTE               0X08
++#define LINE_IN_PGA_VOL_ROUTE         0X0A
++#define DAC_PGA_VOL_ROUTE             0X0C
++#define MIC_PGA_VOLUME                        0X0E
++#define MIC_ROUTING                   0X10
++#define REC_PGA_VOL                   0X12
++#define REC_ROUTE_MUX_SEL             0X14
++#define PCBEEP_VOL_ROUTE              0X16
++#define VXDAC_VOLUME_ROUTE            0X18
++#define AUX_DAC_VOL_ROUTE             0X1A
++#define OUTPUT_PGA_MUX                        0X1C
++#define DAC_3D_CTRL_INV_MUX_SEL               0X1E
++#define DAC_TONE_CTRL                 0X20
++#define MIC_BIAS                      0X22
++#define OUTPUT_VOL_MAPPING_JACK               0X24
++#define POWERDOWN_CTRL_STAT           0X26
++#define EXTENDED_AUD_ID                       0X28
++#define EXTENDED_AUD_STAT_CTRL        0X2A
++#define AUDIO_DAC_RATE                        0X2C
++#define AUX_DAC_RATE                  0X2E
++#define AUDIO_ADC_RATE                        0X32
++#define PCM_CODEC_CTRL                        0X36
++#define SPDIF_CTRL                    0X3A
++#define POWER_DOWN_1                  0X3C
++#define POWER_DOWN_2                  0X3E
++#define GENERAL_PURPOSE_WM_13         0X40
++#define FAST_POWERUP_CTRL             0X42
++#define MCLK_PLL_CTRL_1                       0X44
++#define MCLK_PLL_CTRL_2                       0X46
++#define GPIO_PIN_CFG                  0X4C
++#define GPIO_PIN_POL_TYPE             0X4E
++#define GPIO_PIN_STICKY               0X50
++#define GPIO_PIN_WAKEUP                       0X52
++#define GPIO_PIN_STATUS                       0X54
++#define GPIO_PIN_SHARING              0X56
++#define GPIO_PULL_UP_DOWN_CTRL                0X58
++#define ADD_FUNC_1                    0X5A
++#define ADD_FUNC_2                    0X5C
++#define ALC_CTRL                      0X60
++#define ALC_NOISE_GATE_CTRL           0X62
++#define AUX_DAC_INPUT_CTRL            0X64
++#define TEST_REG_1                    0X68
++#define TEST_REG_2                    0X6A
++#define TEST_REG_3                    0X6C
++#define TEST_REG_4                    0X6E
++#define DIGITIZER_1_WM13              0x74
++#define DIGITIZER_2_WM13              0x76
++#define DIGITIZER_3_WM13              0x78
++#define DIGITIZER_READ_BACK           0x7a
++#define VENDOR_ID1                    0x7c
++#define VENDOR_ID2                    0x7e
++
++#define ZY_TOUCH_SAMPLE_X 1
++#define ZY_TOUCH_SAMPLE_Y 2
++
++#define ZY_EVENT_TYPE_NONE                    0
++#define ZY_EVENT_TYPE_PDN                     1
++
++
++typedef enum _zy_acodec_error_t {
++    ZY_ACODEC_SUCCESS = 0,    /* successful completion of a function */
++    ZY_ACODEC_GENERAL_SW_ERR, /* null pointer to registers or other software error */
++    ZY_ACODEC_CONTROLLER_INTERFACE_TIMEOUT, /* time-out for waiting for respponse */
++    ZY_ACODEC_SAMPLERATE_NOT_SUPPORTED, /* the sample rate is not supported either in controller or codec */
++    ZY_ACODEC_FEATURE_NO_SUPPORTED, /* this codec feature is not supported  */
++    ZY_ACODEC_GENERAL_HW_ERR ,/* other hardware error besides time out */
++    ZY_ACODEC_ROUTE_NO_SUPPORTED, /* the codec can not set the route required */
++    ZY_ACODEC_SLEEP /* the codec is sleep */
++} zy_acodec_error_t;
++
++typedef unsigned int zy_acodec_device_id_t;
++
++typedef enum _codec_state {
++      ZY_CODEC_SLEEP  = 0,
++      ZY_CODEC_WAKEUP = 1
++} acodec_state_t;
++
++typedef enum {
++       ZY_FM = 0,
++       ZY_MIC1 = 1,
++       ZY_MIC2 = 2,
++       ZY_SPEAKER =3,
++       ZY_HEADSET =4,
++       ZY_HANDSET =5,
++} vol_port_type_t;
++
++typedef struct _context_t {
++      int  use_count;                 /* probe/remove and suspend/resume usage count, sync among multiple devices */
++      zy_acodec_device_id_t acodec_id;/* - an ID that uniquely identifies the codec to be used */
++      unsigned long init_number;      /* used by driver to track whether it is inited or not */
++
++      void *p_voice_reg;              /* pointer to Monahans registers that has PCM interface to codec */
++      void *p_hifi_reg;               /* pointer to Monahans registers that has hifi interface to codec */
++      void *p_ctrl_reg;               /* pointer to Monahans registers that has control interface to codec */
++      int  *p_ost_regs;               /* needed for time out */
++      void *p_save_memory;            /* pointer to a memory region to save context while suspend */
++      void *p_zy_scenario;            /* pointer to the scenario data structure  */
++      long u_max_read_write_time_out_ms;/* input the max time to wait in milliseconds before giving up on a read or write operation */
++      long u_max_setup_time_out_ms;   /* input the maximum time in milliseconds to wait during initial setup of the ACODEC controller and codec */
++
++      /* member functions these pointers must be set by */
++      zy_acodec_error_t (* g_pfn_codec_specific_init)      (struct _context_t *p_device_context);
++      zy_acodec_error_t (* g_pfn_codec_specific_dinit)    (struct _context_t *p_device_context);
++      zy_acodec_error_t (* g_pfn_acodec_read)             (struct _context_t *p_dev_context, unsigned short reg_addr, unsigned short *p_reg_value);
++      zy_acodec_error_t (* g_pfn_acodec_write)            (struct _context_t *p_dev_context, unsigned short reg_addr, unsigned short reg_value);
++
++      /* add for route */
++      zy_acodec_error_t (* g_pfn_set_route)           (struct _context_t *p_device_context, unsigned short * rout_map ,unsigned short* current_map);
++      /* add for sleep the codec */
++      zy_acodec_error_t (* g_pfn_sleep_codec)           (struct _context_t *p_device_context);
++      /* add for Wake up the codec */
++      zy_acodec_error_t (* g_pfn_wake_codec)           (struct _context_t *p_device_context);
++      /* add for get codec state */
++      zy_acodec_error_t (* g_pfn_get_state)           (struct _context_t *p_device_context, acodec_state_t *p_state);
++      /* add for volume */
++      zy_acodec_error_t (* g_pfn_get_vol)(struct _context_t *p_device_context, vol_port_type_t port,  unsigned short *gain_in_db);
++      zy_acodec_error_t (* g_pfn_set_vol)(struct _context_t *p_device_context, vol_port_type_t port,  unsigned short gain_in_db);
++
++        void (* g_pfn_get_event)(struct _context_t *p_device_context, unsigned char * event_type);
++        void (* g_pfn_event_ack)(struct _context_t *p_device_context, unsigned char event_type);
++        zy_acodec_error_t (* g_pfn_enable_touch)(struct _context_t *p_device_context);
++        zy_acodec_error_t (* g_pfn_disable_touch)(struct _context_t *p_device_context);
++} zy_acocec_context_t, *p_zy_acocec_context_t;
++
++
++
++
++
++static p_zy_acocec_context_t p_zy_codec_ctxt = NULL;
++
++#include <linux/input.h>
++//#include <asm/arch/codec/wm9713.h>
++
++#define PEN_DOWN              1
++#define PEN_UP                        0
++#define TS_SAMPLE_INTERVAL    1
++
++typedef struct {
++      struct input_dev *idev;
++      struct timer_list *timer;
++      int  use_count;
++} codec_zy_ts_t;
++
++codec_zy_ts_t codec_zy_ts;
++
++static struct input_dev *codec_zy_ts_input;
++
++#ifdef CONFIG_PM
++static volatile int touch_suspend = 0 ;
++#endif
++
++#define ZY_AC97_CODEC_REGS_NUM        0x40
++
++typedef struct
++{  //   Register symbol     // Usage
++    volatile unsigned long pocr;           // PCM Out Control Register
++    volatile unsigned long picr;           // PCM In Control Register
++    volatile unsigned long mccr;           // Mic In Control Register
++    volatile unsigned long gcr;            // Global Control Register
++    volatile unsigned long posr;           // PCM Out Status Register
++    volatile unsigned long pisr;           // PCM In Status Register
++    volatile unsigned long mcsr;           // Mic In Status Register
++    volatile unsigned long gsr;            // Global Status Register
++    volatile unsigned long car;            // CODEC Access Register
++    volatile unsigned long pcscr;          // PCM Surround Out Control
++    volatile unsigned long pcssr;          // PCM Surround Out Status
++    volatile unsigned long pcsdr;          // PCM Surround Out Data
++    volatile unsigned long pcclcr;         // PCM Center/LFE Out Control
++    volatile unsigned long pcclsr;         // PCM Center/LFE Out Status
++    volatile unsigned long pccldr;         // PCM Center/LFE Out Data
++    volatile unsigned long reserved1;       //
++    volatile unsigned long pcdr;           // PCM FIFO Data Register
++    volatile unsigned long reserved2 [0x7];      // 0x4050-0044 through 0x4050-005C
++    volatile unsigned long mcdr;           // Mic-in FIFO Data Register
++    volatile unsigned long reserved3 [0x27];   // 0x4050-0064 through 0x4050-00FC
++    volatile unsigned long mocr;           // MODEM Out Control Register
++    volatile unsigned long reserved4;
++    volatile unsigned long micr;           // MODEM In Control Register
++    volatile unsigned long reserved5;
++    volatile unsigned long mosr;           // MODEM Out Status Register
++    volatile unsigned long reserved6;
++    volatile unsigned long misr;           // MODEM In Status Register
++    volatile unsigned long reserved7 [0x9];      // 0x4050-011C through 0x4050-013C
++    volatile unsigned long modr;           // MODEM FIFO Data Register
++    volatile unsigned long reserved8 [0x2F];   // 0x4050-0144 through 0x4050-01FC
++                            // Primary Audio CODEC registers access
++    volatile unsigned long codec_regs_primary_aud   [ZY_AC97_CODEC_REGS_NUM];
++                            // Secondary ID 01 Audio CODEC registers access
++    volatile unsigned long codec_regs_secondary_aud [ZY_AC97_CODEC_REGS_NUM];
++                            // Primary MODEM CODEC registers access
++    volatile unsigned long codec_regs_primary_mdm   [ZY_AC97_CODEC_REGS_NUM];
++                            // Secondary ID 01 MODEM CODEC registers access
++    volatile unsigned long codec_regs_secondary_mdm [ZY_AC97_CODEC_REGS_NUM];
++                            // Secondary ID 10 MODEM CODEC registers access
++    volatile unsigned long codec_regs_third_mdm [ZY_AC97_CODEC_REGS_NUM];
++                            // Secondary ID 11 MODEM CODEC registers access
++    volatile unsigned long codec_regs_fouth_mdm [ZY_AC97_CODEC_REGS_NUM];
++                            // Secondary ID 10 Audio CODEC registers access
++    volatile unsigned long codec_regs_third_aud [ZY_AC97_CODEC_REGS_NUM];
++                            // Secondary ID 11 Audio CODEC registers access
++    volatile unsigned long codec_regs_fouth_aud [ZY_AC97_CODEC_REGS_NUM];
++}  zy_ac97_acodec_t, *p_zy_ac97acodec_t ;
++
++
++/* Constants for the Global Control Register and Global Status Register */
++
++// AC97 Global Control Register bit mask constants
++
++#define ZY_AC97_GCR_GIE_MSK          (1u << 0 )
++#define ZY_AC97_GCR_COLD_RESET_MSK   (1u << 1 )
++#define ZY_AC97_GCR_WARM_RESET_MSK   (1u << 2 )
++#define ZY_AC97_GCR_LINK_OFF_MSK     (1u << 3 )
++#define ZY_AC97_GCR_PCRSM_IEN_MSK    (1u << 4 )
++#define ZY_AC97_GCR_SCRSM_IEN_MSK    (1u << 5 )
++#define ZY_AC97_GCR_PCRDY_IEN_MSK    (1u << 8 )
++#define ZY_AC97_GCR_SCRDY_IEN_MSK    (1u << 9 )
++#define ZY_AC97_GCR_SDONE_IE_MSK     (1u << 18)
++#define ZY_AC97_GCR_CDONE_IE_MSK     (1u << 19)
++#define ZY_AC97_GCR_nDMAEN_MSK       (1u << 24)
++#define ZY_AC97_GCR_CLKBPB_MSK       (1u << 31)
++#define ZY_AC97_GCR_FRCRST_MSK       (1u << 30)
++// Global Status Register bit mask constants
++
++#define ZY_AC97_GSR_GSCI_MSK       (1u << 0 )
++#define ZY_AC97_GSR_MIINT_MSK      (1u << 1 )
++#define ZY_AC97_GSR_MOINT_MSK      (1u << 2 )
++#define ZY_AC97_GSR_ACOFFD_MSK     (1u << 3 )
++#define ZY_AC97_GSR_PIINT_MSK      (1u << 5 )
++#define ZY_AC97_GSR_POINT_MSK      (1u << 6 )
++#define ZY_AC97_GSR_MINT_MSK       (1u << 7 )
++#define ZY_AC97_GSR_PCRDY_MSK      (1u << 8 )
++#define ZY_AC97_GSR_SCRDY_MSK      (1u << 9 )
++#define ZY_AC97_GSR_PCRSM_MSK      (1u << 10)
++#define ZY_AC97_GSR_SCRSM_MSK      (1u << 11)
++#define ZY_AC97_GSR_SLT12_BITS_MSK (7u << 12)
++#define ZY_AC97_GSR_RCS_ERR_MSK    (1u << 15)
++#define ZY_AC97_GSR_SDONE_MSK      (1u << 18)
++#define ZY_AC97_GSR_CDONE_MSK      (1u << 19)
++
++
++// Bit mask and values for CAIP bit in car register.
++#define ZY_AC97_CAR_CAIP_MSK       (0x1<<0)
++#define ZY_AC97_CAR_CAIP_LOCKED    (0x1<<0)
++#define ZY_AC97_CAR_CAIP_CLEAR     (0<<0)
++
++/* Constants for FIFO status reporting and control */
++
++// One bit location is used to report FIFO error conditions and clear
++//  interrupts on those conditions in the various non-global status registers.
++
++// ZY_AC97_FIFOSTAT_FIFOE is used in:
++                                                // posr
++                                                // pisr
++                                                // mcsr
++                                                // mosr
++                                                // misr
++
++#define ZY_AC97_FIFOSTAT_FIFOE  (1u << 4)
++#define ZY_AC97_FIFOSTAT_EOC    (1u << 3)
++#define ZY_AC97_FIFOSTAT_FSR    (1u << 2)
++
++// A different bit location is used to enable or disable interrupts based on
++//  FIFO error conditions in the various non-global control registers.
++
++// ZY_AC97_FIFOCTRL_FEIE is used in:
++                                                // pocr
++                                                // picr
++                                                // mccr
++                                                // mocr
++                                                // micr
++
++#define ZY_AC97_FIFOCTRL_FEIE  (1u << 3)
++#define ZY_AC97_FIFOCTRL_FSRIE (1u << 1)
++
++/*
++*******************************************************************************
++    AC'97 Codec Registers Location and Bit Definition
++*******************************************************************************
++*/
++
++/* */
++
++    // Includes symbolic values for certain proprietary register asssignments
++    //   in AC'97 devices that might be used with ZY_AC97.
++
++    // Valid for subset of R 2.1 specification.
++    // Leading "e" in comment means it is an "expanded" register definition as
++    //  found in one or more of the Appendices A-D of the R 2.1 specification.
++    //  Appendix identifier will immediately follow the "e", such as "eA"
++    // R/O indicates read-only
++    // Registers not supported by the assumed controller will be commented out.
++
++#define    ZY_AC97_CR_RESET_ID             0x00  // RESET CODEC TO DEFAULT, get ID info
++#define    ZY_AC97_CR_MASTER_VOLUME        0x02  // LINE OUT VOLUME
++#define    ZY_AC97_CR_HEADPHONE_VOLUME     0x04  //
++#define    ZY_AC97_CR_MASTER_VOLUME_MONO   0x06  //
++#define    ZY_AC97_CR_MASTER_TONE_R_L      0x08  //
++#define    ZY_AC97_CR_PC_BEEP_VOLUME       0x0A  //
++#define    ZY_AC97_CR_PHONE_VOLUME         0x0C  //
++#define    ZY_AC97_CR_MIC_VOLUME           0x0E  //   micrOPHONE VOLUME/ AGC
++#define    ZY_AC97_CR_LINE_IN_VOLUME       0x10  //   LINE IN VOLUME
++#define    ZY_AC97_CR_CD_VOLUME            0x12  //
++#define    ZY_AC97_CR_VIDEO_VOLUME         0x14  //
++#define    ZY_AC97_CR_AUX_VOLUME           0x16  //
++#define    ZY_AC97_CR_PCM_OUT_VOLUME       0x18  //
++#define    ZY_AC97_CR_RECORD_SELECT        0x1A  //   SELECT LINE IN OR micrOPHONE
++#define    ZY_AC97_CR_RECORD_GAIN          0x1C  //
++#define    ZY_AC97_CR_RECORD_GAIN_MIC      0x1E  //
++#define    ZY_AC97_CR_GENERAL_PURPOSE      0x20  //
++#define    ZY_AC97_CR_CONTROL_3D           0x22  //
++#define    ZY_AC97_CR_POWERDOWN_CTRL_STAT  0x26  //   POWER MANAGEMENT
++#define    ZY_AC97_CR_E_AUDIO_ID           0x28  // eA Extended audio sprt info, R/O
++#define    ZY_AC97_CR_E_AUDIO_CTRL_STAT    0x2A  // eA Extended audio stat + control
++
++//
++// Audio Sample Rate Control Registers, 0x2C - 0x34
++//
++                                           // eA PCM Front DAC rate control
++#define    ZY_AC97_CR_E_ASR_PCM_FRNT_DAC_RT 0x2C  //  (output slots 3, 4, 6)
++#define    ZY_AC97_CR_E_ASR_PCM_LR_ADC_RT   0x32  // eA PCM L+R ADC rate control (3+4)
++#define    ZY_AC97_CR_E_ASR_MIC_ADC_RT      0x34  // eA PCM Mic ADC rate control (5)
++
++
++#define    ZY_AC97_CR_E_MDM_GPIO_PIN_STAT     0x54
++//
++// 5Ah-7Ah: Vendor Reserved
++//
++//
++// 7Ch-7Eh: Vendor ID registers.  Optional but standardized for Plug'n'Play
++//
++#define    ZY_AC97_CR_VENDOR_ID1         0x7C
++#define    ZY_AC97_CR_VENDOR_ID2         0x7E
++
++#define    ZY_AC97_CR_MAX               ZY_AC97_CR_VENDOR_ID2
++
++#define    ZY_AC97_CR_END_OF_LIST       (ZY_AC97_CR_MAX +  2)
++
++
++
++/* Other Constants */
++
++// For accessing the Codec mixer registers, each increment of one 32-bit word
++//  in processor space increments the addressed mixer register by two.
++// This does not cause any ambiguities because only even mixer register
++//  addresses are currently supported (AC '97 spec, R 2.2)
++#define ZY_AC97_CODEC_REGS_PER_WORD           2
++
++/* Default timeout and holdtime settings */
++
++// timeout in reading and writing codec registers through AC link
++#define ZY_AC97_RW_TIMEOUT_DEF                200     //unit is us
++
++// timeout in waiting for codec's ready signal during setup process
++#define ZY_AC97_SETUP_TIMEOUT_DEF             500     //unit is us
++
++// timeout in waiting for locking the link successfully
++#define ZY_AC97_LOCK_TIMEOUT_DEF              300     //unit is us
++
++// timeout in shutting down the link
++#define ZY_AC97_LINKOFF_TIMEOUT_DEF           500     //unit is us
++
++// holdtime for keeping nReset signal active(low) in AC link
++#define ZY_AC97_COLD_HOLDTIME                 100     //unit is us
++
++/*
++*******************************************************************************
++  ZY AC97 data structure used in function interface
++*******************************************************************************
++*/
++
++typedef struct
++{
++    unsigned long pocr;           // PCM Out Control Register
++    unsigned long picr;           // PCM In Control Register
++    unsigned long mccr;           // Mic In Control Register
++    unsigned long gcr;            // Global Control Register
++    unsigned long pcscr;          // PCM Surround Out Control
++    unsigned long pcclcr;         // PCM Center/LFE Out Control
++    unsigned long mocr;           // MODEM Out Control Register
++    unsigned long micr;           // MODEM In Control Register
++}zy_ac97_save_context_t;
++
++
++#define AC97_SAVE_CONTEXT_SIZE (sizeof(zy_ac97_save_context_t))
++
++static int zy_ac97_acodec_link_lock(p_zy_ac97acodec_t p_ac97_reg)
++{
++      int             status = 1;
++      volatile unsigned long  car_tmp;
++
++      car_tmp = p_ac97_reg->car;
++      if (car_tmp & ZY_AC97_CAR_CAIP_MSK)     /*  "1" in CAIP bit means lock failed. */
++      {
++              status = 0;
++      }
++      return (status);
++}
++
++
++zy_acodec_error_t zy_ac97_acodec_write (zy_acocec_context_t *p_dev_context, unsigned short offset, unsigned short data)
++{
++      zy_acodec_error_t       status = ZY_ACODEC_SUCCESS;
++      int                     got_link;
++      unsigned long           time_remaining;
++      volatile unsigned long *        p_codec_reg;
++      p_zy_ac97acodec_t p_ac97_reg = (p_zy_ac97acodec_t)(p_dev_context->p_ctrl_reg);
++      unsigned long max_rw_time_out_us = (p_dev_context->u_max_read_write_time_out_ms) * 1000;
++
++
++      if(offset == ZY_AC97_CR_E_MDM_GPIO_PIN_STAT)
++      {/* it is a special register and sent out on slot 12 */
++              p_codec_reg = &(p_ac97_reg->codec_regs_primary_mdm[0]);
++              p_codec_reg += offset / ZY_AC97_CODEC_REGS_PER_WORD;
++              /*  The data will be sent out on slot 12. */
++              *p_codec_reg = (unsigned long)data;
++              goto done;
++      }
++
++      /*  Point to specified register within area mapped to target codec regs */
++      p_codec_reg = &(p_ac97_reg->codec_regs_primary_aud[0]);
++      p_codec_reg += offset / ZY_AC97_CODEC_REGS_PER_WORD;
++
++
++      /* Lock the ACLINK */
++      time_remaining = ZY_AC97_LOCK_TIMEOUT_DEF;
++      do
++      {
++              got_link = zy_ac97_acodec_link_lock(p_ac97_reg);
++              if (0 == got_link)      /*  1 usec is a long time.  Skip delay if possible. */
++              {
++                      udelay(1);
++              }
++      }               /*  Wait while time remaining and ACLINK not available */
++      while (time_remaining-- && (0 == got_link));
++
++      if (0 == got_link)      /*  Didn't get the ACLINK */
++      {
++              status = ZY_ACODEC_CONTROLLER_INTERFACE_TIMEOUT;
++              printk(KERN_ERR "AC97 Write Link Timeout\n");
++      }
++      else    /*  We got the link. Perform the write operation and don't wait. */
++      {
++              /*  First, clear old write status indication CDONE by writing a ONE to that bit. */
++              p_ac97_reg->gsr = ZY_AC97_GSR_CDONE_MSK;
++
++              *p_codec_reg = (unsigned long)data;        /*  Now the write! */
++
++              /* Wait until write cycle is complete. There should be a way
++               * to do this speculatively at the beginning of the procedure.
++               * Need to discover it. Too inefficient to always wait.
++               */
++
++              time_remaining = max_rw_time_out_us;
++              do
++              {
++                      udelay(1);
++              }        /*  Wait while time remaining and command I/O still incomplete. */
++              while ( (time_remaining--) && !(p_ac97_reg->gsr & ZY_AC97_GSR_CDONE_MSK));
++              if (!(p_ac97_reg->gsr & ZY_AC97_GSR_CDONE_MSK))
++              {
++                      status = ZY_ACODEC_CONTROLLER_INTERFACE_TIMEOUT;
++                      p_ac97_reg->car = ZY_AC97_CAR_CAIP_CLEAR;
++              }
++      }  /*  Got AC link */
++
++done:
++      return(status);
++} /*  Ac97CtrlCodecWrite() */
++
++#define CKENA         __REG(0x4134000C)       /* A Clock Enable Register */
++#define CKENB         __REG(0x41340010)
++
++zy_acodec_error_t zy_ac97_acodec_read  (zy_acocec_context_t *p_dev_context, unsigned short offset,  unsigned short *pdata)
++{
++      zy_acodec_error_t       status = ZY_ACODEC_SUCCESS;
++      int                     got_link;
++      unsigned long           time_remaining;
++      volatile unsigned long *        p_codec_reg;
++      p_zy_ac97acodec_t p_ac97_reg = (p_zy_ac97acodec_t)(p_dev_context->p_ctrl_reg);
++      unsigned long max_rw_time_out_us = (p_dev_context->u_max_read_write_time_out_ms) * 1000;
++
++      /*  Point to specified register within area mapped to target codec regs */
++      p_codec_reg = &(p_ac97_reg->codec_regs_primary_aud[0]);
++      p_codec_reg += offset / ZY_AC97_CODEC_REGS_PER_WORD;
++
++      /* Lock the ACLINK */
++      time_remaining = ZY_AC97_LOCK_TIMEOUT_DEF;
++      do
++      {
++              got_link = zy_ac97_acodec_link_lock(p_ac97_reg);
++              if (0 == got_link)      /*  1 usec is a long time.  Skip delay if possible. */
++              {
++                      udelay(1);
++              }
++      }               /*  Wait while time remaining and ACLINK not available */
++      while (time_remaining-- && (0 == got_link));
++
++      if (0 == got_link)      /*  Didn't get the ACLINK */
++      {
++              status = ZY_ACODEC_CONTROLLER_INTERFACE_TIMEOUT;
++              printk(KERN_ERR "AC97 Read Link Timeout\n");
++      }
++      else    /*  We got the link. Perform the write operation and don't wait. */
++      {
++               /*  First, clear old read status indications. */
++              p_ac97_reg->gsr = ZY_AC97_GSR_SDONE_MSK | ZY_AC97_GSR_RCS_ERR_MSK;
++
++              *pdata = (unsigned short)(*p_codec_reg); /*  This is THE DUMMY READ. */
++
++               /*  Wait for read I/O with codec to complete before doing real read. */
++              time_remaining = max_rw_time_out_us;
++              do
++              {
++                      udelay(1);
++              }   /*  Wait while time remaining and read I/O still incomplete */
++              while( (time_remaining--) && (!(p_ac97_reg->gsr & ZY_AC97_GSR_SDONE_MSK)) );
++
++              if ((p_ac97_reg->gsr & ZY_AC97_GSR_SDONE_MSK) && (!(p_ac97_reg->gsr & ZY_AC97_GSR_RCS_ERR_MSK)) )
++              {
++                      if (p_ac97_reg->gsr & ZY_AC97_GSR_RCS_ERR_MSK)
++                      {/* timeout indicated by RCS bit */
++                              status = ZY_ACODEC_CONTROLLER_INTERFACE_TIMEOUT;
++                      }
++                      /*  succeed in reading. clear status bits first. */
++                      p_ac97_reg->gsr = ZY_AC97_GSR_SDONE_MSK | ZY_AC97_GSR_RCS_ERR_MSK;
++                      *pdata = (unsigned short)(*p_codec_reg);        /*  THE REAL READ. */
++                      if (*pdata == 0xffff)
++                      {/* timeout indicated by returned value */
++                              status = ZY_ACODEC_CONTROLLER_INTERFACE_TIMEOUT;
++                      }
++                      /* check later: is second waiting really needed? */
++                      time_remaining = max_rw_time_out_us;
++                      do
++                      {
++                              udelay(1);
++                      }   /*  Wait while time remaining and read I/O still incomplete */
++                      while( (time_remaining--) && (!(p_ac97_reg->gsr & ZY_AC97_GSR_SDONE_MSK)) );
++                      //printk(KERN_ERR "AC97 Read Result %d\n", (p_ac97_reg->gsr & ZY_AC97_GSR_SDONE_MSK) );
++              }
++              else    /*  failed */
++              {
++                      status = ZY_ACODEC_CONTROLLER_INTERFACE_TIMEOUT;
++                      p_ac97_reg->car = ZY_AC97_CAR_CAIP_CLEAR;
++                      //printk(KERN_ERR "AC97 Read Link Timeout2 %x %x %x\n", CKENA, OSCC, CKENB);
++              } /*  else  (OK to do real read) */
++
++      } /*  else  (We got the link.  Perform the read operations.) */
++
++      return (status);
++}
++
++
++
++zy_acodec_error_t zy_acodec_get_adc_sample(zy_acocec_context_t *p_device_context, unsigned short *p_sample_data, unsigned short adc_type, int *p_pen_down)
++{
++      zy_acodec_error_t       status = ZY_ACODEC_SUCCESS;
++      unsigned short value;
++      unsigned long wait;
++
++      if (adc_type == ZY_TOUCH_SAMPLE_X)
++      {
++              value = 0x202;
++      }
++      else
++      {/* Y sample */
++              value = 0x204;
++      }
++
++      status = zy_ac97_acodec_write(p_device_context, DIGITIZER_1_WM13, value);
++
++      wait = 0;
++      do
++      {
++              status = zy_ac97_acodec_read(p_device_context, DIGITIZER_1_WM13, &value);
++              if ( !(value & 0x200 ) )
++              {
++                      break;
++              }
++      }while ( 100 > wait++ );
++
++      status = zy_ac97_acodec_read(p_device_context, DIGITIZER_READ_BACK, &value);
++      if (value & 0x8000)
++      {/* means pen down */
++              *p_pen_down = 1;
++      }
++      else
++      {
++              *p_pen_down = 0;
++      }
++      *p_sample_data = value & 0xfff;
++
++      return status;
++}
++
++
++
++/*
++ * add a touch event
++ */
++static int codec_zy_ts_evt_add(codec_zy_ts_t* ts, u16 pressure, u16 x, u16 y)
++{
++        /* add event and remove adc src bits */
++        static u16 pre_press = 0;
++
++        input_report_abs(ts->idev, ABS_X, x & 0xfff);
++        input_report_abs(ts->idev, ABS_Y, y & 0xfff);
++        if (pressure == pre_press){
++                pressure--;
++        }
++        pre_press = pressure;
++        input_report_abs(ts->idev, ABS_PRESSURE, pressure & 0xfff);
++      input_sync(ts->idev);
++#ifdef CONFIG_IPM
++      ipm_event_notify(IPM_EVENT_UI, IPM_EVENT_DEVICE_TSI, NULL, 0);
++#endif
++        return 0;
++}
++
++/*
++ * add a pen up event
++ */
++static void codec_zy_ts_evt_release(codec_zy_ts_t* ts)
++{
++      input_report_abs(ts->idev, ABS_PRESSURE, 0);
++      input_sync(ts->idev);
++
++#ifdef CONFIG_IPM
++      ipm_event_notify(IPM_EVENT_UI, IPM_EVENT_DEVICE_TSI, NULL, 0);
++#endif
++      p_zy_codec_ctxt->g_pfn_event_ack(p_zy_codec_ctxt,ZY_EVENT_TYPE_PDN);
++}
++
++/*
++ * Kill the touchscreen thread and stop
++ * the touch digitiser.
++ */
++static void codec_zy_ts_input_close(struct input_dev *idev)
++{
++      codec_zy_ts_t *ts = (codec_zy_ts_t *) &codec_zy_ts;
++
++#ifdef CONFIG_PM
++      if(touch_suspend){
++              pr_info("touch is suspended!\n");
++              return -1;
++      }
++#endif
++      dbg("close ts input!\n");
++      if (--ts->use_count == 0) {
++              del_timer(ts->timer);
++              if (ts->timer != NULL)
++                      kfree(ts->timer);
++              p_zy_codec_ctxt->g_pfn_disable_touch(p_zy_codec_ctxt);
++      }
++}
++
++/*
++ * Sample the touchscreen
++ */
++int ac97_poll_touch(codec_zy_ts_t *ts)
++{
++      unsigned short x=0, y=0;
++      int if_down= 0;
++      zy_acodec_error_t status = ZY_ACODEC_SUCCESS;
++
++#ifdef DEBUG
++        start_time = OSCR;
++#endif
++
++      /* get x value */
++      status = zy_acodec_get_adc_sample(p_zy_codec_ctxt, &x, ZY_TOUCH_SAMPLE_X, &if_down);
++      if (ZY_ACODEC_SUCCESS != status ){
++              return -EIO;
++      }
++      dbg("x:0x%x\n", x);
++
++      /* the pen is up */
++      if (1 != if_down){
++              return PEN_UP;
++      }
++
++      /* get y vaule */
++      status = zy_acodec_get_adc_sample(p_zy_codec_ctxt, &y, ZY_TOUCH_SAMPLE_Y, &if_down);
++      if (ZY_ACODEC_SUCCESS != status ){
++              return -EIO;
++      }
++      dbg("y:0x%x\n",y);
++
++      /* the pen is up */
++      if (1 != if_down){
++              return PEN_UP;
++      }
++
++      /* the pen is down, can not get the pressure value,
++       * so if pen is down, give the max pressure value
++       */
++      codec_zy_ts_evt_add(ts,0xfff, x, y);
++
++#ifdef DEBUG
++        end_time = OSCR;
++        PRINT_TIME();
++#endif
++
++      return PEN_DOWN;
++}
++
++static void touch_timer_handler(unsigned long unused)
++{
++      int event;
++      codec_zy_ts_t *ts = &codec_zy_ts;
++
++      event = ac97_poll_touch(ts);
++
++      if (event == PEN_DOWN) {
++              dbg("pen down!\n");
++              ts->timer->expires = jiffies + TS_SAMPLE_INTERVAL;
++              add_timer(ts->timer);
++      } else if(event == PEN_UP) {
++              dbg("pen up!\n");
++              codec_zy_ts_evt_release(ts);
++      } else if(event == -EIO) {
++              printk(KERN_ERR "Access touch interface error!\n");
++      }
++      return;
++}
++
++static zy_acodec_error_t  zy_ac97_acodec_cold_reset(zy_acocec_context_t * p_ac97_ctxt)
++{
++      zy_acodec_error_t       status = ZY_ACODEC_SUCCESS;
++      p_zy_ac97acodec_t p_ac97 = (p_zy_ac97acodec_t)(p_ac97_ctxt->p_ctrl_reg);
++      int              pri_codec_ready;
++      unsigned long           time_remaining;
++
++      p_ac97->gcr = 0;
++      p_ac97->gcr |= ZY_AC97_GCR_CLKBPB_MSK;
++      /*  Hold reset active for a minimum time */
++      udelay(ZY_AC97_COLD_HOLDTIME);
++      p_ac97->gcr &= ~ZY_AC97_GCR_CLKBPB_MSK;
++
++      /*  Deactivate cold reset condition */
++      p_ac97->gcr |= (ZY_AC97_GCR_COLD_RESET_MSK | ZY_AC97_GCR_WARM_RESET_MSK);
++
++
++      pri_codec_ready = 0;
++      time_remaining = (p_ac97_ctxt->u_max_setup_time_out_ms) * 10;
++      do
++      {
++              udelay(1);
++              if (p_ac97->gsr & ZY_AC97_GSR_PCRDY_MSK)
++                      pri_codec_ready = 1;
++      }
++      while (time_remaining-- && (pri_codec_ready == 0));
++
++      /*  Timeout status if some of the devices weren't ready. */
++      if (pri_codec_ready == 0)
++      {
++              status = ZY_ACODEC_CONTROLLER_INTERFACE_TIMEOUT;
++      }
++
++      return (status);
++}
++
++
++zy_acodec_error_t  zy_ac97_acodec_init(zy_acocec_context_t *p_ac97_ctxt)
++{
++      zy_acodec_error_t       status ;
++
++      status = zy_ac97_acodec_cold_reset(p_ac97_ctxt);
++
++      return (status);
++}
++
++
++/*
++ * Start the touchscreen thread and
++ * the touch digitiser.
++ */
++static int codec_zy_ts_input_open(struct input_dev *idev)
++{
++      codec_zy_ts_t *ts = (codec_zy_ts_t *) &codec_zy_ts;
++
++#ifdef CONFIG_PM
++      if(touch_suspend){
++              pr_info("touch is suspended!\n");
++              return -1;
++      }
++#endif
++
++      if (ts->use_count++ > 0)
++              return 0;
++
++      dbg("Touch is opened. Use count: %d\n", ts->use_count);
++      ts->idev = idev;
++      ts->timer = kmalloc(sizeof(struct timer_list), GFP_KERNEL);
++      if (!ts->timer) {
++              printk(KERN_ERR "Alloc memory error for timer!\n");
++              return -ENOMEM;
++      }
++
++      init_timer(ts->timer);
++      ts->timer->function = touch_timer_handler;
++      ts->timer->data = 0;
++      p_zy_codec_ctxt->g_pfn_enable_touch(p_zy_codec_ctxt);
++
++      return 0;
++}
++
++/*
++ * initilze the pxa touch screen
++ */
++static int alsa_ts_init( void )
++{
++      codec_zy_ts_t* ts = &codec_zy_ts;
++
++      memset(ts, 0, sizeof(codec_zy_ts_t));
++
++      codec_zy_ts_input = input_allocate_device();
++      if (!codec_zy_ts_input)
++              return -ENOMEM;
++
++
++      /* tell input system what we events we accept and register */
++      codec_zy_ts_input->name = "codec zy touchscreen";
++      codec_zy_ts_input->open = codec_zy_ts_input_open;
++      codec_zy_ts_input->close = codec_zy_ts_input_close;
++      __set_bit(EV_ABS, codec_zy_ts_input->evbit);
++      __set_bit(ABS_X, codec_zy_ts_input->absbit);
++      __set_bit(ABS_Y, codec_zy_ts_input->absbit);
++      __set_bit(ABS_PRESSURE, codec_zy_ts_input->absbit);
++      input_register_device(codec_zy_ts_input);
++
++      return 0;
++}
++
++static irqreturn_t pxa_touch_irq(int irq, void *dev)
++{
++      unsigned char event_type;
++
++      //printk(KERN_ERR "%s: enter codec event handler\n", __FUNCTION__);
++
++      dbg("%s: enter codec event handler\n", __FUNCTION__);
++      p_zy_codec_ctxt->g_pfn_get_event(p_zy_codec_ctxt, &event_type);
++      switch (event_type) {
++              case ZY_EVENT_TYPE_PDN:
++              {
++                      codec_zy_ts_t *ts = &codec_zy_ts;
++                      /*if the touch is not open need not acknowledge the event*/
++                      if (ts->use_count <= 0)
++                              break;
++                      ts->timer->expires = jiffies + TS_SAMPLE_INTERVAL;
++                      add_timer(ts->timer);
++                      break;
++              }
++              default:
++                      printk("unsupported codec event:0x%x\n", event_type);
++      }
++
++      return IRQ_HANDLED;
++}
++
++
++
++
++
++
++
++
++
++static mfp_cfg_t extra_cfg[] = {
++      MFP_CFG_X(GPIO17, AF3, DS03X, PULL_LOW),
++      MFP_CFG_X(GPIO25, AF0, DS01X, PULL_LOW),
++};
++
++#define ARRAY_AND_SIZE(x)     (x), ARRAY_SIZE(x)
++
++extern void dump_mfp(void);
++
++zy_acodec_error_t     zy_ac97_acodec_mfp_init(zy_acocec_context_t *p_device_context)
++{
++      unsigned short codec_id;
++
++      //mhn_mfp_set_afds(MFP_RSVD_AC97_SDATA_IN_0, MFP_AF0, MFP_DS03X);
++      //enable_ac97_pins();
++      zy_ac97_acodec_init(p_device_context);
++      if (zy_ac97_acodec_read(p_device_context, 0x0, &codec_id)){
++
++              /*
++               * there is a bug on MonahansL/MonhansPL PC card: AC97_SDATA_IN is not connected to CODEC
++               * ECO 72: Connect PWM_0(MFP_RSVD_AC97_SDATA_IN_0) to CODEC as AC97_SDATA_IN
++               */
++
++              //mhn_mfp_set_afds(MFP_RSVD_AC97_SDATA_IN_0, MFP_RSVD_AC97_SDATA_IN_0_AF, MFP_DS03X);
++              //mhn_mfp_set_afds(MFP_AC97_SDATA_IN_0, MFP_AF0, MFP_DS01X);
++
++              gpio_direction_output(mfp_to_gpio(MFP_PIN_GPIO17), 0);
++              pxa3xx_mfp_config(ARRAY_AND_SIZE(extra_cfg));
++              gpio_direction_input(mfp_to_gpio(MFP_PIN_GPIO25));
++      }
++
++
++      return ZY_ACODEC_SUCCESS;
++}
++
++#define ZY_AC97_WM9713_GPIO_PIN_PDN ( 0x1 << 13 )  /* Pen down */
++
++/*power enable bit in 3ch and 3eh */
++/*3ch */
++#define ZY_AC97_9713_PWR_PADCPD   ( 0x1 << 15 )
++#define ZY_AC97_9713_PWR_VMID     ( 0x1 << 14 )
++#define ZY_AC97_9713_PWR_TSHUT    ( 0x1 << 13 )
++#define ZY_AC97_9713_PWR_VXDAC    ( 0x1 << 12 )
++#define ZY_AC97_9713_PWR_AUXDAC   ( 0x1 << 11 )
++#define ZY_AC97_9713_PWR_MBIAS    ( 0x1 << 10 )
++#define ZY_AC97_9713_PWR_PLL      ( 0x1 << 9 )
++#define ZY_AC97_9713_PWR_DACL     ( 0x1 << 7 )
++#define ZY_AC97_9713_PWR_DACR     ( 0x1 << 6 )
++#define ZY_AC97_9713_PWR_ADCL     ( 0x1 << 5 )
++#define ZY_AC97_9713_PWR_ADCR     ( 0x1 << 4 )
++#define ZY_AC97_9713_PWR_HPLX     ( 0x1 << 3 )
++#define ZY_AC97_9713_PWR_HPRX     ( 0x1 << 2 )
++#define ZY_AC97_9713_PWR_SPKX     ( 0x1 << 1 )
++#define ZY_AC97_9713_PWR_MX       ( 0x1 << 0 )
++
++/*3EH */
++#define ZY_AC97_9713_PWR_MCD      ( 0x1 << 15 )
++#define ZY_AC97_9713_PWR_MICBIAS  ( 0x1 << 14 )
++#define ZY_AC97_9713_PWR_MONO     ( 0x1 << 13 )
++#define ZY_AC97_9713_PWR_OUT4     ( 0x1 << 12 )
++#define ZY_AC97_9713_PWR_OUT3     ( 0x1 << 11 )
++#define ZY_AC97_9713_PWR_HPL      ( 0x1 << 10 )
++#define ZY_AC97_9713_PWR_HPR      ( 0x1 << 9 )
++#define ZY_AC97_9713_PWR_SPKL     ( 0x1 << 8 )
++#define ZY_AC97_9713_PWR_SPKR     ( 0x1 << 7 )
++#define ZY_AC97_9713_PWR_LL       ( 0x1 << 6 )
++#define ZY_AC97_9713_PWR_LR       ( 0x1 << 5 )
++#define ZY_AC97_9713_PWR_MOIN     ( 0x1 << 4 )
++#define ZY_AC97_9713_PWR_MA       ( 0x1 << 3 )
++#define ZY_AC97_9713_PWR_MB       ( 0x1 << 2 )
++#define ZY_AC97_9713_PWR_MPA      ( 0x1 << 1 )
++#define ZY_AC97_9713_PWR_MPB      ( 0x1 << 0 )
++
++
++void zy_wm9713_get_event(zy_acocec_context_t *p_device_context, unsigned char * event_type)
++{
++      unsigned short event_state = 0;
++      zy_ac97_acodec_read(p_device_context, GPIO_PIN_STATUS, &event_state);
++      if(event_state & ZY_AC97_WM9713_GPIO_PIN_PDN){
++              *event_type = ZY_EVENT_TYPE_PDN;
++              return;
++      }
++      return;
++}
++
++void zy_wm9713_event_ack(zy_acocec_context_t *p_device_context, unsigned char event_type)
++{
++      unsigned short event_state = 0;
++      zy_ac97_acodec_read(p_device_context, GPIO_PIN_STATUS, &event_state);
++      if( event_type == ZY_EVENT_TYPE_PDN){
++              zy_ac97_acodec_write(p_device_context,
++                                      GPIO_PIN_STATUS,
++                                      (event_state & (~ZY_AC97_WM9713_GPIO_PIN_PDN)));
++      }
++
++      zy_ac97_acodec_read(p_device_context, GPIO_PIN_STATUS, &event_state);
++      return;
++}
++
++static void * p_saved_memory = NULL;
++static void * p_zy_scenario = NULL;
++static p_zy_acocec_context_t p_zy_ctxt = NULL;
++
++#define WM9713_SAVE_REGISTER_NO (64-11)
++typedef struct {
++    unsigned short wm9713RegisterContext [WM9713_SAVE_REGISTER_NO + 1]; /* Fixed (data misalignment error) */
++}ZY_9713_CONTEXT_SAVE_T;
++
++
++/**
++ * alsa_prepare_for_zy - create and initialize the p_zy_acocec_context_t
++ *                               open the clock of data link
++ * @p_p_zy_ctxt: return the data structure p_zy_acocec_context_t
++ * return: 0 success ; -ENOMEM
++ **/
++int alsa_prepare_for_zy(p_zy_acocec_context_t * p_p_zy_ctxt)
++{
++      if (p_zy_ctxt) {
++              p_zy_ctxt->use_count++;
++              *p_p_zy_ctxt = p_zy_ctxt;
++              return 0;
++      }
++
++      p_zy_ctxt = kzalloc(sizeof(zy_acocec_context_t), GFP_KERNEL);
++      if (!p_zy_ctxt)
++              return -ENOMEM;
++
++      /* enable CLK_POUT as CODEC clock input */
++      OSCC |= 0x800;
++
++      p_saved_memory = kzalloc(sizeof(ZY_9713_CONTEXT_SAVE_T) +
++                              sizeof(zy_ac97_save_context_t), GFP_KERNEL);
++      if (NULL == p_saved_memory) {
++              if (p_zy_ctxt)
++                      kfree(p_zy_ctxt);
++              return -ENOMEM;
++      }
++
++      p_zy_ctxt->acodec_id = (zy_acodec_device_id_t) (WM_9713_ID);
++      p_zy_ctxt->use_count++;
++      /*
++      p_zy_ctxt->pMfpRegBase = (unsigned long) (MFP_BASE);
++      p_zy_ctxt->pMfpRmDb = ZY_MFP_RM_DATABASE;
++      p_zy_ctxt->p_ost_regs = OST_BASE;
++      */
++      p_zy_ctxt->p_voice_reg = NULL;
++      p_zy_ctxt->p_hifi_reg = (void *) (&POCR);
++      p_zy_ctxt->p_ctrl_reg = (void *) (&POCR);
++      p_zy_ctxt->u_max_read_write_time_out_ms = ZY_AC97_RW_TIMEOUT_DEF;
++      p_zy_ctxt->u_max_setup_time_out_ms = ZY_AC97_SETUP_TIMEOUT_DEF;
++      p_zy_ctxt->p_save_memory = p_saved_memory;
++      p_zy_ctxt->p_zy_scenario = p_zy_scenario;
++//    pxa_set_cken(24, 1);
++      CKENA |= (1 << 24);
++      AC97_DIV = 1625<<12 | 128;
++#ifdef DEBUG_ALSA_ZY
++      debug_pac97ctxt = p_zy_ctxt;
++      misc_register(&audio_dev);
++#endif
++
++      (*p_p_zy_ctxt) = p_zy_ctxt;
++
++      return 0;
++}
++
++
++/* this is platform specific */
++/* do later: not to enable recording route and playback route in this function,
++ * leave it to driver to call other function
++ */
++zy_acodec_error_t zy_wm9713_specific_init (zy_acocec_context_t *p_device_context)
++{
++
++      unsigned short value;
++
++      /* this assumes that the aclink is initialized wait some time and then
++       * do a warm reset to enabled the ACLINK, required for wm9713
++       * (not wm9712 or ucb1400)
++       */
++
++      /* pay attention: whether the workaround is still needed? */
++      p_zy_ac97acodec_t p_ac97_reg = (p_zy_ac97acodec_t)(p_device_context->p_ctrl_reg);
++
++      p_ac97_reg->gcr |= ZY_AC97_GCR_WARM_RESET_MSK;
++
++      mdelay(5);
++
++      /* power on all the necessary unit */
++      zy_ac97_acodec_write(p_device_context,POWERDOWN_CTRL_STAT, 0x000);      /*26*/
++      /* open left headphone mixer */
++      /* open right headphone mixer */
++      /* open right/left dac */
++      /* open right/left adc */
++      /* open temperature sensor */
++      /* enable reference generator */
++      zy_ac97_acodec_write(p_device_context,POWER_DOWN_1, 0xda00);            /*3c */
++      /* open microphone bias */
++      /* open HPL output PGA */
++      /* open HPR output PGA */
++      /* open mic PGA MA */
++      /* open mic pre-amp MPA */
++      /* if here we enable SPKL and SPKR PGA, then Touch screen will doesn't work */
++      zy_ac97_acodec_write(p_device_context,POWER_DOWN_2,0xb9f5);   /*3e */
++
++      /* recording route and microphone input */
++      /* microphone selection, now fixed to MIC1 input and mic bias output */
++      /* MIC1 only, MICBIAS enable */
++      zy_ac97_acodec_write (p_device_context, MIC_BIAS, 0xC440);      /*0x22h*/
++
++      /* mic pga setting to mixer (side tone) */
++      /* comment the below code to make MICA/B play back volume gain + 0db */
++      /* zy_ac97_acodec_write (p_device_context, MIC_PGA_VOLUME, 0x0000); */  /*0x0eh*/
++
++      /* recording side tone and ADC boost, now fixed to default (14h) */
++      /* recording volume  0dB */
++      zy_ac97_acodec_write(p_device_context, REC_PGA_VOL, 0x0); /*12*/
++
++      /* hifi playback route and output mixer  */
++      /* by default, fixed to enable headphone only */
++
++      /* comment the below code to make SPEAKER default MUTE */
++      zy_ac97_acodec_write (p_device_context, SPEAKER_VOLUME, 0x0);           /*02*/
++
++      /* comment the below code to make OUT3_OUT4 default MUTE */
++      /* zy_ac97_acodec_write (p_device_context, OUT3_OUT4_VOLUME, 0x8000); */        /*06*/
++
++      /* remove all  the mute bit  volume gain + 0db  */
++      zy_ac97_acodec_write(p_device_context, HEADPHONE_VOLUME, 0x0);  /*04*/
++
++      /* DAC route */
++      /* open DAC to headphone mixer path */
++      /* left DAC gain +0db */
++      /* right DAC gain +0db */
++      zy_ac97_acodec_write(p_device_context, DAC_PGA_VOL_ROUTE,0x0808);       /*0c*/
++
++      /* out3 configure, invert to HPMIXR */
++      /* zy_ac97_acodec_write(p_device_context,DAC_3D_CTRL_INV_MUX_SEL, 0x8000); */   /*1e*/
++
++      /* output control */
++       /* select HPMIXR HPMIXL out */
++       /* other out are all VIM */
++      zy_ac97_acodec_write(p_device_context,OUTPUT_PGA_MUX, 0x9BA8);          /*1c*/
++
++      /* set sample rates */
++      /* enable variable rate conversion */
++      zy_ac97_acodec_write(p_device_context, EXTENDED_AUD_STAT_CTRL , 0x1); /*2a*/
++      /*  DAC 44kHZ */
++      zy_ac97_acodec_write(p_device_context,AUDIO_DAC_RATE,0xac44); /*2c*/
++      /*  ADC 16KHZ */
++      zy_ac97_acodec_write(p_device_context,AUDIO_ADC_RATE,0x3E80); /*32*/
++
++      /* clock scheme, use external clock, it is 24MHZ from MCLK_A */
++
++
++      zy_ac97_acodec_read(p_device_context, MCLK_PLL_CTRL_1, &value);
++      zy_ac97_acodec_write(p_device_context, MCLK_PLL_CTRL_1, value | 0x2);
++
++      return ZY_ACODEC_SUCCESS;
++}
++
++zy_acodec_error_t zy_wm9713_specific_deinit (zy_acocec_context_t *p_device_context)
++{/* do later: shut down all power */
++      unsigned short value = 0;
++
++      /* close the power of all units */
++      zy_ac97_acodec_write(p_device_context, POWER_DOWN_1, 0xffff);
++      zy_ac97_acodec_write(p_device_context, POWER_DOWN_2, 0xffff);
++      zy_ac97_acodec_read(p_device_context, POWER_DOWN_1, &value);
++      value &= ~(ZY_AC97_9713_PWR_MBIAS);
++      zy_ac97_acodec_write(p_device_context, POWER_DOWN_1, value);
++
++      return ZY_ACODEC_SUCCESS;
++}
++
++zy_acodec_error_t zy_acodec_set_pen_down_interrupt(zy_acocec_context_t *p_device_context, int enable)
++{/* disable/enable pen down interrupt in the codec. This function is not implemented for Wm9713 */
++      /* because the pen down detection could not be disabled in codec */
++      return ZY_ACODEC_SUCCESS;
++}
++
++zy_acodec_error_t zy_wm9713_enable_touch(zy_acocec_context_t *p_device_context)
++{/* enable touch functionality in the codec */
++      zy_acodec_error_t       status = ZY_ACODEC_SUCCESS;
++      unsigned short value;
++
++      /* power setting */
++      status = zy_ac97_acodec_read(p_device_context, POWER_DOWN_1, &value);
++      value &= ~(ZY_AC97_9713_PWR_PADCPD);
++      status = zy_ac97_acodec_write(p_device_context, POWER_DOWN_1, value);
++
++      /* basic touch setting   */
++      status = zy_ac97_acodec_write(p_device_context, DIGITIZER_3_WM13, 0xc008);
++      status = zy_ac97_acodec_write(p_device_context, DIGITIZER_2_WM13, 0x6);
++
++
++      /* 9713 powerdown virtual gpio setting (polarity, sticky, wakeup) */
++      /* 9713 gpio 2(pin45) route to IRQ */
++      /*  Notes: Can use defaults for IRQ polarity, PENDOWN polarity in IRQ, */
++      /*   sticky for PENDOWN in IRQ and wakeup for PENDOWN.   */
++      status = zy_ac97_acodec_read(p_device_context, GPIO_PIN_CFG, &value);
++      value &= ~(0x4);
++      status = zy_ac97_acodec_write(p_device_context, GPIO_PIN_CFG, value);
++
++      status = zy_ac97_acodec_read(p_device_context, GPIO_PIN_SHARING, &value);
++      value &= ~(0x4);
++      status = zy_ac97_acodec_write(p_device_context, GPIO_PIN_SHARING, value);
++
++      status = zy_ac97_acodec_read(p_device_context, GPIO_PIN_WAKEUP, &value);
++      value |= (0x2000);
++      status = zy_ac97_acodec_write(p_device_context, GPIO_PIN_WAKEUP, value);
++
++      status = zy_ac97_acodec_read(p_device_context, GPIO_PIN_STICKY, &value);
++      value |= (0x2000);
++      status = zy_ac97_acodec_write(p_device_context, GPIO_PIN_STICKY, value);
++
++      return status;
++}
++
++zy_acodec_error_t zy_wm9713_disable_touch(zy_acocec_context_t *p_device_context)
++{/* disable touch functionality in the codec */
++      zy_acodec_error_t       status = ZY_ACODEC_SUCCESS;
++      unsigned short value;
++
++      /* power setting */
++      status = zy_ac97_acodec_read(p_device_context, POWER_DOWN_1, &value);
++      value |= (ZY_AC97_9713_PWR_PADCPD);
++      status = zy_ac97_acodec_write(p_device_context, POWER_DOWN_1, value);
++
++      return status;
++}
++zy_acodec_error_t     zy_ac97_acodec_mfp_deinit(zy_acocec_context_t *p_device_context)
++{/* do later: free all MFP resources. */
++    return ZY_ACODEC_SUCCESS;
++}
++
++static zy_acodec_error_t  zy_ac97_acodec_shut_down_aclink(p_zy_ac97acodec_t p_ac97_reg, int * p_ost_regs)
++{
++      zy_acodec_error_t       status = ZY_ACODEC_SUCCESS;
++      unsigned long time_remaining = ZY_AC97_LINKOFF_TIMEOUT_DEF;
++
++      p_ac97_reg->gcr |= ZY_AC97_GCR_LINK_OFF_MSK;
++      p_ac97_reg->gcr |= ZY_AC97_GCR_CLKBPB_MSK;
++
++      while (!(p_ac97_reg->gsr & ZY_AC97_GSR_ACOFFD_MSK))
++      {
++              time_remaining --;
++              if (0 == time_remaining)
++              {
++                      status = ZY_ACODEC_CONTROLLER_INTERFACE_TIMEOUT;
++                      break;
++              }
++              udelay(1);
++      }
++      p_ac97_reg->gcr |= ZY_AC97_GCR_FRCRST_MSK;
++      /* check later: any delay needed */
++      p_ac97_reg->gcr &= ~ZY_AC97_GCR_FRCRST_MSK;
++      p_ac97_reg->gcr &= ~ZY_AC97_GCR_CLKBPB_MSK;
++
++      return(status);
++}
++
++
++zy_acodec_error_t  zy_ac97_acodec_deinit(zy_acocec_context_t * p_ac97_ctxt)
++{
++      zy_acodec_error_t       status ;
++
++      status = zy_ac97_acodec_shut_down_aclink((p_zy_ac97acodec_t)(p_ac97_ctxt->p_ctrl_reg), p_ac97_ctxt->p_ost_regs);
++
++      return (status);
++}
++
++zy_acodec_error_t zy_acodec_deinit(zy_acocec_context_t *p_device_context)
++{
++      /* power down codec by codec specific power down function */
++      if (p_device_context->g_pfn_codec_specific_dinit)
++      {
++              p_device_context->g_pfn_codec_specific_dinit(p_device_context);
++      }
++      /* call bus deinit function */
++      zy_ac97_acodec_deinit(p_device_context);
++      /* restore MFP, set GPIO to suitable value */
++      zy_ac97_acodec_mfp_deinit(p_device_context);
++
++      return ZY_ACODEC_SUCCESS;
++}
++
++void alsa_zy_codec_put(p_zy_acocec_context_t p_acodectxt)
++{
++
++      zy_acodec_deinit(p_acodectxt);
++      //pxa_set_cken(24, 0);
++      CKENA &= ~(1 << 24);
++
++      if(p_acodectxt->p_save_memory){
++              kfree(p_saved_memory);
++      }
++      if(p_acodectxt->p_zy_scenario){
++              kfree(p_zy_scenario);
++      }
++}
++
++
++zy_acodec_error_t zy_acodec_init(zy_acocec_context_t *p_device_context, int hw_init)
++{
++      /* set codec specific functions
++       * set mfp for Zylonite platform
++       * call bus init function (AC97, I2S, I2C, SSP)
++       * call specific init of codec
++       */
++      zy_acodec_error_t retval = ZY_ACODEC_SUCCESS;
++
++      if (p_device_context->acodec_id != WM_9713_ID)
++      {/* on Zylonite, it is Wolfson 9713 codec only */
++              return ZY_ACODEC_GENERAL_SW_ERR;
++      }
++
++      if (1 == hw_init)
++      {
++              zy_ac97_acodec_mfp_init(p_device_context);
++              zy_ac97_acodec_init(p_device_context);  /* codec init common to ac97 */
++      }
++
++      /* wm9713-specific functions */
++      (p_device_context->g_pfn_codec_specific_init)   = zy_wm9713_specific_init;
++      (p_device_context->g_pfn_codec_specific_dinit)  = zy_wm9713_specific_deinit;
++      (p_device_context->g_pfn_acodec_read)           = zy_ac97_acodec_read;
++      (p_device_context->g_pfn_acodec_write)          = zy_ac97_acodec_write;
++
++      (p_device_context->g_pfn_event_ack)    = zy_wm9713_event_ack;
++      (p_device_context->g_pfn_get_event)    = zy_wm9713_get_event;
++      (p_device_context->g_pfn_disable_touch)        = zy_wm9713_disable_touch;
++      (p_device_context->g_pfn_enable_touch) = zy_wm9713_enable_touch;
++
++      if (1 == hw_init)
++      {
++              retval = p_device_context->g_pfn_codec_specific_init(p_device_context);
++      }
++
++      return retval;
++}
++
++static int __devinit touch_codec_zy_probe(struct platform_device *dev)
++{
++      int ret = 0;
++      struct snd_card *card = NULL;
++      zy_acodec_error_t status;
++
++      /* will increase codec context use count */
++      ret = alsa_prepare_for_zy(&p_zy_codec_ctxt);
++      if (ret)
++              goto err;
++
++      /* codec specific initialization, audio will do it either */
++      if (1 == p_zy_codec_ctxt->use_count) {
++              status = zy_acodec_init(p_zy_codec_ctxt, 1);
++              if (ZY_ACODEC_SUCCESS != status) {
++                      printk(KERN_ERR "initialize codec error\n");
++                      ret = -EIO;
++                      goto err;
++              }
++
++      /* power down the units of the acodec, sleep the acodec, zy_acodec_init()
++       * will open all the units' power of the codec while ALSA need all the codec
++       * units power down and the codec should sleep if it can.
++       * So on the zylonite platform we call below function to power down and sleep
++       * wm9713 codec.
++       */
++      p_zy_codec_ctxt->g_pfn_codec_specific_dinit(p_zy_codec_ctxt);
++
++      }
++
++      alsa_ts_init();
++
++      //mhn_mfp_set_afds(MFP_AC97_INT_N_GPIO,0,0);
++      //mhn_gpio_set_direction(MFP_AC97_INT_N_GPIO, GPIO_DIR_IN);
++      //mhn_gpio_clear_edge_detect_status(MFP_AC97_INT_N_GPIO);
++      gpio_direction_input(mfp_to_gpio(MFP_PIN_GPIO26));
++      ret = request_irq(IRQ_GPIO(mfp_to_gpio(MFP_PIN_GPIO26)),
++                      pxa_touch_irq, IRQF_TRIGGER_RISING,
++                      "wm9713 touch event interrupt", NULL);
++      if (ret) {
++              printk(KERN_ERR "Request IRQ for touch failed (%d).\n", ret);
++              goto err;
++      }
++
++      return 0;
++err:
++      if (p_zy_codec_ctxt && (!--p_zy_codec_ctxt->use_count)) {
++              zy_acodec_deinit(p_zy_codec_ctxt);
++              //pxa_set_cken(24, 0);
++              CKENA &= ~(1 << 24);
++              kfree(p_zy_codec_ctxt);
++              p_zy_codec_ctxt = NULL;
++      }
++
++      if (card)
++              snd_card_free(card);
++
++      return ret;
++}
++
++static int __devexit touch_codec_zy_remove(struct platform_device *dev)
++{
++      struct snd_card *card = platform_get_drvdata(dev);
++
++      input_unregister_device(codec_zy_ts_input);
++
++      if (p_zy_codec_ctxt && (!--p_zy_codec_ctxt->use_count)) {
++              alsa_zy_codec_put(p_zy_codec_ctxt);
++              kfree(p_zy_codec_ctxt);
++              p_zy_codec_ctxt = NULL;
++      }
++
++      if (card) {
++              snd_card_free(card);
++              platform_set_drvdata(dev, NULL);
++      }
++
++      return 0;
++}
++
++#ifdef CONFIG_PM
++static int touch_codec_zy_suspend(struct platform_device *_dev, pm_message_t state, u32 level)
++{
++      int ret=0;
++      
++      if (level == SUSPEND_DISABLE) {
++              ret = audio_codec_zy_do_suspend(NULL, SNDRV_CTL_POWER_D3cold, p_zy_codec_ctxt);
++              touch_suspend = 1;
++      }
++      return ret;
++}
++
++static int touch_codec_zy_resume(struct platform_device *_dev, u32 level)
++{
++      int ret = 0;
++      
++      if (level == RESUME_ENABLE) {
++              ret = audio_codec_zy_do_resume(NULL, SNDRV_CTL_POWER_D0, p_zy_codec_ctxt);
++              touch_suspend = 0;
++      }
++      return ret;
++}
++#else
++#define touch_codec_zy_suspend        NULL
++#define touch_codec_zy_resume NULL
++#endif
++
++static struct platform_driver touch_codec_zy_driver = {
++      .probe  =       touch_codec_zy_probe,
++      .remove =       __devexit_p(touch_codec_zy_remove),
++      .suspend=       touch_codec_zy_suspend,
++      .resume =       touch_codec_zy_resume,
++      .driver = {
++              .name   =       "pxa2xx-touch",
++      },
++};
++
++static int __init touch_codec_zy_init(void)
++{
++      return platform_driver_register(&touch_codec_zy_driver);
++}
++
++static void __exit touch_code_zy_exit(void)
++{
++      platform_driver_unregister(&touch_codec_zy_driver);
++}
++module_init(touch_codec_zy_init);
++module_exit(touch_code_zy_exit);
++
++EXPORT_SYMBOL(p_zy_codec_ctxt);
++
++MODULE_AUTHOR("bridge.wu@marvell.com");
++MODULE_DESCRIPTION("zylonite audio touch codec driver on ALSA");
++MODULE_LICENSE("GPL");
++
diff --git a/packages/kexecboot/linux-kexecboot_2.6.23.bb b/packages/kexecboot/linux-kexecboot_2.6.23.bb
new file mode 100644 (file)
index 0000000..bbe1302
--- /dev/null
@@ -0,0 +1,149 @@
+require linux-kexecboot.inc
+
+DEFAULT_PREFERENCE_c7x0 = "1"
+
+# Handy URLs
+# git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git;protocol=git;tag=ef7d1b244fa6c94fb76d5f787b8629df64ea4046
+# ${KERNELORG_MIRROR}/pub/linux/kernel/v2.6/linux-2.6.18.tar.bz2
+# ${KERNELORG_MIRROR}/pub/linux/kernel/v2.6/testing/linux-2.6.20-rc4.tar.bz2
+# ${KERNELORG_MIRROR}/pub/linux/kernel/v2.6/testing/patch-2.6.18-rc6.bz2;patch=1
+# ${KERNELORG_MIRROR}/pub/linux/kernel/v2.6/snapshots/patch-2.6.18-rc2-git1.bz2;patch=1
+# ${KERNELORG_MIRROR}/pub/linux/kernel/people/alan/linux-2.6/2.6.10/patch-2.6.10-ac8.gz;patch=1
+# ${KERNELORG_MIRROR}/pub/linux/kernel/people/akpm/patches/2.6/2.6.14-rc2/2.6.14-rc2-mm1/2.6.14-rc2-mm1.bz2;patch=1
+
+# Patches submitted upstream are towards top of this list 
+# Hacks should clearly named and at the bottom
+SRC_URI = "${KERNELORG_MIRROR}/pub/linux/kernel/v2.6/linux-2.6.23.tar.bz2 \
+           file://defconfig"
+
+ZAURUS_PATCHES = " \
+           ${RPSRC}/pxa25x_suspend_fixes-r0.patch;patch=1;status=merged \
+           ${RPSRC}/lzo_jffs2-r3.patch;patch=1;status=merged \
+           ${RPSRC}/lzo_jffs2_lzomode-r1.patch;patch=1;status=merged \
+           ${RPSRC}/spitzkbd_fix-r0.patch;patch=1;status=merged \
+           file://uvesafb-0.1-rc3-2.6.22.patch;patch=1;status=merged \
+           ${RPSRC}/locomo_led_fix-r0.patch;patch=1;status=merged \
+           file://hrw-add-wcf11-to-hostap.patch;patch=1;status=merged \
+           ${RPSRC}/export_atags-r0a.patch;patch=1;status=pending \
+           ${RPSRC}/lzo_crypto-r2.patch;patch=1;status=pending \
+           ${RPSRC}/lzo_jffs2_sysfs-r1.patch;patch=1 \
+           ${RPSRC}/hx2750_base-r29.patch;patch=1 \
+           ${RPSRC}/hx2750_bl-r9.patch;patch=1 \
+           ${RPSRC}/hx2750_pcmcia-r2.patch;patch=1 \
+           ${RPSRC}/pxa_keys-r7.patch;patch=1 \
+           ${RPSRC}/tsc2101-r16.patch;patch=1 \
+           ${RPSRC}/hx2750_test1-r7.patch;patch=1 \
+           ${RPSRC}/input_power-r9.patch;patch=1 \
+           ${RPSRC}/pxa25x_cpufreq-r2.patch;patch=1 \
+           ${RPSRC}/sharpsl_pm_fixes1-r0.patch;patch=1 \
+           ${RPSRC}/pm_changes-r1.patch;patch=1 \
+           ${RPSRC}/usb_add_epalloc-r3.patch;patch=1 \
+           ${RPSRC}/usb_pxa27x_udc-r6.patch;patch=1 \
+           ${RPSRC}/locomo_kbd_tweak-r1.patch;patch=1 \
+           ${RPSRC}/pxa27x_overlay-r6.patch;patch=1 \
+           ${RPSRC}/w100_extaccel-r2.patch;patch=1 \
+           ${RPSRC}/w100_extmem-r1.patch;patch=1 \
+           ${RPSRC}/poodle_pm-r4.patch;patch=1 \
+           ${RPSRC}/poodle_lcd_hack-r0.patch;patch=1 \
+           ${RPSRC}/poodle_asoc_fix-r1.patch;patch=1 \
+           file://wm8750-treble.patch;patch=1 \
+           file://mtd-module.patch;patch=1 \
+           file://squashfs3.0-2.6.15.patch;patch=1;status=external \
+           ${RPSRC}/pxa-linking-bug.patch;patch=1;status=unmergable \
+           file://hostap-monitor-mode.patch;patch=1;status=unmergable \
+           file://serial-add-support-for-non-standard-xtals-to-16c950-driver.patch;patch=1;status=unmergable \
+           ${RPSRC}/mmcsd_large_cards-r1.patch;patch=1;status=hack \
+           ${RPSRC}/mmcsd_no_scr_check-r2.patch;patch=1;status=hack \
+           ${RPSRC}/integrator_rgb-r1.patch;patch=1;status=hack \
+           ${RPSRC}/pxa_cf_initorder_hack-r1.patch;patch=1;status=hack \
+           file://pxa-serial-hack.patch;patch=1;status=hack \
+           file://connectplus-remove-ide-HACK.patch;patch=1;status=hack \
+           file://connectplus-prevent-oops-HACK.patch;patch=1;status=hack \
+           file://htcuni.patch;patch=1 \
+           file://binutils-buildid-arm.patch;patch=1 \
+           file://versatile-armv6.patch;patch=1 \
+           "
+
+# FIXMEs before made default      
+# ${RPSRC}/mmcsd_no_scr_check-r1.patch;patch=1;status=hack
+
+# Add this to enable pm debug code (useful with a serial lead)
+#  ${RPSRC}/sharpsl_pm_debug-r0.patch;patch=1
+
+# Disabled until I find the reason this gives issues with cdc_subset
+#            ${RPSRC}/usb_rndis_tweaks-r0.patch;patch=1 \
+
+# Is anything out of this still needed? Parts were commited to mainline by rmk (drivers/mfd/)
+# (Pavel Machek's git tree has updated versions of this?)
+#  ${JLSRC}/zaurus-lcd-2.6.11.diff.gz;patch=1
+
+SRC_URI_append_c7x0 = " ${ZAURUS_PATCHES} "
+
+# These patches are extracted from Pavel Machek's git tree
+# (diff against vanilla kernel)
+SRC_URI_append_collie = " ${ZAURUS_PATCHES} \
+           ${DOSRC}/collie/mtd-sharp-flash-hack-r0.patch;patch=1 \
+           ${DOSRC}/collie/collie-r0.patch;patch=1 \
+           ${DOSRC}/collie/locomolcd-backlight-r0.patch;patch=1 \
+           ${DOSRC}/collie/ucb1x00-touch-audio-r0.patch;patch=1 \
+           file://collie-mcp-r1.patch;patch=1 \
+           ${DOSRC}/collie/sa1100-udc-r0.patch;patch=1 \
+#          ${DOSRC}/collie/collie-pm-r1.patch;patch=1 \
+"
+
+SRC_URI_append_poodle = " ${ZAURUS_PATCHES} \
+           ${RPSRC}/poodle_serial_vcc-r0.patch;patch=1 \
+"
+
+SRC_URI_append_tosa = " ${ZAURUS_PATCHES} \
+           ${CHSRC}/tmio-core-r4.patch;patch=1 \
+           file://tmio-tc6393-r8.patch;patch=1 \
+           file://tmio-nand-r8.patch;patch=1 \
+           ${CHSRC}/tmio-fb-r6.patch;patch=1 \
+          file://tmio-fb-r6-fix-r0.patch;patch=1 \
+           file://tosa-keyboard-r19.patch;patch=1 \
+           ${DOSRC}/tosa-pxaac97-r6.patch;patch=1 \
+          file://tosa-pxaac97-r6-fix-r0.patch;patch=1 \
+           ${DOSRC}/tosa-tmio-r6.patch;patch=1 \
+           file://tosa-power-r18.patch;patch=1 \
+           file://tosa-power-r18-fix-r0.patch;patch=1 \
+           file://tosa-tmio-lcd-r10.patch;patch=1 \
+           file://tosa-tmio-lcd-r10-fix-r0.patch;patch=1 \
+           file://tosa-bluetooth-r8.patch;patch=1 \
+           file://wm97xx-lg13-r0.patch;patch=1 \
+           file://wm97xx-lg13-r0-fix-r0.patch;patch=1 \
+           file://wm9712-suspend-cold-res-r2.patch;patch=1 \
+           file://sharpsl-pm-postresume-r1.patch;patch=1 \
+           file://wm9712-reset-loop-r2.patch;patch=1 \
+           file://tosa-lcdnoise-r1.patch;patch=1 \
+           file://tosa-lcdnoise-r1-fix-r0.patch;patch=1 \
+          file://arm-dma-coherent.patch;patch=1 \
+           file://usb-ohci-hooks-r3.patch;patch=1 \
+           file://tmio-ohci-r9.patch;patch=1 \
+           file://pxa2xx_udc_support_inverse_vbus.patch;patch=1 \
+           file://tosa_udc_use_gpio_vbus.patch;patch=1 \
+           "
+#          ${DOSRC}/tosa-asoc-r1.patch;patch=1 "
+
+SRC_URI_append_akita = " ${ZAURUS_PATCHES} \
+           file://sharpsl-rc-r1.patch;patch=1;status=external \
+           "
+
+SRC_URI_append_spitz = " ${ZAURUS_PATCHES} \
+           file://sharpsl-rc-r1.patch;patch=1;status=external \
+           "
+
+SRC_URI_append_htcuniversal =" ${ZAURUS_PATCHES} \
+       file://htcuni-acx.patch;patch=1;status=external \
+       "
+
+SRC_URI_append_zylonite =" ${ZAURUS_PATCHES} \
+       file://arm_pxa_20070923.patch;patch=1 \
+       file://pxa_fb_overlay.patch;patch=1 \
+       file://zylonite-boot.patch;patch=1 \
+       file://zylonite_mtd-r0.patch;patch=1 \
+       file://zylonite_touch-r0.patch;patch=1 \
+       file://zylonite_keypad-r0.patch;patch=1 \
+       "
+
+S = "${WORKDIR}/linux-2.6.23"