h6300 kernel: update to 2.6.14.3 and remove 2.6.14-rc5
authorMika Laitio <lamikr@cc.jyu.fi>
Sat, 3 Dec 2005 22:13:21 +0000 (22:13 +0000)
committerOpenEmbedded Project <openembedded-devel@lists.openembedded.org>
Sat, 3 Dec 2005 22:13:21 +0000 (22:13 +0000)
packages/linux/linux-h6300-omap1-2.6.14-rc5/defconfig
        packages/linux/linux-h6300-omap1-2.6.14-rc5/h6300_omap1_2614rc5.patch
        packages/linux/linux-h6300-omap1_2.6.14-rc5.bb
packages/linux/linux-h6300-omap1_2.6.14.3.bb
packages/linux/linux-h6300-omap1-2.6.14.3/defconfig
packages/linux/linux-h6300-omap1-2.6.14.3/patch-linux-2614-omap2-to-2614_3-omap1-h6300

packages/linux/linux-h6300-omap1-2.6.14-rc5/.mtn2git_empty [deleted file]
packages/linux/linux-h6300-omap1-2.6.14-rc5/defconfig [deleted file]
packages/linux/linux-h6300-omap1-2.6.14-rc5/h6300_omap1_2614rc5.patch [deleted file]
packages/linux/linux-h6300-omap1-2.6.14.3/.mtn2git_empty [new file with mode: 0644]
packages/linux/linux-h6300-omap1-2.6.14.3/defconfig [new file with mode: 0644]
packages/linux/linux-h6300-omap1-2.6.14.3/patch-linux-2614-omap2-to-2614_3-omap1-h6300 [new file with mode: 0644]
packages/linux/linux-h6300-omap1_2.6.14-rc5.bb [deleted file]
packages/linux/linux-h6300-omap1_2.6.14.3.bb [new file with mode: 0644]

diff --git a/packages/linux/linux-h6300-omap1-2.6.14-rc5/.mtn2git_empty b/packages/linux/linux-h6300-omap1-2.6.14-rc5/.mtn2git_empty
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/packages/linux/linux-h6300-omap1-2.6.14-rc5/defconfig b/packages/linux/linux-h6300-omap1-2.6.14-rc5/defconfig
deleted file mode 100644 (file)
index 8e76562..0000000
+++ /dev/null
@@ -1,1538 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.14-rc5-omap-h6300
-# Sun Oct 30 09:16:57 2005
-#
-CONFIG_ARM=y
-CONFIG_MMU=y
-CONFIG_UID16=y
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-# CONFIG_CLEAN_COMPILE is not set
-CONFIG_BROKEN=y
-CONFIG_BROKEN_ON_SMP=y
-CONFIG_INIT_ENV_ARG_LIMIT=32
-
-#
-# General setup
-#
-CONFIG_LOCALVERSION=""
-CONFIG_LOCALVERSION_AUTO=y
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-CONFIG_POSIX_MQUEUE=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_BSD_PROCESS_ACCT_V3=y
-CONFIG_SYSCTL=y
-# CONFIG_AUDIT is not set
-CONFIG_HOTPLUG=y
-CONFIG_KOBJECT_UEVENT=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_INITRAMFS_SOURCE=""
-CONFIG_EMBEDDED=y
-CONFIG_KALLSYMS=y
-# CONFIG_KALLSYMS_ALL is not set
-# CONFIG_KALLSYMS_EXTRA_PASS is not set
-CONFIG_PRINTK=y
-CONFIG_BUG=y
-CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_CC_OPTIMIZE_FOR_SIZE=y
-CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
-# CONFIG_TINY_SHMEM is not set
-CONFIG_BASE_SMALL=0
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
-CONFIG_OBSOLETE_MODPARM=y
-# CONFIG_MODVERSIONS is not set
-# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
-
-#
-# System Type
-#
-# CONFIG_ARCH_CLPS7500 is not set
-# CONFIG_ARCH_CLPS711X is not set
-# CONFIG_ARCH_CO285 is not set
-# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_CAMELOT is not set
-# CONFIG_ARCH_FOOTBRIDGE is not set
-# CONFIG_ARCH_INTEGRATOR is not set
-# CONFIG_ARCH_IOP3XX is not set
-# CONFIG_ARCH_IXP4XX is not set
-# CONFIG_ARCH_IXP2000 is not set
-# CONFIG_ARCH_L7200 is not set
-# CONFIG_ARCH_PXA is not set
-# CONFIG_ARCH_RPC is not set
-# CONFIG_ARCH_SA1100 is not set
-# CONFIG_ARCH_S3C2410 is not set
-# CONFIG_ARCH_SHARK is not set
-# CONFIG_ARCH_LH7A40X is not set
-CONFIG_ARCH_OMAP=y
-# CONFIG_ARCH_VERSATILE is not set
-# CONFIG_ARCH_IMX is not set
-# CONFIG_ARCH_H720X is not set
-# CONFIG_ARCH_AAEC2000 is not set
-
-#
-# TI OMAP Implementations
-#
-CONFIG_ARCH_OMAP1=y
-# CONFIG_ARCH_OMAP2 is not set
-
-#
-# OMAP Feature Selections
-#
-# CONFIG_OMAP_RESET_CLOCKS is not set
-# CONFIG_OMAP_BOOT_TAG is not set
-CONFIG_OMAP_MUX=y
-# CONFIG_OMAP_MUX_DEBUG is not set
-CONFIG_OMAP_MUX_WARNINGS=y
-CONFIG_OMAP_MPU_TIMER=y
-# CONFIG_OMAP_32K_TIMER is not set
-CONFIG_OMAP_LL_DEBUG_UART1=y
-# CONFIG_OMAP_LL_DEBUG_UART2 is not set
-# CONFIG_OMAP_LL_DEBUG_UART3 is not set
-CONFIG_OMAP_SERIAL_WAKE=y
-
-#
-# OMAP Core Type
-#
-# CONFIG_ARCH_OMAP730 is not set
-CONFIG_ARCH_OMAP15XX=y
-# CONFIG_ARCH_OMAP16XX is not set
-
-#
-# OMAP Board Type
-#
-# CONFIG_MACH_OMAP_INNOVATOR is not set
-CONFIG_MACH_OMAP_H6300=y
-# CONFIG_MACH_VOICEBLUE is not set
-# CONFIG_MACH_NETSTAR is not set
-# CONFIG_MACH_OMAP_PALMTE is not set
-# CONFIG_MACH_OMAP_GENERIC is not set
-
-#
-# OMAP CPU Speed
-#
-# CONFIG_OMAP_CLOCKS_SET_BY_BOOTLOADER is not set
-CONFIG_OMAP_ARM_168MHZ=y
-CONFIG_OMAP_ARM_150MHZ=y
-CONFIG_OMAP_ARM_120MHZ=y
-CONFIG_OMAP_ARM_60MHZ=y
-CONFIG_OMAP_ARM_30MHZ=y
-CONFIG_OMAP_DSP=y
-CONFIG_OMAP_DSP_MBCMD_VERBOSE=y
-CONFIG_OMAP_DSP_TASK_MULTIOPEN=y
-CONFIG_OMAP_DSP_FBEXPORT=y
-
-#
-# Processor Type
-#
-CONFIG_CPU_32=y
-CONFIG_CPU_ARM925T=y
-CONFIG_CPU_32v4=y
-CONFIG_CPU_ABRT_EV4T=y
-CONFIG_CPU_CACHE_V4WT=y
-CONFIG_CPU_CACHE_VIVT=y
-CONFIG_CPU_COPY_V4WB=y
-CONFIG_CPU_TLB_V4WBI=y
-
-#
-# Processor Features
-#
-CONFIG_ARM_THUMB=y
-# CONFIG_CPU_ICACHE_DISABLE is not set
-# CONFIG_CPU_DCACHE_DISABLE is not set
-CONFIG_CPU_DCACHE_WRITETHROUGH=y
-
-#
-# Bus support
-#
-CONFIG_ISA_DMA_API=y
-
-#
-# 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
-#
-
-#
-# Kernel Features
-#
-# CONFIG_SMP is not set
-# CONFIG_PREEMPT is not set
-# CONFIG_NO_IDLE_HZ 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_LEDS=y
-CONFIG_LEDS_TIMER=y
-CONFIG_LEDS_CPU=y
-CONFIG_ALIGNMENT_TRAP=y
-
-#
-# Boot options
-#
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="console=tty0 root=/dev/nfs nfsroot=192.168.2.1:/opt/h6300/rootfs,rsize=8192,wsize=8192 ip=192.168.2.2:192.168.2.1:192.168.2.1:255.0.0.0:ipaq:"
-# CONFIG_XIP_KERNEL is not set
-
-#
-# 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=y
-CONFIG_CPU_FREQ_GOV_USERSPACE=y
-CONFIG_CPU_FREQ_GOV_ONDEMAND=y
-# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
-
-#
-# Floating point emulation
-#
-
-#
-# At least one emulation must be selected
-#
-CONFIG_FPE_NWFPE=y
-CONFIG_FPE_NWFPE_XP=y
-# CONFIG_FPE_FASTFPE is not set
-
-#
-# Userspace binary formats
-#
-CONFIG_BINFMT_ELF=y
-CONFIG_BINFMT_AOUT=y
-CONFIG_BINFMT_MISC=y
-# CONFIG_ARTHUR is not set
-
-#
-# Power management options
-#
-CONFIG_PM=y
-CONFIG_APM=y
-
-#
-# Networking
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_UNIX=y
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_FIB_HASH=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-CONFIG_IP_PNP_RARP=y
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
-# CONFIG_ARPD is not set
-CONFIG_SYN_COOKIES=y
-CONFIG_INET_AH=m
-CONFIG_INET_ESP=m
-CONFIG_INET_IPCOMP=m
-CONFIG_INET_TUNNEL=m
-CONFIG_INET_DIAG=y
-CONFIG_INET_TCP_DIAG=y
-# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
-
-#
-# IP: Virtual Server Configuration
-#
-# CONFIG_IP_VS is not set
-CONFIG_IPV6=y
-CONFIG_IPV6_PRIVACY=y
-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
-CONFIG_BRIDGE_NETFILTER=y
-# CONFIG_NETFILTER_NETLINK is not set
-
-#
-# IP: Netfilter Configuration
-#
-CONFIG_IP_NF_CONNTRACK=m
-CONFIG_IP_NF_CT_ACCT=y
-CONFIG_IP_NF_CONNTRACK_MARK=y
-# CONFIG_IP_NF_CONNTRACK_EVENTS is not set
-CONFIG_IP_NF_CT_PROTO_SCTP=m
-CONFIG_IP_NF_FTP=m
-CONFIG_IP_NF_IRC=m
-# CONFIG_IP_NF_NETBIOS_NS is not set
-CONFIG_IP_NF_TFTP=m
-# CONFIG_IP_NF_AMANDA is not set
-# CONFIG_IP_NF_PPTP is not set
-CONFIG_IP_NF_QUEUE=m
-CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_LIMIT=m
-CONFIG_IP_NF_MATCH_IPRANGE=m
-CONFIG_IP_NF_MATCH_MAC=m
-CONFIG_IP_NF_MATCH_PKTTYPE=m
-# CONFIG_IP_NF_MATCH_MARK is not set
-# CONFIG_IP_NF_MATCH_MULTIPORT is not set
-# CONFIG_IP_NF_MATCH_TOS is not set
-# CONFIG_IP_NF_MATCH_RECENT is not set
-# CONFIG_IP_NF_MATCH_ECN is not set
-# CONFIG_IP_NF_MATCH_DSCP is not set
-# CONFIG_IP_NF_MATCH_AH_ESP is not set
-# CONFIG_IP_NF_MATCH_LENGTH is not set
-# CONFIG_IP_NF_MATCH_TTL is not set
-# CONFIG_IP_NF_MATCH_TCPMSS is not set
-# CONFIG_IP_NF_MATCH_HELPER is not set
-# CONFIG_IP_NF_MATCH_STATE is not set
-# CONFIG_IP_NF_MATCH_CONNTRACK is not set
-# CONFIG_IP_NF_MATCH_OWNER is not set
-# CONFIG_IP_NF_MATCH_PHYSDEV is not set
-# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
-# CONFIG_IP_NF_MATCH_REALM is not set
-# CONFIG_IP_NF_MATCH_SCTP is not set
-# CONFIG_IP_NF_MATCH_DCCP is not set
-# CONFIG_IP_NF_MATCH_COMMENT is not set
-# CONFIG_IP_NF_MATCH_CONNMARK is not set
-# CONFIG_IP_NF_MATCH_CONNBYTES is not set
-# CONFIG_IP_NF_MATCH_HASHLIMIT is not set
-# CONFIG_IP_NF_MATCH_STRING is not set
-# CONFIG_IP_NF_FILTER is not set
-# CONFIG_IP_NF_TARGET_LOG is not set
-# CONFIG_IP_NF_TARGET_ULOG is not set
-# CONFIG_IP_NF_TARGET_TCPMSS is not set
-# CONFIG_IP_NF_TARGET_NFQUEUE is not set
-# CONFIG_IP_NF_NAT is not set
-CONFIG_IP_NF_MANGLE=m
-# CONFIG_IP_NF_TARGET_TOS is not set
-# CONFIG_IP_NF_TARGET_ECN is not set
-# CONFIG_IP_NF_TARGET_DSCP is not set
-# CONFIG_IP_NF_TARGET_MARK is not set
-# CONFIG_IP_NF_TARGET_CLASSIFY is not set
-# CONFIG_IP_NF_TARGET_TTL is not set
-# CONFIG_IP_NF_TARGET_CONNMARK is not set
-# CONFIG_IP_NF_TARGET_CLUSTERIP is not set
-# CONFIG_IP_NF_RAW is not set
-# CONFIG_IP_NF_ARPTABLES is not set
-
-#
-# IPv6: Netfilter Configuration (EXPERIMENTAL)
-#
-CONFIG_IP6_NF_QUEUE=m
-CONFIG_IP6_NF_IPTABLES=m
-# CONFIG_IP6_NF_MATCH_LIMIT is not set
-CONFIG_IP6_NF_MATCH_MAC=m
-CONFIG_IP6_NF_MATCH_RT=m
-# CONFIG_IP6_NF_MATCH_OPTS is not set
-# CONFIG_IP6_NF_MATCH_FRAG is not set
-# CONFIG_IP6_NF_MATCH_HL is not set
-# CONFIG_IP6_NF_MATCH_MULTIPORT is not set
-# CONFIG_IP6_NF_MATCH_OWNER is not set
-# CONFIG_IP6_NF_MATCH_MARK is not set
-CONFIG_IP6_NF_MATCH_IPV6HEADER=m
-# CONFIG_IP6_NF_MATCH_AHESP is not set
-# CONFIG_IP6_NF_MATCH_LENGTH is not set
-# CONFIG_IP6_NF_MATCH_EUI64 is not set
-# CONFIG_IP6_NF_MATCH_PHYSDEV is not set
-CONFIG_IP6_NF_FILTER=m
-# CONFIG_IP6_NF_TARGET_LOG is not set
-# CONFIG_IP6_NF_TARGET_REJECT is not set
-# CONFIG_IP6_NF_TARGET_NFQUEUE is not set
-CONFIG_IP6_NF_MANGLE=m
-# CONFIG_IP6_NF_TARGET_MARK is not set
-# CONFIG_IP6_NF_TARGET_HL is not set
-CONFIG_IP6_NF_RAW=m
-
-#
-# Bridge: Netfilter Configuration
-#
-CONFIG_BRIDGE_NF_EBTABLES=m
-# CONFIG_BRIDGE_EBT_BROUTE is not set
-# CONFIG_BRIDGE_EBT_T_FILTER is not set
-# CONFIG_BRIDGE_EBT_T_NAT is not set
-# CONFIG_BRIDGE_EBT_802_3 is not set
-# CONFIG_BRIDGE_EBT_AMONG is not set
-# CONFIG_BRIDGE_EBT_ARP is not set
-# CONFIG_BRIDGE_EBT_IP is not set
-# CONFIG_BRIDGE_EBT_LIMIT is not set
-# CONFIG_BRIDGE_EBT_MARK is not set
-# CONFIG_BRIDGE_EBT_PKTTYPE is not set
-# CONFIG_BRIDGE_EBT_STP is not set
-# CONFIG_BRIDGE_EBT_VLAN is not set
-# CONFIG_BRIDGE_EBT_ARPREPLY is not set
-# CONFIG_BRIDGE_EBT_DNAT is not set
-# CONFIG_BRIDGE_EBT_MARK_T is not set
-# CONFIG_BRIDGE_EBT_REDIRECT is not set
-# CONFIG_BRIDGE_EBT_SNAT is not set
-# CONFIG_BRIDGE_EBT_LOG is not set
-# CONFIG_BRIDGE_EBT_ULOG is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-CONFIG_BRIDGE=y
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_HAMRADIO is not set
-CONFIG_IRDA=m
-
-#
-# IrDA protocols
-#
-CONFIG_IRLAN=m
-CONFIG_IRNET=m
-CONFIG_IRCOMM=m
-CONFIG_IRDA_ULTRA=y
-
-#
-# IrDA options
-#
-CONFIG_IRDA_CACHE_LAST_LSAP=y
-CONFIG_IRDA_FAST_RR=y
-# CONFIG_IRDA_DEBUG is not set
-
-#
-# Infrared-port device drivers
-#
-
-#
-# SIR device drivers
-#
-# CONFIG_IRTTY_SIR 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_NSC_FIR is not set
-# CONFIG_WINBOND_FIR is not set
-CONFIG_OMAP1610_IR=m
-CONFIG_SMC_IRCC_FIR=m
-# CONFIG_ALI_FIR is not set
-# CONFIG_VIA_FIR is not set
-CONFIG_BT=m
-CONFIG_BT_L2CAP=m
-# CONFIG_BT_SCO is not set
-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_HCIUART_BCSP_TXCRC is not set
-# CONFIG_BT_HCIBCM203X is not set
-# CONFIG_BT_HCIBPA10X is not set
-# CONFIG_BT_HCIBFUSB is not set
-# CONFIG_BT_HCIDTL1 is not set
-# CONFIG_BT_HCIBT3C is not set
-# CONFIG_BT_HCIBLUECARD is not set
-# CONFIG_BT_HCIBTUART is not set
-CONFIG_BT_HCIVHCI=m
-CONFIG_BT_H6300=m
-# CONFIG_IEEE80211 is not set
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-CONFIG_FW_LOADER=y
-# CONFIG_DEBUG_DRIVER is not set
-
-#
-# Memory Technology Devices (MTD)
-#
-CONFIG_MTD=y
-# CONFIG_MTD_DEBUG is not set
-CONFIG_MTD_CONCAT=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_REDBOOT_PARTS=y
-CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
-# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
-# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
-# CONFIG_MTD_CMDLINE_PARTS is not set
-# CONFIG_MTD_AFS_PARTS is not set
-
-#
-# User Modules And Translation Layers
-#
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-# CONFIG_FTL is not set
-# CONFIG_NFTL is not set
-# CONFIG_INFTL is not set
-
-#
-# RAM/ROM/Flash chip drivers
-#
-CONFIG_MTD_CFI=m
-CONFIG_MTD_JEDECPROBE=m
-CONFIG_MTD_GEN_PROBE=m
-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=m
-CONFIG_MTD_CFI_AMDSTD=m
-CONFIG_MTD_CFI_AMDSTD_RETRY=1
-CONFIG_MTD_CFI_STAA=m
-CONFIG_MTD_CFI_UTIL=m
-# CONFIG_MTD_RAM is not set
-# CONFIG_MTD_ROM is not set
-CONFIG_MTD_ABSENT=m
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
-# CONFIG_MTD_XIP is not set
-
-#
-# Mapping drivers for chip access
-#
-CONFIG_MTD_COMPLEX_MAPPINGS=y
-CONFIG_MTD_PHYSMAP=m
-CONFIG_MTD_PHYSMAP_START=0x8000000
-CONFIG_MTD_PHYSMAP_LEN=0x4000000
-CONFIG_MTD_PHYSMAP_BANKWIDTH=2
-# CONFIG_MTD_ARM_INTEGRATOR is not set
-# CONFIG_MTD_EDB7312 is not set
-# CONFIG_MTD_IMPA7 is not set
-# CONFIG_MTD_OMAP_NOR is not set
-# CONFIG_MTD_PCMCIA is not set
-# CONFIG_MTD_PLATRAM is not set
-
-#
-# Self-contained MTD device drivers
-#
-CONFIG_MTD_SLRAM=m
-CONFIG_MTD_PHRAM=m
-CONFIG_MTD_MTDRAM=m
-CONFIG_MTDRAM_TOTAL_SIZE=4096
-CONFIG_MTDRAM_ERASE_SIZE=128
-CONFIG_MTD_BLKMTD=m
-# CONFIG_MTD_BLOCK2MTD is not set
-
-#
-# Disk-On-Chip Device Drivers
-#
-CONFIG_MTD_DOC2000=m
-CONFIG_MTD_DOC2001=m
-CONFIG_MTD_DOC2001PLUS=m
-CONFIG_MTD_DOCPROBE=m
-CONFIG_MTD_DOCECC=m
-CONFIG_MTD_DOCPROBE_ADVANCED=y
-CONFIG_MTD_DOCPROBE_ADDRESS=0x0000
-CONFIG_MTD_DOCPROBE_HIGH=y
-CONFIG_MTD_DOCPROBE_55AA=y
-
-#
-# NAND Flash Device Drivers
-#
-CONFIG_MTD_NAND=m
-# CONFIG_MTD_NAND_VERIFY_WRITE is not set
-# CONFIG_MTD_NAND_TOTO is not set
-CONFIG_MTD_NAND_IDS=m
-CONFIG_MTD_NAND_DISKONCHIP=m
-CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED=y
-CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0x0
-# CONFIG_MTD_NAND_DISKONCHIP_PROBE_HIGH is not set
-CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE=y
-# CONFIG_MTD_NAND_NANDSIM is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_COW_COMMON is not set
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_CRYPTOLOOP=m
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_UB is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_BLK_DEV_RAM_SIZE=16384
-CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CDROM_PKTCDVD is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-# CONFIG_ATA_OVER_ETH is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-# CONFIG_RAID_ATTRS is not set
-# CONFIG_SCSI is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-
-#
-# Network device support
-#
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-
-#
-# PHY device support
-#
-# CONFIG_PHYLIB is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-CONFIG_SMC91X=y
-# CONFIG_DM9000 is not set
-
-#
-# 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=y
-# 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_AIRO is not set
-# CONFIG_HERMES is not set
-CONFIG_ATMEL=y
-
-#
-# Wireless 802.11b Pcmcia/Cardbus cards support
-#
-# CONFIG_AIRO_CS is not set
-# CONFIG_PCMCIA_ATMEL is not set
-# CONFIG_PCMCIA_WL3501 is not set
-# CONFIG_HOSTAP is not set
-CONFIG_NET_WIRELESS=y
-CONFIG_ACX=m
-# CONFIG_ACX_USB is not set
-CONFIG_ACX_CFI=y
-
-#
-# PCMCIA network device support
-#
-# CONFIG_NET_PCMCIA is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-CONFIG_PPP=y
-CONFIG_PPP_MULTILINK=y
-CONFIG_PPP_FILTER=y
-CONFIG_PPP_ASYNC=y
-CONFIG_PPP_SYNC_TTY=y
-CONFIG_PPP_DEFLATE=y
-CONFIG_PPP_BSDCOMP=y
-CONFIG_PPPOE=y
-# 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 is not set
-# 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
-
-#
-# 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_OMAP=m
-CONFIG_INPUT_MOUSE=y
-CONFIG_MOUSE_PS2=y
-CONFIG_MOUSE_SERIAL=y
-# CONFIG_MOUSE_VSXXXAA 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_OMAP=m
-CONFIG_INPUT_MISC=y
-CONFIG_INPUT_UINPUT=m
-
-#
-# Hardware I/O ports
-#
-CONFIG_SERIO=y
-CONFIG_SERIO_SERPORT=y
-CONFIG_SERIO_LIBPS2=y
-CONFIG_SERIO_RAW=y
-# 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=y
-# CONFIG_SERIAL_8250_CONSOLE is not set
-# CONFIG_SERIAL_8250_CS is not set
-CONFIG_SERIAL_8250_NR_UARTS=4
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_UNIX98_PTYS=y
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-CONFIG_WATCHDOG=y
-CONFIG_WATCHDOG_NOWAYOUT=y
-
-#
-# Watchdog Device Drivers
-#
-CONFIG_SOFT_WATCHDOG=m
-
-#
-# USB-based Watchdog Cards
-#
-# CONFIG_USBPCWATCHDOG is not set
-CONFIG_NVRAM=y
-# CONFIG_RTC is not set
-CONFIG_OMAP_RTC=y
-# 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_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
-
-#
-# I2C support
-#
-CONFIG_I2C=m
-CONFIG_I2C_CHARDEV=m
-
-#
-# I2C Algorithms
-#
-CONFIG_I2C_ALGOBIT=m
-CONFIG_I2C_ALGOPCF=m
-CONFIG_I2C_ALGOPCA=m
-
-#
-# I2C Hardware Bus support
-#
-CONFIG_I2C_PARPORT_LIGHT=m
-# CONFIG_I2C_STUB is not set
-# CONFIG_I2C_PCA_ISA is not set
-CONFIG_I2C_OMAP=m
-
-#
-# 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_PCA9535=m
-# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_RTC8564 is not set
-# CONFIG_TPS65010 is not set
-CONFIG_SENSORS_TLV320AIC23=m
-# CONFIG_SENSORS_MAX6875 is not set
-# CONFIG_I2C_DEBUG_CORE is not set
-# CONFIG_I2C_DEBUG_ALGO is not set
-# CONFIG_I2C_DEBUG_BUS is not set
-# CONFIG_I2C_DEBUG_CHIP is not set
-
-#
-# Hardware Monitoring support
-#
-CONFIG_HWMON=y
-# CONFIG_HWMON_VID is not set
-# CONFIG_SENSORS_ADM1021 is not set
-# CONFIG_SENSORS_ADM1025 is not set
-# CONFIG_SENSORS_ADM1026 is not set
-# CONFIG_SENSORS_ADM1031 is not set
-# CONFIG_SENSORS_ADM9240 is not set
-# CONFIG_SENSORS_ASB100 is not set
-# CONFIG_SENSORS_ATXP1 is not set
-# CONFIG_SENSORS_DS1621 is not set
-# CONFIG_SENSORS_FSCHER is not set
-# CONFIG_SENSORS_FSCPOS is not set
-# CONFIG_SENSORS_GL518SM is not set
-# CONFIG_SENSORS_GL520SM is not set
-# CONFIG_SENSORS_IT87 is not set
-# CONFIG_SENSORS_LM63 is not set
-# CONFIG_SENSORS_LM75 is not set
-# CONFIG_SENSORS_LM77 is not set
-# CONFIG_SENSORS_LM78 is not set
-# CONFIG_SENSORS_LM80 is not set
-# CONFIG_SENSORS_LM83 is not set
-# CONFIG_SENSORS_LM85 is not set
-# CONFIG_SENSORS_LM87 is not set
-# CONFIG_SENSORS_LM90 is not set
-# CONFIG_SENSORS_LM92 is not set
-# CONFIG_SENSORS_MAX1619 is not set
-# CONFIG_SENSORS_PC87360 is not set
-# CONFIG_SENSORS_SMSC47M1 is not set
-# CONFIG_SENSORS_SMSC47B397 is not set
-# CONFIG_SENSORS_W83781D is not set
-# CONFIG_SENSORS_W83792D is not set
-# CONFIG_SENSORS_W83L785TS is not set
-# CONFIG_SENSORS_W83627HF is not set
-# CONFIG_SENSORS_W83627EHF is not set
-# CONFIG_HWMON_DEBUG_CHIP is not set
-
-#
-# Misc devices
-#
-
-#
-# Multimedia Capabilities Port drivers
-#
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# Graphics support
-#
-CONFIG_FB=y
-# CONFIG_FB_CFB_FILLRECT is not set
-# CONFIG_FB_CFB_COPYAREA is not set
-# CONFIG_FB_CFB_IMAGEBLIT is not set
-CONFIG_FB_SOFT_CURSOR=y
-# CONFIG_FB_MACMODES is not set
-CONFIG_FB_MODE_HELPERS=y
-# CONFIG_FB_TILEBLITTING is not set
-# CONFIG_FB_S1D13XXX is not set
-CONFIG_FB_OMAP=y
-CONFIG_FB_OMAP_LCDC_INTERNAL=y
-# CONFIG_FB_OMAP_LCDC_EXTERNAL is not set
-CONFIG_FB_OMAP_DMA_TUNE=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_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
-
-#
-# Logo configuration
-#
-CONFIG_LOGO=y
-# CONFIG_LOGO_LINUX_MONO is not set
-CONFIG_LOGO_LINUX_VGA16=y
-# 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=y
-CONFIG_LCD_DEVICE=y
-
-#
-# Telephony Support
-#
-CONFIG_PHONE=m
-# CONFIG_PHONE_IXJ is not set
-CONFIG_GSM_H6300=m
-
-#
-# Sound
-#
-CONFIG_SOUND=m
-
-#
-# Advanced Linux Sound Architecture
-#
-# CONFIG_SND is not set
-
-#
-# Open Sound System
-#
-CONFIG_SOUND_PRIME=m
-CONFIG_SOUND_OMAP=m
-CONFIG_SOUND_OMAP_TSC2101=m
-# CONFIG_SOUND_MSNDCLAS is not set
-# CONFIG_SOUND_MSNDPIN is not set
-# CONFIG_SOUND_OSS is not set
-# CONFIG_SOUND_TVMIXER is not set
-# CONFIG_SOUND_AD1980 is not set
-
-#
-# USB support
-#
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
-CONFIG_USB=y
-CONFIG_USB_DEBUG=y
-
-#
-# Miscellaneous USB options
-#
-CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_BANDWIDTH is not set
-# CONFIG_USB_DYNAMIC_MINORS is not set
-# CONFIG_USB_SUSPEND is not set
-# CONFIG_USB_OTG is not set
-
-#
-# USB Host Controller Drivers
-#
-# CONFIG_USB_ISP116X_HCD is not set
-CONFIG_USB_OHCI_HCD=y
-# CONFIG_USB_OHCI_BIG_ENDIAN is not set
-CONFIG_USB_OHCI_LITTLE_ENDIAN=y
-# CONFIG_USB_SL811_HCD is not set
-
-#
-# USB Device Class drivers
-#
-# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set
-
-#
-# USB Bluetooth TTY can only be used with disabled Bluetooth subsystem
-#
-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 is not set
-
-#
-# USB Input Devices
-#
-# CONFIG_USB_HID is not set
-
-#
-# USB HID Boot Protocol drivers
-#
-# CONFIG_USB_KBD is not set
-# CONFIG_USB_MOUSE is not set
-# CONFIG_USB_AIPTEK is not set
-# CONFIG_USB_WACOM is not set
-# CONFIG_USB_ACECAD is not set
-# CONFIG_USB_KBTAB is not set
-# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_MTOUCH is not set
-# CONFIG_USB_ITMTOUCH is not set
-# CONFIG_USB_EGALAX is not set
-# CONFIG_USB_YEALINK is not set
-# CONFIG_USB_XPAD is not set
-# CONFIG_USB_ATI_REMOTE is not set
-# CONFIG_USB_KEYSPAN_REMOTE is not set
-# CONFIG_USB_APPLETOUCH is not set
-
-#
-# USB Imaging devices
-#
-# CONFIG_USB_MDC800 is not set
-
-#
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
-# USB Network Adapters
-#
-# CONFIG_USB_CATC is not set
-# CONFIG_USB_KAWETH is not set
-# CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_RTL8150 is not set
-CONFIG_USB_USBNET=y
-CONFIG_USB_NET_AX8817X=y
-CONFIG_USB_NET_CDCETHER=y
-# CONFIG_USB_NET_GL620A is not set
-CONFIG_USB_NET_NET1080=y
-# CONFIG_USB_NET_PLUSB is not set
-# CONFIG_USB_NET_RNDIS_HOST is not set
-# CONFIG_USB_NET_CDC_SUBSET is not set
-CONFIG_USB_NET_ZAURUS=y
-# CONFIG_USB_ZD1201 is not set
-CONFIG_USB_MON=y
-
-#
-# USB port drivers
-#
-
-#
-# USB Serial Converter support
-#
-CONFIG_USB_SERIAL=y
-CONFIG_USB_SERIAL_CONSOLE=y
-CONFIG_USB_SERIAL_GENERIC=y
-# CONFIG_USB_SERIAL_AIRPRIME is not set
-# CONFIG_USB_SERIAL_BELKIN is not set
-# CONFIG_USB_SERIAL_WHITEHEAT is not set
-# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
-# CONFIG_USB_SERIAL_CP2101 is not set
-# CONFIG_USB_SERIAL_CYPRESS_M8 is not set
-# CONFIG_USB_SERIAL_EMPEG is not set
-# CONFIG_USB_SERIAL_FTDI_SIO is not set
-CONFIG_USB_SERIAL_VISOR=y
-CONFIG_USB_SERIAL_IPAQ=y
-# CONFIG_USB_SERIAL_IR is not set
-# CONFIG_USB_SERIAL_EDGEPORT is not set
-# CONFIG_USB_SERIAL_EDGEPORT_TI is not set
-# CONFIG_USB_SERIAL_GARMIN is not set
-# CONFIG_USB_SERIAL_IPW is not set
-# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
-# CONFIG_USB_SERIAL_KEYSPAN is not set
-# CONFIG_USB_SERIAL_KLSI is not set
-# CONFIG_USB_SERIAL_KOBIL_SCT is not set
-# CONFIG_USB_SERIAL_MCT_U232 is not set
-# CONFIG_USB_SERIAL_PL2303 is not set
-# CONFIG_USB_SERIAL_HP4X is not set
-# CONFIG_USB_SERIAL_SAFE is not set
-# CONFIG_USB_SERIAL_TI is not set
-# CONFIG_USB_SERIAL_CYBERJACK is not set
-# CONFIG_USB_SERIAL_XIRCOM is not set
-# CONFIG_USB_SERIAL_OPTION is not set
-# CONFIG_USB_SERIAL_OMNINET is not set
-
-#
-# USB Miscellaneous drivers
-#
-# CONFIG_USB_EMI62 is not set
-# CONFIG_USB_EMI26 is not set
-# CONFIG_USB_AUERSWALD is not set
-# CONFIG_USB_RIO500 is not set
-# CONFIG_USB_LEGOTOWER is not set
-# CONFIG_USB_LCD is not set
-# CONFIG_USB_LED is not set
-# CONFIG_USB_CYTHERM is not set
-# CONFIG_USB_PHIDGETKIT is not set
-# CONFIG_USB_PHIDGETSERVO is not set
-# CONFIG_USB_IDMOUSE is not set
-# CONFIG_USB_LD is not set
-# CONFIG_USB_TEST is not set
-
-#
-# USB DSL modem support
-#
-
-#
-# USB Gadget Support
-#
-CONFIG_USB_GADGET=y
-CONFIG_USB_GADGET_DEBUG_FILES=y
-CONFIG_USB_GADGET_SELECTED=y
-# CONFIG_USB_GADGET_NET2280 is not set
-# CONFIG_USB_GADGET_PXA2XX is not set
-# CONFIG_USB_GADGET_GOKU is not set
-# CONFIG_USB_GADGET_LH7A40X is not set
-CONFIG_USB_GADGET_OMAP=y
-CONFIG_USB_OMAP=y
-# CONFIG_USB_GADGET_DUMMY_HCD is not set
-# CONFIG_USB_GADGET_DUALSPEED is not set
-# CONFIG_USB_ZERO is not set
-CONFIG_USB_ETH=y
-# CONFIG_USB_ETH_RNDIS is not set
-# CONFIG_USB_GADGETFS is not set
-# CONFIG_USB_FILE_STORAGE is not set
-# CONFIG_USB_G_SERIAL is not set
-
-#
-# MMC/SD Card support
-#
-CONFIG_MMC=y
-# CONFIG_MMC_DEBUG is not set
-CONFIG_MMC_BLOCK=y
-CONFIG_MMC_BLOCK_BROKEN_RFD=y
-CONFIG_MMC_BULKTRANSFER=y
-CONFIG_MMC_OMAP=y
-# CONFIG_MMC_WBSD is not set
-
-#
-# Synchronous Serial Interfaces (SSI)
-#
-CONFIG_OMAP_UWIRE=y
-CONFIG_OMAP_TSC2101=y
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_EXT2_FS_POSIX_ACL=y
-CONFIG_EXT2_FS_SECURITY=y
-# CONFIG_EXT2_FS_XIP is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
-CONFIG_FS_MBCACHE=y
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-CONFIG_FS_POSIX_ACL=y
-# CONFIG_XFS_FS is not set
-# CONFIG_MINIX_FS is not set
-CONFIG_ROMFS_FS=y
-CONFIG_INOTIFY=y
-# CONFIG_QUOTA is not set
-# CONFIG_DNOTIFY is not set
-# CONFIG_AUTOFS_FS is not set
-CONFIG_AUTOFS4_FS=y
-# CONFIG_FUSE_FS is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-CONFIG_FAT_FS=y
-CONFIG_MSDOS_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_FAT_DEFAULT_CODEPAGE=437
-CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_SYSFS=y
-CONFIG_TMPFS=y
-# CONFIG_HUGETLBFS is not set
-# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_HFSPLUS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-CONFIG_JFFS_FS=y
-CONFIG_JFFS_FS_VERBOSE=0
-CONFIG_JFFS_PROC_FS=y
-CONFIG_JFFS2_FS=y
-CONFIG_JFFS2_FS_DEBUG=4
-CONFIG_JFFS2_FS_WRITEBUFFER=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=y
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-# CONFIG_NFS_V3_ACL is not set
-CONFIG_NFS_V4=y
-# CONFIG_NFS_DIRECTIO is not set
-# CONFIG_NFSD is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-CONFIG_NFS_COMMON=y
-CONFIG_SUNRPC=y
-CONFIG_SUNRPC_GSS=y
-CONFIG_RPCSEC_GSS_KRB5=y
-# CONFIG_RPCSEC_GSS_SPKM3 is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_AFS_FS is not set
-# CONFIG_9P_FS is not set
-
-#
-# Partition Types
-#
-CONFIG_PARTITION_ADVANCED=y
-# CONFIG_ACORN_PARTITION is not set
-# CONFIG_OSF_PARTITION is not set
-# CONFIG_AMIGA_PARTITION is not set
-# CONFIG_ATARI_PARTITION is not set
-# CONFIG_MAC_PARTITION is not set
-CONFIG_MSDOS_PARTITION=y
-# CONFIG_BSD_DISKLABEL is not set
-# CONFIG_MINIX_SUBPARTITION is not set
-# CONFIG_SOLARIS_X86_PARTITION is not set
-# CONFIG_UNIXWARE_DISKLABEL is not set
-# CONFIG_LDM_PARTITION is not set
-# CONFIG_SGI_PARTITION is not set
-# CONFIG_ULTRIX_PARTITION is not set
-# CONFIG_SUN_PARTITION is not set
-# CONFIG_EFI_PARTITION is not set
-
-#
-# Native Language Support
-#
-CONFIG_NLS=y
-CONFIG_NLS_DEFAULT="utf8"
-CONFIG_NLS_CODEPAGE_437=y
-# CONFIG_NLS_CODEPAGE_737 is not set
-# CONFIG_NLS_CODEPAGE_775 is not set
-# CONFIG_NLS_CODEPAGE_850 is not set
-# CONFIG_NLS_CODEPAGE_852 is not set
-# CONFIG_NLS_CODEPAGE_855 is not set
-# CONFIG_NLS_CODEPAGE_857 is not set
-# CONFIG_NLS_CODEPAGE_860 is not set
-# CONFIG_NLS_CODEPAGE_861 is not set
-# CONFIG_NLS_CODEPAGE_862 is not set
-# CONFIG_NLS_CODEPAGE_863 is not set
-# CONFIG_NLS_CODEPAGE_864 is not set
-# CONFIG_NLS_CODEPAGE_865 is not set
-# CONFIG_NLS_CODEPAGE_866 is not set
-# CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_936 is not set
-# CONFIG_NLS_CODEPAGE_950 is not set
-# CONFIG_NLS_CODEPAGE_932 is not set
-# CONFIG_NLS_CODEPAGE_949 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_ISO8859_8 is not set
-# CONFIG_NLS_CODEPAGE_1250 is not set
-# CONFIG_NLS_CODEPAGE_1251 is not set
-# CONFIG_NLS_ASCII 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 is not set
-
-#
-# Kernel hacking
-#
-# CONFIG_PRINTK_TIME is not set
-CONFIG_DEBUG_KERNEL=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_LOG_BUF_SHIFT=17
-CONFIG_DETECT_SOFTLOCKUP=y
-# CONFIG_SCHEDSTATS is not set
-# CONFIG_DEBUG_SLAB is not set
-# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
-# CONFIG_DEBUG_KOBJECT is not set
-# CONFIG_DEBUG_BUGVERBOSE is not set
-# CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_FS is not set
-CONFIG_FRAME_POINTER=y
-# CONFIG_DEBUG_USER is not set
-# CONFIG_DEBUG_WAITQ is not set
-CONFIG_DEBUG_ERRORS=y
-CONFIG_DEBUG_LL=y
-# CONFIG_DEBUG_ICEDCC is not set
-
-#
-# Security options
-#
-# CONFIG_KEYS is not set
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_HMAC=y
-# 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_DES=y
-# CONFIG_CRYPTO_BLOWFISH is not set
-# CONFIG_CRYPTO_TWOFISH is not set
-# CONFIG_CRYPTO_SERPENT is not set
-# CONFIG_CRYPTO_AES is not set
-# CONFIG_CRYPTO_CAST5 is not set
-# CONFIG_CRYPTO_CAST6 is not set
-# CONFIG_CRYPTO_TEA is not set
-# CONFIG_CRYPTO_ARC4 is not set
-# CONFIG_CRYPTO_KHAZAD is not set
-# CONFIG_CRYPTO_ANUBIS is not set
-CONFIG_CRYPTO_DEFLATE=m
-# CONFIG_CRYPTO_MICHAEL_MIC is not set
-# CONFIG_CRYPTO_CRC32C is not set
-# CONFIG_CRYPTO_TEST is not set
-
-#
-# Hardware crypto devices
-#
-
-#
-# Library routines
-#
-CONFIG_CRC_CCITT=y
-# CONFIG_CRC16 is not set
-CONFIG_CRC32=y
-CONFIG_LIBCRC32C=y
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
-CONFIG_REED_SOLOMON=m
-CONFIG_REED_SOLOMON_DEC16=y
diff --git a/packages/linux/linux-h6300-omap1-2.6.14-rc5/h6300_omap1_2614rc5.patch b/packages/linux/linux-h6300-omap1-2.6.14-rc5/h6300_omap1_2614rc5.patch
deleted file mode 100644 (file)
index 435a5f1..0000000
+++ /dev/null
@@ -1,30881 +0,0 @@
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/arch/arm/Kconfig bt_kernel/arch/arm/Kconfig
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/arch/arm/Kconfig    2005-10-30 17:44:14.719521158 +0200
-+++ bt_kernel/arch/arm/Kconfig 2005-10-14 18:55:31.156317000 +0300
-@@ -725,6 +725,8 @@
- source "drivers/video/Kconfig"
-+source "drivers/telephony/Kconfig"
-+
- source "sound/Kconfig"
- source "drivers/usb/Kconfig"
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/arch/arm/mach-omap1/board-h6300.c bt_kernel/arch/arm/mach-omap1/board-h6300.c
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/arch/arm/mach-omap1/board-h6300.c   1970-01-01 02:00:00.000000000 +0200
-+++ bt_kernel/arch/arm/mach-omap1/board-h6300.c        2005-10-22 03:52:45.687256000 +0300
-@@ -0,0 +1,317 @@
-+/*
-+ * Modified from board-h6300.c
-+ *
-+ * Code for generic OMAP board. Should work on many OMAP systems where
-+ * the device drivers take care of all the necessary hardware initialization.
-+ * Do not put any board specific code to this file; create a new machine
-+ * type if you need custom low-level initializations.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/init.h>
-+#include <linux/device.h>
-+#include <linux/delay.h>
-+#include <linux/mtd/mtd.h>
-+#include <linux/mtd/partitions.h>
-+
-+#include <asm/hardware.h>
-+#include <asm/mach-types.h>
-+#include <asm/mach/arch.h>
-+#include <asm/mach/flash.h>
-+#include <asm/mach/map.h>
-+
-+#include <asm/arch/gpio.h>
-+
-+#include <asm/arch/tc.h>
-+#include <asm/arch/usb.h>
-+
-+#include <asm/arch/common.h>
-+
-+#include <asm/arch/h6300_uart_info.h>
-+
-+/*
-+ * Bluetooth - Relies on h6300_bt module,
-+ * so make the calls indirectly through pointers. Requires that the
-+ * h6300_bt bluetooth module be loaded before any attempt to use
-+ * bluetooth (obviously).
-+ */
-+
-+static struct h6300_uart_funcs bt_funcs;
-+static struct h6300_uart_funcs gsm_funcs;
-+
-+static void
-+h6300_bt_configure(struct uart_omap_port *up, int enable)
-+{
-+      printk(KERN_NOTICE "board-h6300.c, h6300_bt_configure() started\n");
-+      if (bt_funcs.configure != NULL)
-+              bt_funcs.configure(up, enable);
-+      printk(KERN_NOTICE "board-h6300.c, h6300_bt_configure() done\n");
-+}
-+
-+static void
-+h6300_bt_set_txrx(struct uart_omap_port *up, int txrx)
-+{
-+      printk(KERN_NOTICE "board-h6300.c, h6300_bt_set_txrx() started\n");
-+      if (bt_funcs.set_txrx != NULL)
-+      {
-+              printk(KERN_NOTICE "board-h6300.c, h6300_bt_set_txrx(), bt_funcs.set_txrx != NULL\n");
-+              bt_funcs.set_txrx(up, txrx);
-+      }
-+      printk(KERN_NOTICE "board-h6300.c, h6300_bt_set_txrx() done\n");
-+}
-+
-+static int
-+h6300_bt_get_txrx(struct uart_omap_port *up)
-+{
-+      int     retVal;
-+      
-+      printk(KERN_NOTICE "board-h6300.c, h6300_bt_get_txrx() started\n");
-+      if (bt_funcs.get_txrx != NULL)
-+      {
-+              retVal  = bt_funcs.get_txrx(up);
-+              printk(KERN_NOTICE "board-h6300.c, h6300_bt_get_txrx(), bt_funcs.get_trx != null, done, retVal %d\n", retVal);
-+              return retVal;
-+      }
-+      else
-+      {
-+              printk(KERN_NOTICE "board-h6300.c, h6300_bt_get_txrx() done, returning 0\n");
-+              return 0;
-+      }
-+}
-+
-+static struct platform_omap_serial_funcs h6300_omap_bt_funcs = {
-+      .configure      = h6300_bt_configure,
-+      .set_txrx       = h6300_bt_set_txrx,
-+      .get_txrx       = h6300_bt_get_txrx,
-+};
-+
-+struct platform_device btuart_device = {
-+      .name   = "h6300_bt",
-+      .id     = 1,
-+};
-+EXPORT_SYMBOL(btuart_device);
-+
-+static void
-+h6300_gsm_configure(struct uart_omap_port *up, int enable)
-+{
-+      printk(KERN_NOTICE "board-h6300.c, h6300_gsm_configure() started\n");
-+      if (gsm_funcs.configure != NULL)
-+              gsm_funcs.configure(up, enable);
-+      printk(KERN_NOTICE "board-h6300.c, h6300_gsm_configure() done\n");
-+}
-+
-+static void
-+h6300_gsm_set_txrx(struct uart_omap_port *up, int txrx)
-+{
-+      printk(KERN_NOTICE "board-h6300.c, h6300_gsm_set_txrx() started\n");
-+      if (bt_funcs.set_txrx != NULL)
-+      {
-+              printk(KERN_NOTICE "board-h6300.c, h6300_gsm_set_txrx(), bt_funcs.set_txrx != NULL\n");
-+              gsm_funcs.set_txrx(up, txrx);
-+      }
-+      printk(KERN_NOTICE "board-h6300.c, h6300_gsm_set_txrx() done\n");
-+}
-+
-+static int
-+h6300_gsm_get_txrx(struct uart_omap_port *up)
-+{
-+      int     retVal;
-+      
-+      printk(KERN_NOTICE "board-h6300.c, h6300_gsm_get_txrx() started\n");
-+      if (bt_funcs.get_txrx != NULL)
-+      {
-+              retVal  = gsm_funcs.get_txrx(up);
-+              printk(KERN_NOTICE "board-h6300.c, h6300_gsm_get_txrx(), bt_funcs.get_trx != null, done, retVal %d\n", retVal);
-+              return retVal;
-+      }
-+      else
-+      {
-+              printk(KERN_NOTICE "board-h6300.c, h6300_gsm_get_txrx() done, returning 0\n");
-+              return 0;
-+      }
-+}
-+
-+static struct platform_omap_serial_funcs h6300_omap_gsm_funcs = {
-+      .configure      = h6300_gsm_configure,
-+      .set_txrx       = h6300_gsm_set_txrx,
-+      .get_txrx       = h6300_gsm_get_txrx,
-+};
-+
-+struct platform_device gsmuart_device = {
-+      .name   = "h6300_gsm",
-+      .id     = 1,
-+};
-+EXPORT_SYMBOL(gsmuart_device);
-+
-+#if 0
-+static struct mtd_partition h6300_partitions[] = {
-+      /* bootloader (U-Boot, etc) in first sector */
-+      {
-+            .name             = "bootloader",
-+            .offset           = 0,
-+            .size             = SZ_128K,
-+            .mask_flags       = MTD_WRITEABLE, /* force read-only */
-+      },
-+      /* bootloader params in the next sector */
-+      {
-+            .name             = "params",
-+            .offset           = MTDPART_OFS_APPEND,
-+            .size             = SZ_128K,
-+            .mask_flags       = 0,
-+      },
-+      /* kernel */
-+      {
-+            .name             = "kernel",
-+            .offset           = MTDPART_OFS_APPEND,
-+            .size             = SZ_2M,
-+            .mask_flags       = 0
-+      },
-+      /* rest of flash1 is a file system */
-+      {
-+            .name             = "rootfs",
-+            .offset           = MTDPART_OFS_APPEND,
-+            .size             = SZ_16M - SZ_2M - 2 * SZ_128K,
-+            .mask_flags       = 0
-+      },
-+      /* file system */
-+      {
-+            .name             = "filesystem",
-+            .offset           = MTDPART_OFS_APPEND,
-+            .size             = MTDPART_SIZ_FULL,
-+            .mask_flags       = 0
-+      }
-+};
-+
-+static struct flash_platform_data h6300_flash_data = {
-+      .map_name       = "cfi_probe",
-+      .width          = 2,
-+      .parts          = h6300_partitions,
-+      .nr_parts       = ARRAY_SIZE(h6300_partitions),
-+};
-+
-+static struct resource h6300_flash_resource = {
-+      .start          = OMAP_CS0_PHYS,
-+      .end            = OMAP_CS0_PHYS + SZ_32M - 1,
-+      .flags          = IORESOURCE_MEM,
-+};
-+
-+static struct platform_device h6300_flash_device = {
-+      .name   = "omapflash",
-+      .id             = 0,
-+      .dev    = {
-+              .platform_data  = &h6300_flash_data,
-+      },
-+      .num_resources  = 1,
-+      .resource       = &h6300_flash_resource,
-+};
-+#endif
-+
-+static struct resource h6300_wlan_resource[] = {
-+        [0] = {
-+                .start          = OMAP_CS1_PHYS,
-+                .end            = OMAP_CS1_PHYS + SZ_32M -1,
-+                .flags          = IORESOURCE_MEM,
-+        },
-+
-+        [1] = {
-+                .start  = OMAP_GPIO_IRQ(11),
-+                .end    = OMAP_GPIO_IRQ(11),
-+                .flags  = IORESOURCE_IRQ,
-+        },
-+};
-+
-+static struct platform_device h6300_wlan_device = {
-+        .name           = "tnetw1100b",
-+        .id             = 0,
-+        .num_resources  = 2,
-+        .resource       = h6300_wlan_resource,
-+};
-+
-+static struct platform_device *h6300_devices[] __initdata = {
-+      &btuart_device,
-+      &gsmuart_device,
-+      &h6300_wlan_device,
-+      //&h6300_flash_device,
-+};
-+
-+static void __init h6300_init_irq(void)
-+{
-+      omap_init_irq();
-+      omap_gpio_init();
-+
-+      omap_request_gpio (2);
-+      omap_set_gpio_direction (2, 0);
-+      omap_set_gpio_dataout (2, 1);
-+}
-+
-+/* assume no Mini-AB port */
-+
-+static struct omap_usb_config h6300_usb_config __initdata = {
-+      .hmc_mode       = 0,
-+      .register_dev   = 1,
-+      .pins[0]        = 0,
-+};
-+
-+static struct omap_lcd_config h6300_lcd_config __initdata = {
-+      .panel_name     = "h6300",
-+      .ctrl_name      = "internal",
-+};
-+
-+static struct omap_mmc_config h6300_mmc_config __initdata = {
-+      .mmc [0] = {
-+              .enabled        = 1,
-+              .wire4          = 1,
-+              .wp_pin         = OMAP_GPIO_IRQ(13),
-+              .power_pin      = -1,   /* FPGA F3 UIO42 */
-+              .switch_pin     = -1,   /* FPGA F4 UIO43 */
-+      },
-+};
-+
-+static struct omap_uart_config h6300_uart_config __initdata = {
-+      .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)),
-+};
-+
-+static struct omap_board_config_kernel h6300_config[] = {
-+      { OMAP_TAG_USB, &h6300_usb_config },
-+      { OMAP_TAG_MMC, &h6300_mmc_config },
-+      { OMAP_TAG_UART,        &h6300_uart_config },
-+      { OMAP_TAG_LCD, &h6300_lcd_config },
-+};
-+
-+static void __init h6300_init(void)
-+{
-+      int ret;
-+      
-+      ret = platform_add_devices(h6300_devices, ARRAY_SIZE(h6300_devices));
-+      if (ret) 
-+      {
-+              printk(KERN_WARNING "Unable to add h6300 platform devices like bluetooth");
-+      }
-+      omap_board_config               = h6300_config;
-+      omap_board_config_size  = ARRAY_SIZE(h6300_config);
-+      omap_serial_init();
-+}
-+
-+static void __init h6300_map_io(void)
-+{
-+      omap_map_common_io();
-+      
-+      btuart_device.dev.platform_data = &h6300_omap_bt_funcs;
-+      gsmuart_device.dev.platform_data        = &h6300_omap_gsm_funcs;
-+}
-+
-+MACHINE_START(H6300, "HP iPAQ H6300")
-+      /* MAINTAINER("Everett Coleman II <gcc80x86@fuzzyneural.net>") */
-+      .phys_ram       = 0x10000000,
-+      .phys_io        = 0xfff00000,
-+      .io_pg_offst    = ((0xfef00000) >> 18) & 0xfffc,
-+      .boot_params    = 0x10000100,
-+      .map_io         = h6300_map_io,
-+      .init_irq       = h6300_init_irq,
-+      .init_machine   = h6300_init,
-+      .timer          = &omap_timer,
-+MACHINE_END
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/arch/arm/mach-omap1/Kconfig bt_kernel/arch/arm/mach-omap1/Kconfig
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/arch/arm/mach-omap1/Kconfig 2005-10-30 17:44:15.310427101 +0200
-+++ bt_kernel/arch/arm/mach-omap1/Kconfig      2005-10-22 03:52:45.687256000 +0300
-@@ -26,6 +26,12 @@
-           TI OMAP 1510 or 1610 Innovator board support. Say Y here if you
-           have such a board.
-+config MACH_OMAP_H6300
-+      bool "HP IPaq H6300"
-+      depends on ARCH_OMAP1 && ARCH_OMAP15XX
-+      help
-+                      HP IPaq H6300 series.
-+
- config MACH_OMAP_H2
-       bool "TI H2 Support"
-       depends on ARCH_OMAP1 && ARCH_OMAP16XX
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/arch/arm/mach-omap1/Makefile bt_kernel/arch/arm/mach-omap1/Makefile
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/arch/arm/mach-omap1/Makefile        2005-10-30 17:44:15.334423281 +0200
-+++ bt_kernel/arch/arm/mach-omap1/Makefile     2005-10-22 03:52:45.687256000 +0300
-@@ -15,7 +15,8 @@
- obj-$(CONFIG_MACH_OMAP_H3)            += board-h3.o
- obj-$(CONFIG_MACH_VOICEBLUE)          += board-voiceblue.o
- obj-$(CONFIG_MACH_NETSTAR)            += board-netstar.o
--obj-$(CONFIG_MACH_OMAP_PALMTE)                += board-palmte.o
-+obj-$(CONFIG_MACH_OMAP_PALMTE)        += board-palmte.o
-+obj-$(CONFIG_MACH_OMAP_H6300)         += board-h6300.o
- ifeq ($(CONFIG_ARCH_OMAP15XX),y)
- # Innovator-1510 FPGA
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/arch/arm/mach-omap2/clock.h bt_kernel/arch/arm/mach-omap2/clock.h
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/arch/arm/mach-omap2/clock.h 2005-10-30 17:44:15.870337978 +0200
-+++ bt_kernel/arch/arm/mach-omap2/clock.h      2005-10-30 16:32:39.609796000 +0200
-@@ -1469,7 +1469,7 @@
-       .parent         = &l4_ck,
-       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-       .enable_reg     = (void __iomem *)&CM_ICLKEN2_CORE,
--      .enable_bit     = 3,
-+      .enable_bit     = 2,
-       .recalc         = &omap2_followparent_recalc,
- };
-@@ -1478,7 +1478,7 @@
-       .parent         = &func_48m_ck,
-       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-       .enable_reg     = (void __iomem *)&CM_FCLKEN2_CORE,
--      .enable_bit     = 3,
-+      .enable_bit     = 2,
-       .recalc         = &omap2_followparent_recalc,
- };
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/arch/arm/plat-omap/devices.c bt_kernel/arch/arm/plat-omap/devices.c
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/arch/arm/plat-omap/devices.c        2005-10-30 17:44:16.144294371 +0200
-+++ bt_kernel/arch/arm/plat-omap/devices.c     2005-10-22 03:52:45.687256000 +0300
-@@ -93,6 +93,9 @@
-       (void) platform_device_register(&omap_i2c_device1);
- }
-+#else
-+static inline void omap_init_i2c(void) {}
-+
- #endif
- /*-------------------------------------------------------------------------*/
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/arch/arm/plat-omap/dma.c bt_kernel/arch/arm/plat-omap/dma.c
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/arch/arm/plat-omap/dma.c    2005-10-30 17:44:16.167290711 +0200
-+++ bt_kernel/arch/arm/plat-omap/dma.c 2005-10-30 16:32:39.609796000 +0200
-@@ -28,6 +28,7 @@
- #include <asm/hardware.h>
- #include <asm/dma.h>
- #include <asm/io.h>
-+#include <asm/mach-types.h>
- #include <asm/arch/tc.h>
-@@ -121,7 +122,8 @@
- }
- void omap_set_dma_transfer_params(int lch, int data_type, int elem_count,
--                                int frame_count, int sync_mode)
-+                                int frame_count, int sync_mode,
-+                                int dma_trigger, int src_or_dst_synch)
- {
-       u16 w;
-@@ -179,7 +181,8 @@
- void omap_set_dma_src_params(int lch, int src_port, int src_amode,
--                           unsigned long src_start)
-+                           unsigned long src_start,
-+                           int src_ei, int src_fi)
- {
-       u16 w;
-@@ -221,7 +224,14 @@
-       case OMAP_DMA_DATA_BURST_DIS:
-               break;
-       case OMAP_DMA_DATA_BURST_4:
--              w |= (0x01 << 7);
-+              if (machine_is_h6300())
-+              {
-+                      w |= (0x01 << 7);
-+              }
-+              else
-+              {
-+                      w |= (0x02 << 7);
-+              }
-               break;
-       case OMAP_DMA_DATA_BURST_8:
-               /* not supported by current hardware
-@@ -235,7 +245,8 @@
- }
- void omap_set_dma_dest_params(int lch, int dest_port, int dest_amode,
--                            unsigned long dest_start)
-+                            unsigned long dest_start,
-+                            int dst_ei, int dst_fi)
- {
-       u16 w;
-@@ -277,7 +288,14 @@
-       case OMAP_DMA_DATA_BURST_DIS:
-               break;
-       case OMAP_DMA_DATA_BURST_4:
--              w |= (0x01 << 14);
-+              if (machine_is_h6300())
-+              {
-+                      w |= (0x01 << 14);
-+              }
-+              else
-+              {
-+                      w |= (0x02 << 14);
-+              }
-               break;
-       case OMAP_DMA_DATA_BURST_8:
-               w |= (0x03 << 14);
-@@ -769,6 +787,10 @@
-       }
-       if (omap_dma_in_1510_mode()) {
-+              u16 l = omap_readw(OMAP1510_DMA_LCD_CTRL);
-+              l &= ~(1 << 6);
-+              omap_writew (l, OMAP1510_DMA_LCD_CTRL);
-+
-               omap_writew(top >> 16, OMAP1510_DMA_LCD_TOP_F1_U);
-               omap_writew(top, OMAP1510_DMA_LCD_TOP_F1_L);
-               omap_writew(bottom >> 16, OMAP1510_DMA_LCD_BOT_F1_U);
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/arch/arm/plat-omap/mcbsp.c bt_kernel/arch/arm/plat-omap/mcbsp.c
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/arch/arm/plat-omap/mcbsp.c  2005-10-30 17:44:16.477241375 +0200
-+++ bt_kernel/arch/arm/plat-omap/mcbsp.c       2005-10-30 16:32:39.609796000 +0200
-@@ -493,17 +493,20 @@
-       omap_set_dma_transfer_params(mcbsp[id].dma_tx_lch,
-                                    OMAP_DMA_DATA_TYPE_S16,
-                                    length >> 1, 1,
--                                   OMAP_DMA_SYNC_ELEMENT);
-+                                   OMAP_DMA_SYNC_ELEMENT,
-+                                   0, 0);
-       omap_set_dma_dest_params(mcbsp[id].dma_tx_lch,
-                                OMAP_DMA_PORT_TIPB,
-                                OMAP_DMA_AMODE_CONSTANT,
--                               mcbsp[id].io_base + OMAP_MCBSP_REG_DXR1);
-+                               mcbsp[id].io_base + OMAP_MCBSP_REG_DXR1,
-+                               0, 0);
-       omap_set_dma_src_params(mcbsp[id].dma_tx_lch,
-                               OMAP_DMA_PORT_EMIFF,
-                               OMAP_DMA_AMODE_POST_INC,
--                              buffer);
-+                              buffer,
-+                              0, 0);
-       omap_start_dma(mcbsp[id].dma_tx_lch);
-       wait_for_completion(&(mcbsp[id].tx_dma_completion));
-@@ -533,17 +536,20 @@
-       omap_set_dma_transfer_params(mcbsp[id].dma_rx_lch,
-                                    OMAP_DMA_DATA_TYPE_S16,
-                                    length >> 1, 1,
--                                   OMAP_DMA_SYNC_ELEMENT);
-+                                   OMAP_DMA_SYNC_ELEMENT,
-+                                   0, 0);
-       omap_set_dma_src_params(mcbsp[id].dma_rx_lch,
-                               OMAP_DMA_PORT_TIPB,
-                               OMAP_DMA_AMODE_CONSTANT,
--                              mcbsp[id].io_base + OMAP_MCBSP_REG_DRR1);
-+                              mcbsp[id].io_base + OMAP_MCBSP_REG_DRR1,
-+                              0, 0);
-       omap_set_dma_dest_params(mcbsp[id].dma_rx_lch,
-                                OMAP_DMA_PORT_EMIFF,
-                                OMAP_DMA_AMODE_POST_INC,
--                               buffer);
-+                               buffer,
-+                               0, 0);
-       omap_start_dma(mcbsp[id].dma_rx_lch);
-       wait_for_completion(&(mcbsp[id].rx_dma_completion));
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/arch/arm/tools/mach-types bt_kernel/arch/arm/tools/mach-types
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/arch/arm/tools/mach-types   2005-10-20 09:23:05.000000000 +0300
-+++ bt_kernel/arch/arm/tools/mach-types        2005-10-22 03:52:45.687256000 +0300
-@@ -576,7 +576,7 @@
- s3c2460                       MACH_S3C2460            S3C2460                 560
- pdm                   MACH_PDM                PDM                     561
- h4700                 MACH_H4700              H4700                   562
--h6300                 MACH_H6300              H6300                   563
-+h6300                 MACH_OMAP_H6300         H6300                   563
- rz1700                        MACH_RZ1700             RZ1700                  564
- a716                  MACH_A716               A716                    565
- estk2440a             MACH_ESTK2440A          ESTK2440A               566
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/bluetooth/Kconfig bt_kernel/drivers/bluetooth/Kconfig
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/bluetooth/Kconfig   2005-10-20 09:23:05.000000000 +0300
-+++ bt_kernel/drivers/bluetooth/Kconfig        2005-10-04 00:58:34.589442000 +0300
-@@ -163,6 +163,16 @@
-         Say Y here to compile support for virtual HCI devices into the
-         kernel or say M to compile it as module (hci_vhci).
-+        
-+config BT_H6300
-+      tristate "H6300 BRF6100 BT DRIVER"
-+      help
-+        Bluetooth H6300 BRF6100 driver.
-+        This driver provides the firmware loading mechanism for the BRF6100
-+        bt hardware in iPAQ h6300.
-+
-+        Say Y here to compile support for BRF6100 BT devices into the
-+        kernel or say M to compile it as module (h6300_BT).     
- endmenu
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/bluetooth/Makefile bt_kernel/drivers/bluetooth/Makefile
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/bluetooth/Makefile  2005-10-20 09:23:05.000000000 +0300
-+++ bt_kernel/drivers/bluetooth/Makefile       2005-09-28 01:04:13.052737000 +0300
-@@ -10,10 +10,11 @@
- obj-$(CONFIG_BT_HCIBFUSB)     += bfusb.o
- obj-$(CONFIG_BT_HCIDTL1)      += dtl1_cs.o
- obj-$(CONFIG_BT_HCIBT3C)      += bt3c_cs.o
--obj-$(CONFIG_BT_HCIBLUECARD)  += bluecard_cs.o
-+obj-$(CONFIG_BT_HCIBLUECARD)+= bluecard_cs.o
- obj-$(CONFIG_BT_HCIBTUART)    += btuart_cs.o
-+obj-$(CONFIG_BT_H6300)                += omap/
--hci_uart-y                            := hci_ldisc.o
-+hci_uart-y                                                    := hci_ldisc.o
- hci_uart-$(CONFIG_BT_HCIUART_H4)      += hci_h4.o
- hci_uart-$(CONFIG_BT_HCIUART_BCSP)    += hci_bcsp.o
--hci_uart-objs                         := $(hci_uart-y)
-+hci_uart-objs                                         := $(hci_uart-y)
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/bluetooth/omap/h6300_bt_brf6100.c bt_kernel/drivers/bluetooth/omap/h6300_bt_brf6100.c
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/bluetooth/omap/h6300_bt_brf6100.c   1970-01-01 02:00:00.000000000 +0200
-+++ bt_kernel/drivers/bluetooth/omap/h6300_bt_brf6100.c        2005-10-06 02:34:39.057478000 +0300
-@@ -0,0 +1,153 @@
-+/* 
-+ * Bluetooth interface driver for TI BRF6100 on h6300
-+ * 
-+ * Copyright (C) 2005 Mika Laitio <lamikr@cc.jyu.fi>
-+ * Ideas taken from the brf6150 bt driver made by Todd Blumer for the pxa hx4700.
-+ * 
-+ * This program is free software; you can 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/delay.h>
-+#include <linux/device.h>
-+
-+#include <asm/hardware.h>
-+#include <asm/arch/gpio.h>
-+
-+#include <asm/arch/h6300_uart_info.h>
-+#include "h6300_bt_led.h"
-+
-+static void
-+h6300_bt_configure(struct uart_omap_port *up, int enable)
-+{
-+      printk(KERN_NOTICE "h6300_bt_brf6100.c h6300_bt_configure() started, enable = %d\n", enable);
-+      
-+      // printk( KERN_NOTICE "h6300 configure bluetooth: %d\n", enable );
-+      if (enable == 0) {
-+              omap_set_gpio_dataout(GPIO_N_BT_RST, 0);        // turn off gpio
-+              mdelay(5);
-+              h6300_clear_led(INDEX_BT_LED);
-+      }
-+      else if (enable == 1) {
-+              omap_set_gpio_dataout(GPIO_N_BT_RST, 1);        // turn on gpio
-+              mdelay(5);                              
-+      }
-+      else if (enable == 2) {
-+              /*
-+               * BRF6150's RTS goes low when firmware is ready
-+               * so check for CTS=1 (nCTS=0 -> CTS=1). Typical 150ms
-+               */
-+/*            
-+              int tries = 0; 
-+              do 
-+              {
-+                      mdelay(10);
-+              } 
-+              while ((BTMSR & MSR_CTS) == 0 && tries++ < 50);
-+*/                            
-+              h6300_set_led(INDEX_BT_LED, 16, 16);
-+      }
-+      printk(KERN_NOTICE "h6300_bt_brf6100.c h6300_bt_configure() done\n");
-+}
-+
-+static void
-+h6300_bt_set_txrx(struct uart_omap_port *up, int txrx)
-+{
-+      printk(KERN_NOTICE "h6300_bt_brf6100.c h6300_bt_set_txrx(), txrx = %d done\n", txrx);
-+      /* do nothing */
-+}
-+
-+static int
-+h6300_bt_get_txrx(struct uart_omap_port *up)
-+{
-+      printk(KERN_NOTICE "h6300_bt_brf6100.c h6300_bt_get_txrx() done\n");
-+      /* do nothing */
-+      return 0;
-+}
-+
-+static int
-+h6300_bt_probe(struct device *dev)
-+{
-+      struct h6300_uart_funcs *funcs = (struct h6300_uart_funcs *)dev->platform_data;
-+
-+      omap_request_gpio(GPIO_BT_PWR_EN);              // ask bt_power_en gpio, remember to release in remove_function
-+      omap_set_gpio_direction(GPIO_BT_PWR_EN, 1);     // set gpio direction to be output
-+      omap_set_gpio_dataout(GPIO_BT_PWR_EN, 1);       // turn on gpio
-+
-+      mdelay(200);
-+
-+      omap_request_gpio(GPIO_N_BT_RST);               // ask bt_reset gpio, remember to release in remove_function
-+      omap_set_gpio_direction(GPIO_N_BT_RST, 1);      // set gpio direction to be output
-+      omap_set_gpio_dataout(GPIO_N_BT_RST, 1);        // turn on gpio
-+      
-+      /* configure bluetooth UART */
-+      //h6300_gpio_mode(GPIO_NR_H6300_BT_RXD_MD);
-+      //h6300_gpio_mode(GPIO_NR_H6300_BT_TXD_MD);
-+      //h6300_gpio_mode(GPIO_NR_H6300_BT_UART_CTS_MD);
-+      //h6300_gpio_mode(GPIO_NR_H6300_BT_UART_RTS_MD);
-+
-+      funcs->configure        = h6300_bt_configure;
-+      funcs->set_txrx         = h6300_bt_set_txrx;
-+      funcs->get_txrx         = h6300_bt_get_txrx;
-+
-+      /* Make sure the LED is off */
-+      h6300_clear_led(INDEX_BT_LED);
-+      
-+      printk(KERN_NOTICE "h6300_bt_brf6100.c h6300_bt_probe() done\n");       
-+
-+      return 0;
-+}
-+
-+static int
-+h6300_bt_remove(struct device *dev)
-+{
-+      struct h6300_uart_funcs *funcs = (struct h6300_uart_funcs *)dev->platform_data;
-+      
-+      printk(KERN_NOTICE "h6300_bt_brf6100.c h6300_bt_remove() started\n");   
-+      
-+      omap_free_gpio(GPIO_BT_PWR_EN);
-+      omap_free_gpio(GPIO_N_BT_RST);
-+
-+      funcs->configure        = NULL;
-+      funcs->set_txrx         = NULL;
-+      funcs->get_txrx         = NULL;
-+
-+      /* Make sure the LED is off */
-+      h6300_clear_led(INDEX_BT_LED);
-+      
-+      printk(KERN_NOTICE "h6300_bt_brf6100.c, h6300_bt_remove() done\n");
-+
-+      return 0;
-+}
-+
-+static struct device_driver bt_driver = {
-+      .name     = "h6300_bt",
-+      .bus      = &platform_bus_type,
-+      .probe    = h6300_bt_probe,
-+      .remove   = h6300_bt_remove,
-+};
-+
-+static int __init
-+h6300_bt_init(void)
-+{
-+      printk(KERN_NOTICE "h6300 Bluetooth Driver init()\n");
-+      return driver_register(&bt_driver);
-+}
-+
-+static void __exit
-+h6300_bt_exit(void)
-+{
-+      printk(KERN_NOTICE "h6300 Bluetooth Driver exit()\n");
-+      driver_unregister(&bt_driver);
-+}
-+
-+module_init(h6300_bt_init);
-+module_exit(h6300_bt_exit);
-+
-+MODULE_AUTHOR("Mika Laitio, <lamikr@cc.jyu.fi>");
-+MODULE_DESCRIPTION("iPAQ h6300 BRF6100 Bluetooth driver.");
-+MODULE_LICENSE("GPL");
-+
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/bluetooth/omap/h6300_bt_led.c bt_kernel/drivers/bluetooth/omap/h6300_bt_led.c
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/bluetooth/omap/h6300_bt_led.c       1970-01-01 02:00:00.000000000 +0200
-+++ bt_kernel/drivers/bluetooth/omap/h6300_bt_led.c    2005-10-06 02:34:39.057478000 +0300
-@@ -0,0 +1,41 @@
-+/* 
-+ * Bluetooth interface driver helper for controlling bluetooth leds available in iPAQ h6300.
-+ * 
-+ * Copyright (C) 2005 Mika Laitio  <lamikr@cc.jyu.fi>
-+ * Ideas from the brf6150 bt driver made by Todd Blumer for the pxa hx4700.
-+ * 
-+ * This program is free software; you can 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/delay.h>
-+#include <linux/device.h>
-+
-+#include <asm/hardware.h>
-+#include <asm/arch/gpio.h>
-+
-+/* 
-+ * Low level access for disabling h6300 bt led.
-+ *
-+ * TODO: implement for h6300 
-+ */
-+void h6300_clear_led(int led_num)
-+{
-+      printk(KERN_NOTICE "h6300_bt_led.c h6300_clear_led() done\n");
-+      //hx4700_set_led(led_num, 0, 16);
-+}
-+EXPORT_SYMBOL(h6300_clear_led);
-+
-+/* 
-+ * Low level access for setting up the bt led.
-+ *
-+ * TODO: implement for h6300 
-+ */
-+void h6300_set_led(int led_num, int duty_time, int cycle_time)
-+{
-+      printk(KERN_NOTICE "h6300_bt_led.c h6300_set_led() done\n");
-+}
-+EXPORT_SYMBOL(h6300_set_led);
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/bluetooth/omap/h6300_bt_led.h bt_kernel/drivers/bluetooth/omap/h6300_bt_led.h
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/bluetooth/omap/h6300_bt_led.h       1970-01-01 02:00:00.000000000 +0200
-+++ bt_kernel/drivers/bluetooth/omap/h6300_bt_led.h    2005-10-06 02:34:39.057478000 +0300
-@@ -0,0 +1,9 @@
-+#ifndef H6300_BT_LED_H_
-+#define H6300_BT_LED_H_
-+
-+#define INDEX_BT_LED  2
-+
-+void h6300_clear_led(int led_num);
-+void h6300_set_led(int led_num, int duty_time, int cycle_time);
-+
-+#endif /*H6300_BT_LED_H_*/
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/bluetooth/omap/Makefile bt_kernel/drivers/bluetooth/omap/Makefile
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/bluetooth/omap/Makefile     1970-01-01 02:00:00.000000000 +0200
-+++ bt_kernel/drivers/bluetooth/omap/Makefile  2005-10-06 02:34:39.057478000 +0300
-@@ -0,0 +1,6 @@
-+#
-+# Makefile for the Linux iPAQ H6300 BRF6100 Bluetooth device drivers.
-+#
-+
-+h6300_bt-objs                         := h6300_bt_led.o h6300_bt_brf6100.o
-+obj-$(CONFIG_BT_H6300)                += h6300_bt.o
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/char/.gitignore bt_kernel/drivers/char/.gitignore
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/char/.gitignore     2005-10-20 09:23:05.000000000 +0300
-+++ bt_kernel/drivers/char/.gitignore  1970-01-01 02:00:00.000000000 +0200
-@@ -1,3 +0,0 @@
--consolemap_deftbl.c
--defkeymap.c
--
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/input/keyboard/omap-keypad.c bt_kernel/drivers/input/keyboard/omap-keypad.c
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/input/keyboard/omap-keypad.c        2005-10-30 17:44:17.444087478 +0200
-+++ bt_kernel/drivers/input/keyboard/omap-keypad.c     2005-10-30 16:34:01.215220000 +0200
-@@ -5,10 +5,11 @@
-  *
-  * Copyright (C) 2003 Nokia Corporation
-  * Written by Timo Teräs <ext-timo.teras@nokia.com>
-+ * iPAQ h6300 key and joypad support added by Mika Laitio. (2005)
-  *
-  * Added support for H2 & H3 Keypad
-  * Copyright (C) 2004 Texas Instruments
-- *
-+ * 
-  * This program is free software; you can redistribute it and/or modify
-  * it under the terms of the GNU General Public License as published by
-  * the Free Software Foundation; either version 2 of the License, or
-@@ -40,6 +41,7 @@
- #include <asm/arch/mux.h>
- #undef NEW_BOARD_LEARNING_MODE
-+//#define NEW_BOARD_LEARNING_MODE 1
- static void omap_kp_tasklet(unsigned long);
- static void omap_kp_timer(unsigned long);
-@@ -48,6 +50,8 @@
- static unsigned char keypad_state[8];
- static unsigned int keypad_irq = INT_KEYBOARD;
-+static int prevJoypadKeycodePressEmulated;
-+
- static struct timer_list kp_timer;
- DECLARE_TASKLET_DISABLED(kp_tasklet, omap_kp_tasklet, 0);
-@@ -165,6 +169,47 @@
-       0
- };
-+#define _h6300_KEY_CALENDAR   67      // xmodmap 75 aka F9
-+#define _H6300_KEY_TELEPHONE  68      // xmodmap 76 aka F10
-+#define _H6300_KEY_HOMEPAGE   87      // xmodmap 87 aka Num_Lock
-+#define _H6300_KEY_MAIL               88      // xmodmap 88 aka Scroll_Lock
-+
-+/*
-+ * Following 5 keypad events are not really sent to userspace. 
-+ * Instead if the good combination of them is sent, then that is send.
-+ * (up, right, down, left, enter)
-+ */
-+#define       _H6300_JOYPAD_UP_RIGHT          1       // 00001
-+#define _H6300_JOYPAD_DOWN_RIGHT      2       // 00010
-+#define _h6300_JOYPAD_DOWN_LEFT               4       // 00100
-+#define _h6300_JOYPAD_UP_LEFT         8       // 01000
-+#define _H6300_JOYPAD_KEY_OK          16      // 10000
-+
-+static int h6300_keymap[] = {
-+      KEY(2, 0, _h6300_KEY_CALENDAR),         // address button in the bottom left    
-+      KEY(2, 3, _H6300_KEY_TELEPHONE),        // start call button in the bottom
-+      KEY(3, 1, _H6300_KEY_HOMEPAGE),         // stop call button in the bottom
-+      KEY(3, 4, _H6300_KEY_MAIL),             // messaging button in the bottom right
-+
-+      KEY(0, 0, KEY_VOLUMEUP),        // volume up button in the right side
-+      KEY(0, 1, KEY_VOLUMEDOWN),      // volume down button in the right side
-+      KEY(3, 2, KEY_RECORD),          // record button in the left side
-+      
-+      KEY(1, 0, _h6300_JOYPAD_UP_LEFT),       
-+      KEY(1, 1, _h6300_JOYPAD_DOWN_LEFT),     
-+      KEY(1, 2, _H6300_JOYPAD_KEY_OK),                
-+      KEY(1, 3, _H6300_JOYPAD_DOWN_RIGHT),
-+      KEY(1, 4, _H6300_JOYPAD_UP_RIGHT),      
-+      
-+      KEY(5, 0, KEY_RIGHT),
-+      KEY(5, 1, KEY_DOWN),
-+      KEY(5, 2, KEY_LEFT),            
-+      KEY(5, 3, KEY_UP),
-+      KEY(5, 4, KEY_ENTER),
-+
-+      0
-+};
-+
- static int *keymap;
- static irqreturn_t omap_kp_interrupt(int irq, void *dev_id,
-@@ -191,7 +236,8 @@
-       for (col = 0; col < 8; col++) {
-               omap_writew(~(1 << col) & 0xff, OMAP_MPUIO_BASE + OMAP_MPUIO_KBC);
--              if (machine_is_omap_osk() || machine_is_omap_h2() || machine_is_omap_h3()) {
-+              if (machine_is_omap_osk() || machine_is_omap_h2() || machine_is_omap_h3()  || machine_is_h6300()) {
-+                      // makes keyboard act a little bit slower
-                       udelay(9);
-               } else {
-                       udelay(4);
-@@ -214,16 +260,24 @@
-       return -1;
- }
-+int is_key_down(unsigned char new_state[],
-+              int col,
-+              int row)
-+{
-+      return (new_state[col] & (1 << row)) ? 1 : 0;
-+}
-+
- static void omap_kp_tasklet(unsigned long data)
- {
-       unsigned char new_state[8], changed, key_down = 0;
-       int col, row;
-       int spurious = 0;
-+      int report_key, report_col, report_row, joypad_checked; // joypad specific variables
-       /* check for any changes */
-       omap_kp_scan_keypad(new_state);
--
-       /* check for changes and print those */
-+      joypad_checked  = 0;
-       for (col = 0; col < 8; col++) {
-               changed = new_state[col] ^ keypad_state[col];
-               key_down |= new_state[col];
-@@ -245,9 +299,173 @@
-                               spurious = 1;
-                               continue;
-                       }
--
--                      input_report_key(&omap_kp_dev, key,
--                                       new_state[col] & (1 << row));
-+                      if (machine_is_h6300() && 
-+                         ((col == 1) || (col == 5)))
-+                      {
-+                              if (col == 5)
-+                              {
-+                                      continue;
-+                              }
-+                              if ((joypad_checked == 0) &&
-+                                  ((key == _H6300_JOYPAD_KEY_OK) ||
-+                                   (key == _h6300_JOYPAD_UP_LEFT) ||
-+                                   (key == _H6300_JOYPAD_UP_RIGHT) ||
-+                                   (key == _H6300_JOYPAD_DOWN_RIGHT) ||
-+                                   (key == _h6300_JOYPAD_DOWN_LEFT)))
-+                              {
-+                                      if (is_key_down(new_state, col, row))
-+                                      {
-+                                              /*
-+                                               * only enter pressed
-+                                               * 1 0 0 _H6300_JOYPAD_KEY_OK 0 0
-+                                               * --> 100100 == 36
-+                                               */
-+                                               if (new_state[1] == 36)
-+                                               {
-+                                                      joypad_checked  = 1;
-+                                                      prevJoypadKeycodePressEmulated  = KEY_ENTER;
-+                                                      new_state[5]    = 48;   //110000
-+                                                      report_key      = prevJoypadKeycodePressEmulated;
-+                                                      report_col      = 5;
-+                                                      report_row      = 4;
-+                                                      input_report_key(&omap_kp_dev,
-+                                                                      report_key,
-+                                                                      new_state[report_col] & (1 << report_row));                                                     
-+                                               }                                              
-+                                              /*
-+                                               * enter, up_left and up_right sensors pressed.
-+                                               * 1 _H6300_JOYPAD_UP_RIGHT 0 _H6300_JOYPAD_KEY_OK 0 _h6300_JOYPAD_UP_LEFT
-+                                               * --> 110101 == 53
-+                                               * OR
-+                                               * 1 KEY_UP_RIGHT 0 0 0 _h6300_JOYPAD_UP_LEFT
-+                                               * --> 110001 == 42
-+                                               * --> move to up
-+                                               */
-+                                              else if ((new_state[1] == 53) ||
-+                                                       (new_state[1] == 49))
-+                                              {
-+                                                      joypad_checked  = 1;
-+                                                      prevJoypadKeycodePressEmulated  = KEY_UP;
-+                                                      new_state[5]    = 40;   //101000
-+                                                      report_key      = prevJoypadKeycodePressEmulated;
-+                                                      report_col      = 5;
-+                                                      report_row      = 3;
-+                                                      input_report_key(&omap_kp_dev,
-+                                                                      report_key,
-+                                                                      new_state[report_col] & (1 << report_row));
-+                                              }
-+                                              /*
-+                                               * enter, down_left and down_right sensors pressed
-+                                               * --> 101110 == 46
-+                                               * OR
-+                                               * down_left and down_right
-+                                               * -->101010 == 42
-+                                               * --> move to down
-+                                               */
-+                                              else if ((new_state[1] == 46) ||
-+                                                       (new_state[1] == 42))
-+                                              {
-+                                                      joypad_checked  = 1;
-+                                                      prevJoypadKeycodePressEmulated  = KEY_DOWN;
-+                                                      new_state[5]    = 34;   //100010
-+                                                      report_key      = prevJoypadKeycodePressEmulated;
-+                                                      report_col      = 5;
-+                                                      report_row      = 1;
-+                                                      input_report_key(&omap_kp_dev,
-+                                                                      report_key,
-+                                                                      new_state[report_col] & (1 << report_row));
-+                                              }                                                                                               
-+                                              /*
-+                                               * enter, up_right and down_right sensors pressed
-+                                               * --> 111100 == 60
-+                                               * or
-+                                               * down_right and up_right
-+                                               * --> 111000 == 56
-+                                               * --> move to right
-+                                               */
-+                                              else if ((new_state[1] == 60) ||
-+                                                       (new_state[1] == 56))
-+                                              {
-+                                                      joypad_checked  = 1;
-+                                                      prevJoypadKeycodePressEmulated  = KEY_RIGHT;
-+                                                      new_state[5]    = 33;   //100001
-+                                                      report_key      = prevJoypadKeycodePressEmulated;
-+                                                      report_col      = 5;
-+                                                      report_row      = 0;
-+                                                      input_report_key(&omap_kp_dev,
-+                                                                      report_key,
-+                                                                      new_state[report_col] & (1 << report_row));
-+                                              }
-+                                              /*
-+                                               * enter, up_left and down_left sensors pressed
-+                                               * --> 100111 == 39
-+                                               * or up_left and down_left
-+                                               * --> 100011 == 35
-+                                               * --> move to left
-+                                               */
-+                                              else if ((new_state[1] == 39) ||
-+                                                       (new_state[1] == 35))
-+                                              {
-+                                                      joypad_checked  = 1;
-+                                                      prevJoypadKeycodePressEmulated  = KEY_LEFT;
-+                                                      new_state[5]    = 36;   //100100
-+                                                      report_key      = prevJoypadKeycodePressEmulated;
-+                                                      report_col      = 5;
-+                                                      report_row      = 2;
-+                                                      input_report_key(&omap_kp_dev,
-+                                                                      report_key,
-+                                                                      new_state[report_col] & (1 << report_row));
-+                                              }
-+                                              else
-+                                              {
-+                                                      //printk("missed new_state = %d\n", new_state[1]);
-+                                              }
-+                                      }
-+                                      else
-+                                      {
-+                                              if (prevJoypadKeycodePressEmulated != 0)
-+                                              {
-+                                                      // report key up event
-+                                                      joypad_checked  = 1;
-+                                                      new_state[5]    = 32;   //100000
-+                                                      report_key      = prevJoypadKeycodePressEmulated;
-+                                                      report_col      = 5;
-+                                                      switch(prevJoypadKeycodePressEmulated)
-+                                                      {
-+                                                              case KEY_RIGHT:
-+                                                                      report_row      = 0;
-+                                                                      break;
-+                                                              case KEY_DOWN:
-+                                                                      report_row      = 1;
-+                                                                      break;
-+                                                              case KEY_LEFT:
-+                                                                      report_row      = 2;
-+                                                                      break;
-+                                                              case KEY_UP:
-+                                                                      report_row      = 3;
-+                                                                      break;
-+                                                              case KEY_ENTER:
-+                                                                      report_row      = 4;
-+                                                                      break;
-+                                                              default:
-+                                                                      printk(KERN_WARNING "Unknown iPAQ h6300 column 1 key = %d released. This should newer happen!\n",
-+                                                                              key);
-+                                                                      report_row      = 0;
-+                                                      }
-+                                                      input_report_key(&omap_kp_dev,
-+                                                                      report_key,
-+                                                                      new_state[report_col] & (1 << report_row));
-+                                                      prevJoypadKeycodePressEmulated  = 0;                                                            
-+                                              }
-+                                      }
-+                              }
-+                      }
-+                      else
-+                      {
-+                              input_report_key(&omap_kp_dev, 
-+                                              key,
-+                                              new_state[col] & (1 << row));
-+                      }
- #endif
-               }
-       }
-@@ -285,7 +503,12 @@
-       } else if (machine_is_omap_perseus2()) {
-               keymap = p2_keymap;
-               keypad_irq = INT_730_MPUIO_KEYPAD;
-+      } else if (machine_is_h6300()) {
-+              keymap = h6300_keymap;
-+              // set keyboard to send repeated key events if key is hold down
-+              set_bit(EV_REP, omap_kp_dev.evbit);
-       } else {
-+              printk("omap_keypad.c, keyMap = test_keymap\n");
-               keymap = test_keymap;
-       }
-@@ -335,6 +558,7 @@
-               omap_writew(0xff, OMAP_MPUIO_BASE + OMAP_MPUIO_GPIO_DEBOUNCING);
-       }
-+      prevJoypadKeycodePressEmulated          = 0;
-       /* scan current status and enable interrupt */
-       omap_kp_scan_keypad(keypad_state);
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/input/touchscreen/omap/Makefile bt_kernel/drivers/input/touchscreen/omap/Makefile
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/input/touchscreen/omap/Makefile     2005-10-30 17:44:17.519075542 +0200
-+++ bt_kernel/drivers/input/touchscreen/omap/Makefile  2005-10-22 03:52:45.687256000 +0300
-@@ -8,5 +8,6 @@
- objs-$(CONFIG_ARCH_OMAP16XX)$(CONFIG_MACH_OMAP_H3) += ts_hx.o
- objs-$(CONFIG_ARCH_OMAP15XX)$(CONFIG_MACH_OMAP_INNOVATOR) += ts_inn1510.o
- objs-$(CONFIG_ARCH_OMAP16XX)$(CONFIG_MACH_OMAP_OSK) += ts_osk.o
-+objs-$(CONFIG_ARCH_OMAP15XX)$(CONFIG_MACH_OMAP_H6300) += ts_hx.o
- omapts-objs := omap_ts.o $(objs-yy)
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/input/touchscreen/omap/omap_ts.c bt_kernel/drivers/input/touchscreen/omap/omap_ts.c
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/input/touchscreen/omap/omap_ts.c    2005-10-30 17:44:17.542071882 +0200
-+++ bt_kernel/drivers/input/touchscreen/omap/omap_ts.c 2005-10-22 03:52:45.687256000 +0300
-@@ -46,7 +46,7 @@
- #define OMAP_TS_NAME  "omap_ts"
- static struct ts_device *__initdata ts_devs[] = {
--#if defined(CONFIG_MACH_OMAP_H2) || defined(CONFIG_MACH_OMAP_H3)
-+#if defined(CONFIG_MACH_OMAP_H2) || defined(CONFIG_MACH_OMAP_H3) || defined(CONFIG_MACH_OMAP_H6300)
-       &hx_ts,
- #endif
- #ifdef CONFIG_MACH_OMAP_OSK
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/input/touchscreen/omap/ts_hx.c bt_kernel/drivers/input/touchscreen/omap/ts_hx.c
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/input/touchscreen/omap/ts_hx.c      2005-10-30 17:44:17.566068062 +0200
-+++ bt_kernel/drivers/input/touchscreen/omap/ts_hx.c   2005-09-28 02:45:59.570809000 +0300
-@@ -33,6 +33,7 @@
- #include <asm/arch/mux.h>
- #include <asm/arch/hardware.h>
- #include <asm/hardware/tsc2101.h>
-+#include <linux/delay.h>
- #include "../drivers/ssi/omap-tsc2101.h"
- #include "omap_ts.h"
-@@ -88,14 +89,19 @@
-       } else if (machine_is_omap_h3()) {
-               gpio = H3_GPIO_NUM;
-               omap_cfg_reg(W19_1610_GPIO48);
-+      } else if (machine_is_h6300 ()) {
-+              gpio = 2;
-+              omap_cfg_reg(M14_1510_GPIO2);   
-       } else
-               return -ENODEV;
-       ts->irq = OMAP_GPIO_IRQ(gpio);
--      if (omap_request_gpio(gpio) != 0) {
--              printk(KERN_ERR "hX_ts_init.c: Could not reserve GPIO!\n");
--              return -EINVAL;
--      };
-+      if (!machine_is_h6300 ()){
-+              if (omap_request_gpio(gpio) != 0) {
-+                      printk(KERN_ERR "hX_ts_init.c: Could not reserve GPIO!\n");
-+                      return -EINVAL;
-+              };
-+      }
-       omap_set_gpio_direction(gpio, 1);
-       set_irq_type(ts->irq, IRQT_FALLING);
-@@ -180,5 +186,7 @@
-               omap_free_gpio(H2_GPIO_NUM);
-       else if (machine_is_omap_h3())
-               omap_free_gpio(H3_GPIO_NUM);
-+      else if (machine_is_h6300())
-+              omap_free_gpio(2);
- }
- #endif
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/i2c/busses/i2c-omap.c bt_kernel/drivers/i2c/busses/i2c-omap.c
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/i2c/busses/i2c-omap.c       2005-10-30 17:44:17.091143658 +0200
-+++ bt_kernel/drivers/i2c/busses/i2c-omap.c    2005-10-20 20:53:33.518825000 +0300
-@@ -124,10 +124,10 @@
- /* I2C System Configuration Register (OMAP_I2C_SYSC): */
- #define OMAP_I2C_SYSC_SRST            (1 << 1)        /* Soft Reset */
-+#undef        I2C_OMAP_DEBUG
- /* ------- debugging ---------------------------------------------------*/
--#define I2C_OMAP_DEBUG
--#ifdef I2c_OMAP_DEBUG
-+#ifdef I2C_OMAP_DEBUG
- static int i2c_debug;
- module_param(i2c_debug, int, 0);
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/i2c/chips/Kconfig bt_kernel/drivers/i2c/chips/Kconfig
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/i2c/chips/Kconfig   2005-10-30 17:44:17.176130130 +0200
-+++ bt_kernel/drivers/i2c/chips/Kconfig        2005-10-14 18:55:31.156317000 +0300
-@@ -56,6 +56,16 @@
-         This driver can also be built as a module.  If so, the module
-         will be called pca9539.
-+config PCA9535
-+        tristate "Philips PCA9535 16-bit I/O port"
-+        depends on I2C 
-+        help
-+          If you say yes here you get support for the Philips PCA9535
-+          16-bit I/O port.
-+      
-+          This driver can also be built as a module.  If so, the module
-+          will be called pca9539.
-+
- config SENSORS_PCF8591
-       tristate "Philips PCF8591"
-       depends on I2C && EXPERIMENTAL
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/i2c/chips/Makefile bt_kernel/drivers/i2c/chips/Makefile
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/i2c/chips/Makefile  2005-10-30 17:44:17.176130130 +0200
-+++ bt_kernel/drivers/i2c/chips/Makefile       2005-10-14 18:55:31.156317000 +0300
-@@ -16,6 +16,7 @@
- obj-$(CONFIG_SENSORS_TLV320AIC23) += tlv320aic23.o
- obj-$(CONFIG_GPIOEXPANDER_OMAP)       += gpio_expander_omap.o
- obj-$(CONFIG_MENELAUS)                += menelaus.o
-+obj-$(CONFIG_PCA9535)                 += pca9535.o
- ifeq ($(CONFIG_I2C_DEBUG_CHIP),y)
- EXTRA_CFLAGS += -DDEBUG
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/i2c/chips/pca9535.c bt_kernel/drivers/i2c/chips/pca9535.c
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/i2c/chips/pca9535.c 1970-01-01 02:00:00.000000000 +0200
-+++ bt_kernel/drivers/i2c/chips/pca9535.c      2005-10-25 22:23:21.875634000 +0300
-@@ -0,0 +1,414 @@
-+/*
-+    Driver for Philips PCA9535 16-bit low power I/O port with interrupt
-+
-+    This program is free software; you can redistribute it and/or modify
-+    it under the terms of the GNU General Public License as published by
-+    the Free Software Foundation; either version 2 of the License, or
-+    (at your option) any later version.
-+    
-+    This program is distributed in the hope that it will be useful,
-+    but WITHOUT ANY WARRANTY; without even the implied warranty of
-+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+    GNU General Public License for more details.
-+
-+    You should have received a copy of the GNU General Public License
-+    along with this program; if not, write to the Free Software
-+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+    
-+    Copyright (C) 2005 Husam Senussi
-+    Framework based on Pawel Kolodziejski's pca9535 driver in 
-+    handheld.org's 2.6.13 kernel. Driver updated by Mika Laitio.
-+*/
-+
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/slab.h>
-+#include <linux/i2c.h>
-+#include <linux/hwmon-sysfs.h>
-+#include <linux/hwmon.h>
-+#include <linux/err.h>
-+
-+#include <asm/arch/pca9535.h>
-+#include <linux/delay.h>
-+
-+#include <linux/interrupt.h>
-+#include <asm/mach-types.h>
-+#include <asm/irq.h>
-+#include <asm/mach/arch.h>
-+#include <asm/hardware.h>
-+
-+EXPORT_SYMBOL(pca9535_gpio_read);
-+EXPORT_SYMBOL(pca9535_gpio_write);
-+EXPORT_SYMBOL(pca9535_gpio_direction);
-+
-+static int pca9535_attach_adapter(struct i2c_adapter *adapter);
-+static int pca9535_detach_client(struct i2c_client *client);
-+static int pca9535_attach(struct i2c_adapter *adapter, int address, int zero_or_minus_one);
-+static u32 pca9535_read_reg(struct i2c_client *client, u8 regaddr);
-+static void pca9535_write_reg(struct i2c_client *client, u8 regaddr, u16 param);
-+
-+enum pca9535_cmd
-+{
-+        PCA9535_INPUT_0         = 0,
-+        PCA9535_INPUT_1         = 1,
-+        PCA9535_OUTPUT_0        = 2,
-+        PCA9535_OUTPUT_1        = 3,
-+        PCA9535_INVERT_0        = 4,
-+        PCA9535_INVERT_1        = 5,
-+        PCA9535_DIRECTION_0     = 6,
-+        PCA9535_DIRECTION_1     = 7,
-+};
-+
-+struct pca9535_data {
-+      struct semaphore  lock;
-+        struct i2c_client client;
-+};
-+
-+static struct i2c_driver pca9535_driver = {
-+      .owner                  = THIS_MODULE,
-+      .name                   = "pca9535",
-+      .flags                  = I2C_DF_NOTIFY,
-+      .attach_adapter         = pca9535_attach_adapter,
-+      .detach_client          = pca9535_detach_client,
-+};
-+
-+static struct i2c_client   *pca9535_i2c_client = NULL;
-+static struct pca9535_data pca9535_inited;
-+
-+static unsigned short normal_i2c[] = { 0x20, I2C_CLIENT_END };
-+
-+#define DRIVER_VERSION  "20 OCT 2005"
-+#define DRIVER_NAME     "PCA9535"
-+
-+/* 
-+ * sysfs callback function.
-+ */ 
-+static ssize_t pca9535_show(struct device *dev, struct device_attribute *attr,
-+                            char *buf)
-+{
-+        struct sensor_device_attribute *psa = to_sensor_dev_attr(attr);
-+        struct i2c_client *client = to_i2c_client(dev);
-+        return sprintf(buf, "%02X\n", (pca9535_read_reg(client, psa->index) >> 8));
-+}
-+
-+/* 
-+ * sysfs callback function.
-+ */ 
-+static ssize_t pca9535_store(struct device *dev, struct device_attribute *attr,
-+                             const char *buf, size_t count)
-+{
-+        struct sensor_device_attribute *psa = to_sensor_dev_attr(attr);
-+        struct i2c_client *client = to_i2c_client(dev);
-+        unsigned long val = simple_strtoul(buf, NULL, 0);
-+      unsigned long old = pca9535_read_reg(client, psa->index);
-+
-+        if (val > 0xff)
-+                return -EINVAL;
-+      
-+      val = (old & 0xff) | (val << 8);
-+        pca9535_write_reg(client, psa->index, val);
-+        return count;
-+}
-+
-+#define PCA9535_ENTRY_RO(name, cmd_idx) \
-+        static SENSOR_DEVICE_ATTR(name, S_IRUGO, pca9535_show, NULL, cmd_idx)
-+
-+#define PCA9535_ENTRY_RW(name, cmd_idx) \
-+        static SENSOR_DEVICE_ATTR(name, S_IRUGO | S_IWUSR, pca9535_show, \
-+                                  pca9535_store, cmd_idx)
-+
-+PCA9535_ENTRY_RO(input0, PCA9535_INPUT_0);
-+PCA9535_ENTRY_RO(input1, PCA9535_INPUT_1);
-+PCA9535_ENTRY_RW(output0, PCA9535_OUTPUT_0);
-+PCA9535_ENTRY_RW(output1, PCA9535_OUTPUT_1);
-+PCA9535_ENTRY_RW(invert0, PCA9535_INVERT_0);
-+PCA9535_ENTRY_RW(invert1, PCA9535_INVERT_1);
-+PCA9535_ENTRY_RW(direction0, PCA9535_DIRECTION_0);
-+PCA9535_ENTRY_RW(direction1, PCA9535_DIRECTION_1);
-+
-+static struct attribute *pca9535_attributes[] = {
-+        &sensor_dev_attr_input0.dev_attr.attr,
-+        &sensor_dev_attr_input1.dev_attr.attr,
-+        &sensor_dev_attr_output0.dev_attr.attr,
-+        &sensor_dev_attr_output1.dev_attr.attr,
-+        &sensor_dev_attr_invert0.dev_attr.attr,
-+        &sensor_dev_attr_invert1.dev_attr.attr,
-+        &sensor_dev_attr_direction0.dev_attr.attr,
-+        &sensor_dev_attr_direction1.dev_attr.attr,
-+        NULL
-+};
-+
-+static struct attribute_group pca9535_defattr_group = {
-+        .attrs = pca9535_attributes,
-+};
-+//End of sysfs management code. 
-+
-+I2C_CLIENT_INSMOD;
-+
-+u32 pca9535_read_input(void)
-+{
-+      return pca9535_read_reg(pca9535_i2c_client, 0);
-+}
-+EXPORT_SYMBOL(pca9535_read_input);
-+
-+void pca9535_write_output(u16 param)
-+{
-+      pca9535_write_reg(pca9535_i2c_client, 2, param);
-+}
-+EXPORT_SYMBOL(pca9535_write_output);
-+
-+void pca9535_set_dir(u16 param)
-+{
-+      pca9535_write_reg(pca9535_i2c_client, 6, param);
-+}
-+EXPORT_SYMBOL(pca9535_set_dir);
-+
-+static int pca9535_attach_adapter(struct i2c_adapter *adapter)
-+{
-+      return i2c_probe(adapter, &addr_data, pca9535_attach);
-+}
-+
-+static int pca9535_attach(struct i2c_adapter *adapter, int address, int zero_or_minus_one)
-+{
-+      struct i2c_client *new_client;
-+      int err = 0;
-+
-+      printk("pca9535_attach() started\n");
-+      new_client = &(pca9535_inited.client);
-+      i2c_set_clientdata(new_client, 0);
-+      new_client->addr = address;
-+      new_client->adapter = adapter;
-+      new_client->driver = &pca9535_driver;
-+      new_client->flags = I2C_CLIENT_ALLOW_USE;
-+      strcpy(new_client->name, DRIVER_NAME);
-+
-+      if ((err = i2c_attach_client(new_client)))
-+              goto exit_free;
-+
-+      pca9535_i2c_client = new_client;
-+      
-+      init_MUTEX(&pca9535_inited.lock);
-+      i2c_set_clientdata(pca9535_i2c_client, &pca9535_inited);
-+      
-+      sysfs_create_group(&pca9535_i2c_client->dev.kobj, &pca9535_defattr_group);
-+      
-+      printk("pca9535_attach() ok\n");
-+      return 0;
-+
-+exit_free:
-+      printk("pca9535_attach() failed, error code = %d\n", err);
-+      return err;
-+}
-+
-+static int pca9535_detach_client(struct i2c_client *client)
-+{
-+      int err;
-+
-+      if ((err = i2c_detach_client(client))) {
-+              dev_err(&client->dev, "Client deregistration failed, client not detached.\n");
-+              return err;
-+      }
-+      pca9535_i2c_client = NULL;
-+
-+      return 0;
-+}
-+
-+static int __init pca9535_init(void)
-+{
-+      return i2c_add_driver(&pca9535_driver);
-+}
-+
-+static void __exit pca9535_exit(void)
-+{
-+        i2c_del_driver(&pca9535_driver);
-+}
-+
-+/* 
-+ * Reads the value of GPIO available via I2C.
-+ */
-+int pca9535_gpio_read(int gpio){
-+      unsigned char reg = 0;
-+      unsigned long val = 0;
-+
-+      printk("9535_gpio_read() called\n");
-+      if(!pca9535_i2c_client)
-+              return -ENODEV;
-+
-+      if(gpio < GPIO0 || gpio > GPIO17)
-+              return -EINVAL;
-+
-+      if(gpio >= GPIO0 && gpio <= GPIO7){
-+              reg      = PCA9535_INPUT_0;
-+              gpio    -= GPIO0;
-+      }else if(gpio >= GPIO8 && gpio <= GPIO17){
-+              reg      = PCA9535_INPUT_1;
-+                gpio    -= GPIO8;
-+      }
-+
-+      down(&pca9535_inited.lock);
-+
-+      // Read the existing values first
-+      val = pca9535_read_reg(pca9535_i2c_client, reg) >> 8;
-+      val = (val >> gpio) & 0x01;
-+
-+      up(&pca9535_inited.lock);
-+
-+      return val;
-+}
-+
-+/* 
-+ * Set the value of I2C GPIO.
-+ */
-+int pca9535_gpio_write(int gpio, unsigned char value){
-+      unsigned char in_reg  = 0;
-+        unsigned char out_reg = 0;
-+        unsigned long val = 0;
-+      unsigned long old = 0;
-+      int           ret = 0;
-+
-+        if(!pca9535_i2c_client)
-+                return -ENODEV;
-+
-+        if(gpio < GPIO0 || gpio > GPIO17)
-+                return -EINVAL;
-+
-+        if(gpio >= GPIO0 && gpio <= GPIO7){
-+                in_reg   = PCA9535_INPUT_0;
-+                out_reg  = PCA9535_OUTPUT_0;
-+                gpio    -= GPIO0;
-+        }else if(gpio >= GPIO8 && gpio <= GPIO17){
-+                in_reg   = PCA9535_INPUT_1;
-+                out_reg  = PCA9535_OUTPUT_1;
-+                gpio    -= GPIO8;
-+        }
-+
-+      down(&pca9535_inited.lock);
-+
-+        // Read the existing values first
-+        val = pca9535_read_reg(pca9535_i2c_client, in_reg);
-+      old = val >> 8;
-+
-+      switch(value){
-+      case LOW:
-+              old |= (1 << gpio);
-+              break;
-+      case HI:
-+              old &= ~(1 << gpio);
-+              break;
-+      default:
-+              ret = -EINVAL;
-+              goto error;
-+      }
-+
-+      val = (val & 0xff) | (old << 8);        
-+
-+      // write the values back to the register
-+      pca9535_write_reg(pca9535_i2c_client, out_reg, val);
-+error:
-+
-+      up(&pca9535_inited.lock);
-+      return ret;
-+}
-+
-+/*
-+ * Set the direction of I2C GPIO.
-+ */ 
-+int pca9535_gpio_direction(int gpio, unsigned char direction){
-+        unsigned char reg = 0;
-+        unsigned long val = 0;
-+      unsigned long old = 0;
-+        int           ret = 0;
-+
-+        if(!pca9535_i2c_client)
-+                return -ENODEV;
-+
-+        if(gpio < GPIO0 || gpio > GPIO17)
-+                return -EINVAL;
-+
-+        if(gpio >= GPIO0 && gpio <= GPIO7){
-+                reg            = PCA9535_DIRECTION_0;
-+                gpio    -= GPIO0;
-+        }else if(gpio >= GPIO8 && gpio <= GPIO17){
-+                reg            = PCA9535_DIRECTION_1;
-+                gpio    -= GPIO8;
-+        }
-+
-+        down(&pca9535_inited.lock);
-+
-+        // Read the existing values first
-+        old = pca9535_read_reg(pca9535_i2c_client, reg);
-+      val = old >> 8;
-+
-+        switch(direction){
-+        case GPIO_INPUT: 
-+                val |= (1 << gpio);
-+                break;
-+        case GPIO_OUTPUT: 
-+                val &= ~(1 << gpio);
-+                break;
-+        default:
-+                ret = -EINVAL;
-+                goto error;
-+        }
-+
-+      val = (old & 0xff) | (val << 8);
-+
-+        // write the values back to the register
-+        pca9535_write_reg(pca9535_i2c_client, reg, val);
-+error:
-+
-+        up(&pca9535_inited.lock);
-+        return ret;
-+}
-+
-+static u32 pca9535_read_reg(struct i2c_client *client, u8 regaddr)
-+{
-+      char buffer[3];
-+      int r;
-+      u32 data;
-+
-+      buffer[0] = regaddr;
-+      buffer[1] = 0;
-+      buffer[2] = 0;
-+
-+      r = i2c_master_send(client, buffer, 1);
-+      if (r != 1) {
-+              printk(KERN_ERR "pca9535: read failed, status %d\n", r);
-+              return 0xffffffff;
-+      }
-+
-+      r = i2c_master_recv(client, buffer, 3);
-+      if (r != 3) {
-+              printk(KERN_ERR "pca9535: read failed, status %d\n", r);
-+              return 0xffffffff;
-+      }
-+
-+      data = buffer[1];
-+      data |= buffer[2] << 8;
-+      //printk(KERN_ERR "%s: reading %x in %x\n", __FUNCTION__, data, regaddr);
-+
-+      return data;
-+}
-+
-+static void pca9535_write_reg(struct i2c_client *client, u8 regaddr, u16 data)
-+{
-+      char buffer[3];
-+      int r;
-+
-+      //printk(KERN_ERR "%s: writing %x in %x\n", __FUNCTION__, data, regaddr);
-+      buffer[0] = regaddr;
-+      buffer[1] = data >> 8;
-+      buffer[2] = data & 0xff;
-+
-+      r = i2c_master_send(client, buffer, 3);
-+      if (r != 3) {
-+              printk(KERN_ERR "pca9535: write failed, status %d\n", r);
-+      }
-+}
-+
-+MODULE_AUTHOR("Husam Senussi <husamsenussi@gmail.com>");
-+MODULE_DESCRIPTION("PCA9535 driver");
-+MODULE_LICENSE("GPL");
-+
-+module_init(pca9535_init);
-+module_exit(pca9535_exit);
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/i2c/i2c-core.c bt_kernel/drivers/i2c/i2c-core.c
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/i2c/i2c-core.c      2005-10-20 09:23:05.000000000 +0300
-+++ bt_kernel/drivers/i2c/i2c-core.c   2005-10-22 03:52:45.687256000 +0300
-@@ -1180,8 +1180,12 @@
-                                               command,size,data);
-               up(&adapter->bus_lock);
-       } else
-+      {
-+              printk("i2c-core, calling i2c_smbus_xfer_emulated!");
-               res = i2c_smbus_xfer_emulated(adapter,addr,flags,read_write,
-                                             command,size,data);
-+              printk("i2c-core, i2c_smbus_xfer_emulated retVal = %d", res);
-+      }
-       if(res >= 0 && swpec &&
-          size != I2C_SMBUS_QUICK && size != I2C_SMBUS_I2C_BLOCK_DATA &&
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/media/video/omap/omap16xxcam.c bt_kernel/drivers/media/video/omap/omap16xxcam.c
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/media/video/omap/omap16xxcam.c      2005-10-30 17:44:17.750038779 +0200
-+++ bt_kernel/drivers/media/video/omap/omap16xxcam.c   2005-10-30 16:32:39.609796000 +0200
-@@ -325,18 +325,22 @@
-       
-       if (machine_is_omap_h3())
-               omap_set_dma_src_params(dmach, OMAP_DMA_PORT_OCP_T1,
--                          OMAP_DMA_AMODE_CONSTANT, CAM_CAMDATA_REG);
-+                          OMAP_DMA_AMODE_CONSTANT, CAM_CAMDATA_REG,
-+                          0, 0);
-       else
-               omap_set_dma_src_params(dmach, OMAP_DMA_PORT_TIPB,
--                          OMAP_DMA_AMODE_CONSTANT, CAM_CAMDATA_REG);
-+                          OMAP_DMA_AMODE_CONSTANT, CAM_CAMDATA_REG,
-+                          0, 0);
-       omap_set_dma_dest_params(dmach, OMAP_DMA_PORT_EMIFF,
--                           OMAP_DMA_AMODE_POST_INC, sg_dma_address(sglist));
-+                           OMAP_DMA_AMODE_POST_INC, sg_dma_address(sglist),
-+                           0, 0);
-       omap_set_dma_transfer_params(dmach, OMAP_DMA_DATA_TYPE_S32,
-                       FIFO_TRIGGER_LVL, 
-                       sg_dma_len(sglist)/(4 * FIFO_TRIGGER_LVL), 
--                      OMAP_DMA_SYNC_FRAME);
-+                      OMAP_DMA_SYNC_FRAME,
-+                      0, 0);
-       
-       omap_writew(omap_readw(OMAP_DMA_CLNK_CTRL(dmach)) & ~(1<<15), 
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/mmc/omap.c bt_kernel/drivers/mmc/omap.c
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/mmc/omap.c  2005-10-30 17:44:17.905014111 +0200
-+++ bt_kernel/drivers/mmc/omap.c       2005-10-30 16:32:39.609796000 +0200
-@@ -4,6 +4,7 @@
-  *  Copyright (C) 2004 Nokia Corporation
-  *  Written by Tuukka Tikkanen and Juha Yrjölä <juha.yrjola@nokia.com>
-  *  Misc hacks here and there by Tony Lindgren <tony@atomide.com>
-+ *  Other hacks (DMA, SD, etc) by David Brownell
-  *
-  * This program is free software; you can redistribute it and/or modify
-  * it under the terms of the GNU General Public License version 2 as
-@@ -703,20 +704,24 @@
-               buf = 0x800f | ((frame - 1) << 8);
-               omap_set_dma_src_params(dma_ch, OMAP_DMA_PORT_TIPB,
-                                       OMAP_DMA_AMODE_CONSTANT,
--                                      data_addr);
-+                                      data_addr,
-+                                      0, 0);
-               omap_set_dma_dest_params(dma_ch, OMAP_DMA_PORT_EMIFF,
-                                       OMAP_DMA_AMODE_POST_INC,
--                                      sg_dma_address(sg));
-+                                      sg_dma_address(sg),
-+                                      0, 0);
-               omap_set_dma_dest_data_pack(dma_ch, 1);
-               omap_set_dma_dest_burst_mode(dma_ch, OMAP_DMA_DATA_BURST_4);
-       } else {
-               buf = 0x0f80 | ((frame - 1) << 0);
-               omap_set_dma_dest_params(dma_ch, OMAP_DMA_PORT_TIPB,
-                                       OMAP_DMA_AMODE_CONSTANT,
--                                      data_addr);
-+                                      data_addr,
-+                                      0, 0);
-               omap_set_dma_src_params(dma_ch, OMAP_DMA_PORT_EMIFF,
-                                       OMAP_DMA_AMODE_POST_INC,
--                                      sg_dma_address(sg));
-+                                      sg_dma_address(sg),
-+                                      0, 0);
-               omap_set_dma_src_data_pack(dma_ch, 1);
-               omap_set_dma_src_burst_mode(dma_ch, OMAP_DMA_DATA_BURST_4);
-       }
-@@ -727,7 +732,8 @@
-       OMAP_MMC_WRITE(host->base, BUF, buf);
-       omap_set_dma_transfer_params(dma_ch, OMAP_DMA_DATA_TYPE_S16,
--                      frame, count, OMAP_DMA_SYNC_FRAME);
-+                      frame, count, OMAP_DMA_SYNC_FRAME,
-+                      0, 0);
- }
- /* a scatterlist segment completed */
-@@ -767,9 +773,6 @@
-       host->sg_idx++;
-       if (host->sg_idx < host->sg_len) {
--              /* REVISIT we only checked the first segment
--               * for being a dma candidate ...
--               */
-               mmc_omap_prepare_dma(host, host->data);
-               omap_start_dma(host->dma_ch);
-       } else
-@@ -1089,9 +1092,10 @@
-               if (dsor > 250)
-                       dsor = 250;
-               dsor++;
--      }
--      /* REVISIT:  if (ios->bus_width == MMC_BUS_WIDTH_4) dsor |= 1 << 15; */
-+              if (ios->bus_width == MMC_BUS_WIDTH_4)
-+                      dsor |= 1 << 15;
-+      }
-       switch (ios->power_mode) {
-       case MMC_POWER_OFF:
-@@ -1132,9 +1136,17 @@
-       clk_unuse(host->fclk);
- }
-+static int mmc_omap_get_ro(struct mmc_host *mmc)
-+{
-+      struct mmc_omap_host *host = mmc_priv(mmc);
-+
-+      return host->wp_pin && omap_get_gpio_datain(host->wp_pin);
-+}
-+
- static struct mmc_host_ops mmc_omap_ops = {
-       .request        = mmc_omap_request,
-       .set_ios        = mmc_omap_set_ios,
-+      .get_ro         = mmc_omap_get_ro,
- };
- static int __init mmc_omap_probe(struct device *dev)
-@@ -1192,9 +1204,7 @@
-               goto out;
-       }
--      /* REVISIT:  SD-only support, when core merged
--       *  - if (minfo->wire4) mmc->caps |= MMC_CAP_4_BIT_DATA;
--       *  - mmc_omap_ops.get_ro uses wp_pin to sense slider
-+      /* REVISIT:
-        * Also, use minfo->cover to decide how to manage
-        * the card detect sensing.
-        */
-@@ -1212,6 +1222,9 @@
-       host->irq = pdev->resource[1].start;
-       host->base = (void __iomem *)pdev->resource[0].start;
-+       if (minfo->wire4)
-+               mmc->caps |= MMC_CAP_4_BIT_DATA;
-+
-       mmc->ops = &mmc_omap_ops;
-       mmc->f_min = 400000;
-       mmc->f_max = 24000000;
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/mtd/nand/omap-hw.c bt_kernel/drivers/mtd/nand/omap-hw.c
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/mtd/nand/omap-hw.c  2005-10-30 17:44:18.133977666 +0200
-+++ bt_kernel/drivers/mtd/nand/omap-hw.c       2005-10-30 16:32:39.609796000 +0200
-@@ -232,25 +232,30 @@
-       fifo_reg = NAND_BASE + NND_FIFO;
-       if (is_write) {
-               omap_set_dma_dest_params(dma_ch, OMAP_DMA_PORT_TIPB,
--                                       OMAP_DMA_AMODE_CONSTANT, fifo_reg);
-+                                       OMAP_DMA_AMODE_CONSTANT, fifo_reg,
-+                                       0, 0);
-               omap_set_dma_src_params(dma_ch, OMAP_DMA_PORT_EMIFF,
-                                       OMAP_DMA_AMODE_POST_INC,
--                                      virt_to_phys(addr));
-+                                      virt_to_phys(addr),
-+                                      0, 0);
- //            omap_set_dma_src_burst_mode(dma_ch, OMAP_DMA_DATA_BURST_4);
-               /* Set POSTWRITE bit */
-               nand_write_reg(NND_CTRL, nand_read_reg(NND_CTRL) | (1 << 16));
-       } else {
-               omap_set_dma_src_params(dma_ch, OMAP_DMA_PORT_TIPB,
--                                      OMAP_DMA_AMODE_CONSTANT, fifo_reg);
-+                                      OMAP_DMA_AMODE_CONSTANT, fifo_reg,
-+                                      0, 0);
-               omap_set_dma_dest_params(dma_ch, OMAP_DMA_PORT_EMIFF,
-                                        OMAP_DMA_AMODE_POST_INC,
--                                       virt_to_phys(addr));
-+                                       virt_to_phys(addr),
-+                                       0, 0);
- //            omap_set_dma_dest_burst_mode(dma_ch, OMAP_DMA_DATA_BURST_8);
-               /* Set PREFETCH bit */
-               nand_write_reg(NND_CTRL, nand_read_reg(NND_CTRL) | (1 << 17));
-       }
-       omap_set_dma_transfer_params(dma_ch, OMAP_DMA_DATA_TYPE_S32, block_size / 4,
--                                   block_count, OMAP_DMA_SYNC_FRAME);
-+                                   block_count, OMAP_DMA_SYNC_FRAME,
-+                                   0, 0);
-       init_completion(&comp);
-       len = u32_count << 2;
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/net/irda/omap1610-ir.c bt_kernel/drivers/net/irda/omap1610-ir.c
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/net/irda/omap1610-ir.c      2005-10-30 17:44:18.200967003 +0200
-+++ bt_kernel/drivers/net/irda/omap1610-ir.c   2005-10-30 16:32:39.609796000 +0200
-@@ -166,14 +166,16 @@
- static void omap1610_irda_start_rx_dma(struct omap1610_irda *si)
- {
-       /* Configure DMA */
--      omap_set_dma_src_params(si->rx_dma_channel, 0x3, 0x0, (unsigned long)UART3_RHR);
-+      omap_set_dma_src_params(si->rx_dma_channel, 0x3, 0x0, (unsigned long)UART3_RHR,
-+                              0, 0);
-       omap_enable_dma_irq(si->rx_dma_channel, 0x01);
-       omap_set_dma_dest_params(si->rx_dma_channel, 0x0, 0x1,
--                               si->rx_buf_dma_phys);
-+                               si->rx_buf_dma_phys,
-+                               0, 0);
--      omap_set_dma_transfer_params(si->rx_dma_channel, 0x0, 4096, 0x1, 0x0);
-+      omap_set_dma_transfer_params(si->rx_dma_channel, 0x0, 4096, 0x1, 0x0, 0, 0);
-       omap_start_dma(si->rx_dma_channel);
- }
-@@ -183,14 +185,16 @@
-       __ECHO_IN;
-       /* Configure DMA */
--      omap_set_dma_dest_params(si->tx_dma_channel, 0x03, 0x0, (unsigned long)UART3_THR);
-+      omap_set_dma_dest_params(si->tx_dma_channel, 0x03, 0x0, (unsigned long)UART3_THR,
-+                              0, 0);
-       omap_enable_dma_irq(si->tx_dma_channel, 0x01);
-       omap_set_dma_src_params(si->tx_dma_channel, 0x0, 0x1,
--                              si->tx_buf_dma_phys);
-+                              si->tx_buf_dma_phys,
-+                              0, 0);
--      omap_set_dma_transfer_params(si->tx_dma_channel, 0x0, size, 0x1, 0x0);
-+      omap_set_dma_transfer_params(si->tx_dma_channel, 0x0, size, 0x1, 0x0, 0, 0);
-       HDBG1(1);
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/net/wireless/Kconfig bt_kernel/drivers/net/wireless/Kconfig
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/net/wireless/Kconfig        2005-10-20 09:23:05.000000000 +0300
-+++ bt_kernel/drivers/net/wireless/Kconfig     2005-10-22 03:52:45.687256000 +0300
-@@ -483,5 +483,7 @@
-       depends on NET_RADIO && (ISA || PCI || PPC_PMAC || PCMCIA)
-       default y
-+source "drivers/net/wireless/tiacx/Kconfig"
-+
- endmenu
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/net/wireless/Makefile bt_kernel/drivers/net/wireless/Makefile
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/net/wireless/Makefile       2005-10-20 09:23:05.000000000 +0300
-+++ bt_kernel/drivers/net/wireless/Makefile    2005-10-14 18:55:31.156317000 +0300
-@@ -39,3 +39,4 @@
- # 16-bit wireless PCMCIA client drivers
- obj-$(CONFIG_PCMCIA_RAYCS)    += ray_cs.o
- obj-$(CONFIG_PCMCIA_WL3501)   += wl3501_cs.o
-+obj-$(CONFIG_ACX)             += tiacx/
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/net/wireless/tiacx/acx_config.h bt_kernel/drivers/net/wireless/tiacx/acx_config.h
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/net/wireless/tiacx/acx_config.h     1970-01-01 02:00:00.000000000 +0200
-+++ bt_kernel/drivers/net/wireless/tiacx/acx_config.h  2005-09-28 23:54:23.938287000 +0300
-@@ -0,0 +1,44 @@
-+/* temporary hack until proper Kconfig integration */
-+#define CONFIG_ACX_PCI 1
-+#define CONFIG_ACX_USB 1
-+
-+#define WLAN_RELEASE "v0.3.10"
-+
-+/* 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 2
-+
-+/* assume 32bit I/O width
-+ * (16bit is also compatible with Compact Flash) */
-+#define ACX_IO_WIDTH 16
-+
-+/* 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
-+
-+/* set to 1 if you want to have 1 driver per card instead of 1 single driver
-+ * managing all cards (of a particular bus type) in your system
-+ * Useful e.g. if you need to reinitialize single cards from time to time
-+ * LINUX 2.4.X ONLY!! (pci_for_each_dev()) Feel free to implement 2.6.x
-+ * compatibility... */
-+#define SEPARATE_DRIVER_INSTANCES 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
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/net/wireless/tiacx/acx_func.h bt_kernel/drivers/net/wireless/tiacx/acx_func.h
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/net/wireless/tiacx/acx_func.h       1970-01-01 02:00:00.000000000 +0200
-+++ bt_kernel/drivers/net/wireless/tiacx/acx_func.h    2005-09-28 23:54:23.938287000 +0300
-@@ -0,0 +1,660 @@
-+/***********************************************************************
-+** 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 acxlog() 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 acxlog(), 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 acxlog(chan, args...) \
-+      do { \
-+              if (acx_debug & (chan)) \
-+                      printk(args); \
-+      } while (0)
-+#define printk_ratelimited(args...) printk(args)
-+
-+#else /* Non-debug build: */
-+
-+#define acxlog(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-entended 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;
-+}
-+
-+
-+/***********************************************************************
-+** LOCKING
-+** We have priv->sem and priv->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. priv->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 inder lock
-+**
-+** 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(wlandevice_t *priv, const char* where);
-+void acx_unlock_debug(wlandevice_t *priv, const char* where);
-+void acx_down_debug(wlandevice_t *priv, const char* where);
-+void acx_up_debug(wlandevice_t *priv, const char* where);
-+void acx_lock_unhold(void);
-+void acx_sem_unhold(void);
-+
-+static inline void
-+acx_lock_helper(wlandevice_t *priv, unsigned long *fp, const char* where)
-+{
-+      acx_lock_debug(priv, where);
-+      spin_lock_irqsave(&priv->lock, *fp);
-+}
-+static inline void
-+acx_unlock_helper(wlandevice_t *priv, unsigned long *fp, const char* where)
-+{
-+      acx_unlock_debug(priv, where);
-+      spin_unlock_irqrestore(&priv->lock, *fp);
-+}
-+static inline void
-+acx_down_helper(wlandevice_t *priv, const char* where)
-+{
-+      acx_down_debug(priv, where);
-+}
-+static inline void
-+acx_up_helper(wlandevice_t *priv, const char* where)
-+{
-+      acx_up_debug(priv, where);
-+}
-+#define acx_lock(priv, flags) acx_lock_helper(priv, &(flags), __FILE__ ":" STRING(__LINE__))
-+#define acx_unlock(priv, flags)       acx_unlock_helper(priv, &(flags), __FILE__ ":" STRING(__LINE__))
-+#define acx_sem_lock(priv)    acx_down_helper(priv, __FILE__ ":" STRING(__LINE__))
-+#define acx_sem_unlock(priv)  acx_up_helper(priv, __FILE__ ":" STRING(__LINE__))
-+
-+#elif defined(DO_LOCKING)
-+
-+#define acx_lock(priv, flags) spin_lock_irqsave(&priv->lock, flags)
-+#define acx_unlock(priv, flags)       spin_unlock_irqrestore(&priv->lock, flags)
-+#define acx_sem_lock(priv)    down(&priv->sem)
-+#define acx_sem_unlock(priv)  up(&priv->sem)
-+#define acx_lock_unhold()     ((void)0)
-+#define acx_sem_unhold()      ((void)0)
-+
-+#else /* no locking! :( */
-+
-+#define acx_lock(priv, flags) ((void)0)
-+#define acx_unlock(priv, flags)       ((void)0)
-+#define acx_sem_lock(priv)    ((void)0)
-+#define acx_sem_unlock(priv)  ((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 -> acx_l_clean_tx_desc -> acx_wake_queue
-+** Review carefully all callsites */
-+static inline void
-+acx_stop_queue(netdevice_t *dev, const char *msg)
-+{
-+      if(netif_queue_stopped(dev))
-+              return;
-+
-+      netif_stop_queue(dev);
-+      if (msg)
-+              acxlog(L_BUFT, "tx: stop queue %s\n", msg);
-+}
-+
-+static inline int
-+acx_queue_stopped(netdevice_t *dev)
-+{
-+      return netif_queue_stopped(dev);
-+}
-+
-+static inline void
-+acx_start_queue(netdevice_t *dev, const char *msg)
-+{
-+      netif_start_queue(dev);
-+      if (msg)
-+              acxlog(L_BUFT, "tx: start queue %s\n", msg);
-+}
-+
-+static inline void
-+acx_wake_queue(netdevice_t *dev, const char *msg)
-+{
-+      netif_wake_queue(dev);
-+      if (msg)
-+              acxlog(L_BUFT, "tx: wake queue %s\n", msg);
-+}
-+
-+static inline void
-+acx_carrier_off(netdevice_t *dev, const char *msg)
-+{
-+      netif_carrier_off(dev);
-+      if (msg)
-+              acxlog(L_BUFT, "tx: carrier off %s\n", msg);
-+}
-+
-+static inline void
-+acx_carrier_on(netdevice_t *dev, const char *msg)
-+{
-+      netif_carrier_on(dev);
-+      if (msg)
-+              acxlog(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(wlandevice_t *priv, 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(wlandevice_t *priv, unsigned cmd, void *param, unsigned len, unsigned timeout, const char* cmdstr);
-+int acxusb_s_issue_cmd_timeo_debug(wlandevice_t *priv, unsigned cmd, void *param, unsigned len, unsigned timeout, const char* cmdstr);
-+static inline int
-+acx_s_issue_cmd_timeo_debug(wlandevice_t *priv, unsigned cmd, void *param, unsigned len, unsigned timeout, const char* cmdstr)
-+{
-+#if defined(CONFIG_ACX_CFI)
-+      return acxpci_s_issue_cmd_timeo_debug(priv, cmd, param, len, timeout, cmdstr);
-+#else
-+      if (IS_PCI(priv))
-+              return acxpci_s_issue_cmd_timeo_debug(priv, cmd, param, len, timeout, cmdstr);
-+      return acxusb_s_issue_cmd_timeo_debug(priv, cmd, param, len, timeout, cmdstr);
-+#endif
-+}
-+#define acx_s_issue_cmd(priv,cmd,param,len) \
-+      acx_s_issue_cmd_timeo_debug(priv,cmd,param,len,ACX_CMD_TIMEOUT_DEFAULT,#cmd)
-+#define acx_s_issue_cmd_timeo(priv,cmd,param,len,timeo) \
-+      acx_s_issue_cmd_timeo_debug(priv,cmd,param,len,timeo,#cmd)
-+int acx_s_configure_debug(wlandevice_t *priv, void *pdr, int type, const char* str);
-+#define acx_s_configure(priv,pdr,type) \
-+      acx_s_configure_debug(priv,pdr,type,#type)
-+int acx_s_interrogate_debug(wlandevice_t *priv, void *pdr, int type, const char* str);
-+#define acx_s_interrogate(priv,pdr,type) \
-+      acx_s_interrogate_debug(priv,pdr,type,#type)
-+
-+#else
-+
-+int acxpci_s_issue_cmd_timeo(wlandevice_t *priv, unsigned cmd, void *param, unsigned len, unsigned timeout);
-+int acxusb_s_issue_cmd_timeo(wlandevice_t *priv, unsigned cmd, void *param, unsigned len, unsigned timeout);
-+static inline int
-+acx_s_issue_cmd_timeo(wlandevice_t *priv, unsigned cmd,       void *param, unsigned len, unsigned timeout)
-+{
-+      if (IS_PCI(priv))
-+              return acxpci_s_issue_cmd_timeo(priv, cmd, param, len, timeout);
-+      return acxusb_s_issue_cmd_timeo(priv, cmd, param, len, timeout);
-+}
-+static inline int
-+acx_s_issue_cmd(wlandevice_t *priv, unsigned cmd, void *param, unsigned len)
-+{
-+      if (IS_PCI(priv))
-+              return acxpci_s_issue_cmd_timeo(priv, cmd, param, len, ACX_CMD_TIMEOUT_DEFAULT);
-+      return acxusb_s_issue_cmd_timeo(priv, cmd, param, len, ACX_CMD_TIMEOUT_DEFAULT);
-+}
-+int acx_s_configure(wlandevice_t *priv, void *pdr, int type);
-+int acx_s_interrogate(wlandevice_t *priv, void *pdr, int type);
-+
-+#endif
-+
-+void acx_s_cmd_start_scan(wlandevice_t *priv);
-+
-+
-+/***********************************************************************
-+** Ioctls
-+*/
-+int
-+acx111pci_ioctl_info(
-+      struct net_device *dev,
-+      struct iw_request_info *info,
-+      struct iw_param *vwrq,
-+      char *extra);
-+int
-+acx100pci_ioctl_set_phy_amp_bias(
-+      struct net_device *dev,
-+      struct iw_request_info *info,
-+      struct iw_param *vwrq,
-+      char *extra);
-+
-+
-+/***********************************************************************
-+** Unsorted yet :)
-+*/
-+int acxpci_s_read_phy_reg(wlandevice_t *priv, u32 reg, u8 *charbuf);
-+int acxusb_s_read_phy_reg(wlandevice_t *priv, u32 reg, u8 *charbuf);
-+static inline int
-+acx_s_read_phy_reg(wlandevice_t *priv, u32 reg, u8 *charbuf)
-+{
-+#if defined(CONFIG_ACX_CFI)
-+      return acxpci_s_read_phy_reg(priv, reg, charbuf);
-+#else
-+      if (IS_PCI(priv))
-+              return acxpci_s_read_phy_reg(priv, reg, charbuf);
-+      return acxusb_s_read_phy_reg(priv, reg, charbuf);
-+#endif
-+}
-+
-+int acxpci_s_write_phy_reg(wlandevice_t *priv, u32 reg, u8 value);
-+int acxusb_s_write_phy_reg(wlandevice_t *priv, u32 reg, u8 value);
-+static inline int
-+acx_s_write_phy_reg(wlandevice_t *priv, u32 reg, u8 value)
-+{
-+#if defined(CONFIG_ACX_CFI)
-+      return acxpci_s_write_phy_reg(priv, reg, value);
-+#else
-+      if (IS_PCI(priv))
-+              return acxpci_s_write_phy_reg(priv, reg, value);
-+      return acxusb_s_write_phy_reg(priv, reg, value);
-+#endif
-+}
-+
-+void acx_s_msleep(int ms);
-+int acx_s_init_mac(netdevice_t *dev);
-+void acx_set_reg_domain(wlandevice_t *priv, unsigned char reg_dom_id);
-+void acx_set_timer(wlandevice_t *priv, int timeout_us);
-+void acx_update_capabilities(wlandevice_t *priv);
-+int acx_read_eeprom_offset(wlandevice_t *priv, u32 addr, u8 *charbuf);
-+void acx_s_start(wlandevice_t *priv);
-+#if USE_FW_LOADER_26
-+firmware_image_t *acx_s_read_fw(struct device *dev, const char *file, u32 *size);
-+#else
-+firmware_image_t *acx_s_read_fw(const char *file, u32 *size);
-+#define acx_s_read_fw(dev, file, size) acx_s_read_fw(file, size)
-+#endif
-+void acx_s_initialize_rx_config(wlandevice_t *priv);
-+void acx_s_update_card_settings(wlandevice_t *priv, int get_all, int set_all);
-+void acx_init_task_scheduler(wlandevice_t *priv);
-+void acx_schedule_after_interrupt_task(wlandevice_t *priv, unsigned int set_flag);
-+int acx_s_upload_radio(wlandevice_t *priv);
-+void acx_read_configoption(wlandevice_t *priv);
-+int acx_proc_register_entries(const struct net_device *dev);
-+int acx_proc_unregister_entries(const struct net_device *dev);
-+void acx_l_update_ratevector(wlandevice_t *priv);
-+
-+int acx_e_ioctl_old(netdevice_t *dev, struct ifreq *ifr, int cmd);
-+
-+client_t *acx_l_sta_list_get(wlandevice_t *priv, const u8 *address);
-+void acx_l_sta_list_del(wlandevice_t *priv, client_t *clt);
-+
-+int acx_l_transmit_disassoc(wlandevice_t *priv, client_t *clt);
-+void acx_i_timer(unsigned long a);
-+int acx_s_complete_scan(wlandevice_t *priv);
-+
-+static inline wlan_hdr_t*
-+acx_get_wlan_hdr(wlandevice_t *priv, const rxbuffer_t *rxbuf)
-+{
-+      if (!(priv->rx_config_1 & RX_CFG1_INCLUDE_PHY_HDR))
-+              return (wlan_hdr_t*)&rxbuf->hdr_a3;
-+
-+      /* take into account phy header in front of packet */
-+      if (IS_ACX111(priv))
-+              return (wlan_hdr_t*)((u8*)&rxbuf->hdr_a3 + 8);
-+
-+      return (wlan_hdr_t*)((u8*)&rxbuf->hdr_a3 + 4);
-+}
-+
-+struct sk_buff *acx_rxbuf_to_ether(struct wlandevice *priv, rxbuffer_t *rxbuf);
-+
-+void acx_l_power_led(wlandevice_t *priv, int enable);
-+
-+unsigned int acx_l_clean_tx_desc(wlandevice_t *priv);
-+void acx_l_clean_tx_desc_emergency(wlandevice_t *priv);
-+
-+u8 acx_signal_determine_quality(u8 signal, u8 noise);
-+
-+void acx_l_process_rxbuf(wlandevice_t *priv, rxbuffer_t *rxbuf);
-+void acx_l_process_rx_desc(wlandevice_t *priv);
-+
-+tx_t* acxpci_l_alloc_tx(wlandevice_t *priv);
-+tx_t* acxusb_l_alloc_tx(wlandevice_t *priv);
-+static inline tx_t*
-+acx_l_alloc_tx(wlandevice_t *priv)
-+{
-+#if defined(CONFIG_ACX_CFI)
-+      return acxpci_l_alloc_tx(priv);
-+#else
-+      if (IS_PCI(priv))
-+              return acxpci_l_alloc_tx(priv);
-+      return acxusb_l_alloc_tx(priv);
-+#endif
-+}
-+
-+void* acxpci_l_get_txbuf(wlandevice_t *priv, tx_t *tx_opaque);
-+void* acxusb_l_get_txbuf(wlandevice_t *priv, tx_t *tx_opaque);
-+static inline void*
-+acx_l_get_txbuf(wlandevice_t *priv, tx_t *tx_opaque)
-+{
-+#if defined(CONFIG_ACX_CFI)
-+      return acxpci_l_get_txbuf(priv, tx_opaque);
-+#else
-+      if (IS_PCI(priv))
-+              return acxpci_l_get_txbuf(priv, tx_opaque);
-+      return acxusb_l_get_txbuf(priv, tx_opaque);
-+#endif
-+}
-+
-+void acxpci_l_tx_data(wlandevice_t *priv, tx_t *tx_opaque, int len);
-+void acxusb_l_tx_data(wlandevice_t *priv, tx_t *tx_opaque, int len);
-+static inline void
-+acx_l_tx_data(wlandevice_t *priv, tx_t *tx_opaque, int len)
-+{
-+#if defined(CONFIG_ACX_CFI)
-+      acxpci_l_tx_data(priv, tx_opaque, len);
-+#else
-+      if (IS_PCI(priv))
-+              acxpci_l_tx_data(priv, tx_opaque, len);
-+      else
-+              acxusb_l_tx_data(priv, tx_opaque, len);
-+#endif
-+}
-+
-+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 acx100usb_l_tx_data(wlandevice_t *priv, struct txdesc *desc);
-+int acx_s_set_defaults(wlandevice_t *priv);
-+void acx_init_mboxes(wlandevice_t *priv);
-+
-+int acx_l_ether_to_txbuf(wlandevice_t *priv, void *txbuf, const struct sk_buff *skb);
-+
-+#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, netdevice_t *dev);
-+void acx_free_desc_queues(wlandevice_t *priv);
-+
-+int acx_s_create_hostdesc_queues(wlandevice_t *priv);
-+void acx_create_desc_queues(wlandevice_t *priv, u32 tx_queue_start, u32 rx_queue_start);
-+
-+int acx100_s_init_wep(wlandevice_t *priv);
-+int acx100_s_init_packet_templates(wlandevice_t *priv);
-+int acx111_s_init_packet_templates(wlandevice_t *priv);
-+
-+void great_inquisitor(wlandevice_t *priv);
-+
-+char* acxpci_s_proc_diag_output(char *p, wlandevice_t *priv);
-+int acx_proc_eeprom_output(char *p, wlandevice_t *priv);
-+void acx_set_interrupt_mask(wlandevice_t *priv);
-+int acx100_s_set_tx_level(wlandevice_t *priv, u8 level_dbm);
-+
-+#if defined(CONFIG_ACX_CFI)
-+int __init acxcfi_e_init_module(void);
-+#else
-+int __init acxpci_e_init_module(void);
-+int __init acxusb_e_init_module(void);
-+#endif
-+
-+#if defined(CONFIG_ACX_CFI)
-+void __exit acxcfi_e_cleanup_module(void);
-+#else
-+void __exit acxpci_e_cleanup_module(void);
-+void __exit acxusb_e_cleanup_module(void);
-+#endif
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/net/wireless/tiacx/acx.h bt_kernel/drivers/net/wireless/tiacx/acx.h
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/net/wireless/tiacx/acx.h    1970-01-01 02:00:00.000000000 +0200
-+++ bt_kernel/drivers/net/wireless/tiacx/acx.h 2005-09-28 23:54:23.938287000 +0300
-@@ -0,0 +1,6 @@
-+#include "acx_config.h"
-+#include "wlan_compat.h"
-+#include "wlan_hdr.h"
-+#include "wlan_mgmt.h"
-+#include "acx_struct.h"
-+#include "acx_func.h"
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/net/wireless/tiacx/acx_struct.h bt_kernel/drivers/net/wireless/tiacx/acx_struct.h
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/net/wireless/tiacx/acx_struct.h     1970-01-01 02:00:00.000000000 +0200
-+++ bt_kernel/drivers/net/wireless/tiacx/acx_struct.h  2005-10-29 22:02:44.690471000 +0300
-@@ -0,0 +1,1966 @@
-+/***********************************************************************
-+** 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 wlandevice wlandevice_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 __WLAN_ATTRIB_PACK__
-+
-+#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) */
-+
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,41)
-+#include <linux/workqueue.h>
-+/* #define NEWER_KERNELS_ONLY 1 */
-+#define USE_WORKER_TASKS
-+#define WORK_STRUCT struct work_struct
-+#define SCHEDULE_WORK schedule_work
-+#define FLUSH_SCHEDULED_WORK flush_scheduled_work
-+
-+#else
-+#include <linux/tqueue.h>
-+#define USE_QUEUE_TASKS
-+#define WORK_STRUCT struct tq_struct
-+#define SCHEDULE_WORK schedule_task
-+#define INIT_WORK(work, func, ndev) \
-+      do { \
-+              (work)->routine = (func); \
-+              (work)->data = (ndev); \
-+      } while (0)
-+#define FLUSH_SCHEDULED_WORK flush_scheduled_tasks
-+
-+#endif
-+
-+
-+/*============================================================================*
-+ * Constants                                                                  *
-+ *============================================================================*/
-+#define OK    0
-+#define NOT_OK        1
-+
-+/* The supported chip models */
-+#define CHIPTYPE_ACX100               1
-+#define CHIPTYPE_ACX111               2
-+
-+#define IS_ACX100(priv)       ((priv)->chip_type == CHIPTYPE_ACX100)
-+#define IS_ACX111(priv)       ((priv)->chip_type == CHIPTYPE_ACX111)
-+
-+/* Supported interfaces */
-+#define DEVTYPE_PCI           0
-+#define DEVTYPE_USB           1
-+
-+#if defined(CONFIG_ACX_PCI)
-+ #if !defined(CONFIG_ACX_USB)
-+  #define IS_PCI(priv)        1
-+ #else
-+  #define IS_PCI(priv)        ((priv)->dev_type == DEVTYPE_PCI)
-+ #endif
-+#else
-+ #define IS_PCI(priv) 0
-+#endif
-+
-+#if defined(CONFIG_ACX_USB)
-+ #if !defined(CONFIG_ACX_PCI)
-+  #define IS_USB(priv)        1
-+ #else
-+  #define IS_USB(priv)        ((priv)->dev_type == DEVTYPE_USB)
-+ #endif
-+#else
-+ #define IS_USB(priv) 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
-+
-+/* 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 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_TEST                       0x17
-+#define ACX1xx_CMD_RADIOINIT          0x18
-+#define ACX111_CMD_RADIOCALIB         0x19
-+
-+/* '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
-+*/
-+/* BTW, 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
-+*/
-+#define RX_CNT 32
-+#define TX_CNT 32
-+
-+/* we clean up txdescs when we have N free txdesc: */
-+#define TX_START_CLEAN (TX_CNT - (TX_CNT/4))
-+#define TX_EMERG_CLEAN 2
-+/* we stop queue if we have less than N free txbufs: */
-+#define TX_STOP_QUEUE 3
-+/* we start queue if we have more than N free txbufs: */
-+#define TX_START_QUEUE 6
-+
-+/***********************************************************************
-+** 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);
-+DEF_IE(1xx_IE_QUEUE_CONFIG            ,0x0003, 0x1c);
-+DEF_IE(100_IE_BLOCK_SIZE              ,0x0004, 0x02);
-+DEF_IE(1xx_IE_MEMORY_CONFIG_OPTIONS   ,0x0005, 0x14);
-+DEF_IE(1xx_IE_RATE_FALLBACK           ,0x0006, 0x01);
-+DEF_IE(100_IE_WEP_OPTIONS             ,0x0007, 0x03);
-+DEF_IE(111_IE_RADIO_BAND              ,0x0007, -1);
-+DEF_IE(1xx_IE_MEMORY_MAP              ,0x0008, 0x28); /* huh? */
-+DEF_IE(100_IE_SSID                    ,0x0008, 0x20); /* huh? */
-+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(100_IE_UNKNOWN_0C              ,0x000c, -1);   /* very small implementation in FW150! */
-+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);
-+DEF_IE(1xx_IE_FIRMWARE_STATISTICS     ,0x0013, 0x9c);
-+DEF_IE(1xx_IE_FEATURE_CONFIG          ,0x0015, 0x08);
-+DEF_IE(111_IE_KEY_CHOOSE              ,0x0016, 0x04); /* for rekeying. really len=4?? */
-+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 */
-+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(1xx_IE_DOT11_SHORT_RETRY_LIMIT ,0x1005, 0x01);
-+DEF_IE(1xx_IE_DOT11_LONG_RETRY_LIMIT  ,0x1006, 0x01);
-+DEF_IE(100_IE_DOT11_WEP_DEFAULT_KEY_WRITE     ,0x1007, 0x20); /* configure default keys */
-+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.
-+////#ifdef ACX_PCI
-+////DEF_IE(1xx_IE_DOT11_CURRENT_ANTENNA       ,0x100b, 0x01);
-+////#else
-+DEF_IE(1xx_IE_DOT11_CURRENT_ANTENNA   ,0x100b, 0x02);
-+////#endif
-+DEF_IE(1xx_IE_DOT11_UNKNOWN_100C      ,0x100c, -1);   /* mapped to cfgInvalid in FW150 */
-+DEF_IE(1xx_IE_DOT11_TX_POWER_LEVEL    ,0x100d, 0x01);
-+////#ifdef ACX_PCI
-+////DEF_IE(1xx_IE_DOT11_CURRENT_CCA_MODE      ,0x100e, 0x01);
-+////#else
-+DEF_IE(1xx_IE_DOT11_CURRENT_CCA_MODE  ,0x100e, 0x02);
-+////#endif
-+//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 */
-+DEF_IE(100_IE_DOT11_UNKNOWN_1011      ,0x1011, -1);   /* mapped to cfgInvalid in FW150 */
-+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 IBBS Beacons
-+ * 0000 3c00 0000 0000 ESS Beacons
-+ * 0000 2700 0000 0000 Probe requests
-+ * --vda
-+ */
-+typedef struct phy_hdr {
-+      u8      unknown[4] ACX_PACKED;
-+      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 PHY_HDR(rxbuf) ((phy_hdr_t*)&rxbuf->hdr_a3)
-+#define RXBUF_BYTES_RCVD(rxbuf) (le16_to_cpu(rxbuf->mac_cnt_rcvd) & 0xfff)
-+#define RXBUF_BYTES_USED(rxbuf) \
-+              ((le16_to_cpu(rxbuf->mac_cnt_rcvd) & 0xfff) + RXBUF_HDRSIZE)
-+/*
-+mac_cnt_rcvd:
-+    12 bits: length of frame from control field to last byte of FCS
-+    4 bits: reserved
-+
-+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 ACX_PACKED;        /* only 12 bits are len! (0xfff) */
-+      u8      mac_cnt_mblks ACX_PACKED;
-+      u8      mac_status ACX_PACKED;
-+      u8      phy_stat_baseband ACX_PACKED;   /* bit 0x80: used LNA (Low-Noise Amplifier) */
-+      u8      phy_plcp_signal ACX_PACKED;
-+      u8      phy_level ACX_PACKED;           /* PHY stat */
-+      u8      phy_snr ACX_PACKED;             /* PHY stat */
-+      u32     time ACX_PACKED;                /* 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 ACX_PACKED;
-+      /* maximally sized data part of wlan packet */
-+      u8      data_a3[WLAN_A4FR_MAXLEN_WEP_FCS - WLAN_HDR_A3_LEN] ACX_PACKED;
-+      /* can add hdr/data_a4 if needed */
-+} rxbuffer_t;
-+
-+
-+/*--- Firmware statistics ----------------------------------------------------*/
-+typedef struct fw_stats {
-+      u32     val0x0 ACX_PACKED;              /* hdr; */
-+      u32     tx_desc_of ACX_PACKED;
-+      u32     rx_oom ACX_PACKED;
-+      u32     rx_hdr_of ACX_PACKED;
-+      u32     rx_hdr_use_next ACX_PACKED;
-+      u32     rx_dropped_frame ACX_PACKED;
-+      u32     rx_frame_ptr_err ACX_PACKED;
-+      u32     rx_xfr_hint_trig ACX_PACKED;
-+
-+      u32     rx_dma_req ACX_PACKED;
-+      u32     rx_dma_err ACX_PACKED;
-+      u32     tx_dma_req ACX_PACKED;
-+      u32     tx_dma_err ACX_PACKED;
-+
-+      u32     cmd_cplt ACX_PACKED;
-+      u32     fiq ACX_PACKED;
-+      u32     rx_hdrs ACX_PACKED;
-+      u32     rx_cmplt ACX_PACKED;
-+      u32     rx_mem_of ACX_PACKED;
-+      u32     rx_rdys ACX_PACKED;
-+      u32     irqs ACX_PACKED;
-+      u32     acx_trans_procs ACX_PACKED;
-+      u32     decrypt_done ACX_PACKED;
-+      u32     dma_0_done ACX_PACKED;
-+      u32     dma_1_done ACX_PACKED;
-+      u32     tx_exch_complet ACX_PACKED;
-+      u32     commands ACX_PACKED;
-+      u32     acx_rx_procs ACX_PACKED;
-+      u32     hw_pm_mode_changes ACX_PACKED;
-+      u32     host_acks ACX_PACKED;
-+      u32     pci_pm ACX_PACKED;
-+      u32     acm_wakeups ACX_PACKED;
-+
-+      u32     wep_key_count ACX_PACKED;
-+      u32     wep_default_key_count ACX_PACKED;
-+      u32     dot11_def_key_mib ACX_PACKED;
-+      u32     wep_key_not_found ACX_PACKED;
-+      u32     wep_decrypt_fail ACX_PACKED;
-+} fw_stats_t;
-+
-+/* Firmware version struct */
-+
-+typedef struct fw_ver {
-+      u16     cmd ACX_PACKED;
-+      u16     size ACX_PACKED;
-+      char    fw_id[20] ACX_PACKED;
-+      u32     hw_id ACX_PACKED;
-+} fw_ver_t;
-+
-+#define FW_ID_SIZE 20
-+
-+
-+/*--- 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 -----------------------------------------------------*/
-+/* priv->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 {
-+      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      used;                   /* misnamed, more like 'status' */
-+      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_INIT           (DESC_CTL_HOSTOWN | DESC_CTL_RECLAIM | \
-+                               DESC_CTL_AUTODMA | DESC_CTL_FIRSTFRAG)
-+#define       DESC_CTL_DONE           (DESC_CTL_ACXDONE | DESC_CTL_HOSTOWN)
-+
-+#define DESC_CTL_HOSTOWN_STR  "80"
-+#define       DESC_CTL_DONE_STR       "C0"
-+/* 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 ACX_PACKED;   /* pointer to next txdesc */
-+      acx_ptr HostMemPtr ACX_PACKED;                  /* 0x04 */
-+      acx_ptr AcxMemPtr ACX_PACKED;                   /* 0x08 */
-+      u32     tx_time ACX_PACKED;                     /* 0x0c */
-+      u16     total_length ACX_PACKED;                /* 0x10 */
-+      u16     Reserved ACX_PACKED;                    /* 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] ACX_PACKED;
-+
-+      u8      Ctl_8 ACX_PACKED;                       /* 0x24, 8bit value */
-+      u8      Ctl2_8 ACX_PACKED;                      /* 0x25, 8bit value */
-+      u8      error ACX_PACKED;                       /* 0x26 */
-+      u8      ack_failures ACX_PACKED;                /* 0x27 */
-+      u8      rts_failures ACX_PACKED;                /* 0x28 */
-+      u8      rts_ok ACX_PACKED;                      /* 0x29 */
-+      union {
-+              struct {
-+                      u8      rate ACX_PACKED;        /* 0x2a */
-+                      u8      queue_ctrl ACX_PACKED;  /* 0x2b */
-+              } r1 ACX_PACKED;
-+              struct {
-+                      u16     rate111 ACX_PACKED;     /* 0x2a */
-+              } r2 ACX_PACKED;
-+      } u ACX_PACKED;
-+      u32     queue_info ACX_PACKED;                  /* 0x2c (acx100, reserved on acx111) */
-+};            /* 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 ACX_PACKED;                   /* 0x00 */
-+      acx_ptr HostMemPtr ACX_PACKED;                  /* 0x04 */
-+      acx_ptr ACXMemPtr ACX_PACKED;                   /* 0x08 */
-+      u32     rx_time ACX_PACKED;                     /* 0x0c */
-+      u16     total_length ACX_PACKED;                /* 0x10 */
-+      u16     WEP_length ACX_PACKED;                  /* 0x12 */
-+      u32     WEP_ofs ACX_PACKED;                     /* 0x14 */
-+
-+/* the following 16 bytes do not change when acx100 owns the descriptor */
-+      u8      driverWorkspace[16] ACX_PACKED;         /* 0x18 */
-+
-+      u8      Ctl_8 ACX_PACKED;
-+      u8      rate ACX_PACKED;
-+      u8      error ACX_PACKED;
-+      u8      SNR ACX_PACKED;                         /* Signal-to-Noise Ratio */
-+      u8      RxLevel ACX_PACKED;
-+      u8      queue_ctrl ACX_PACKED;
-+      u16     unknown ACX_PACKED;
-+      u32     unknown2 ACX_PACKED;
-+};            /* size 52 = 0x34 */
-+
-+#ifdef ACX_PCI
-+
-+/* 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_HW_SLAVE_REG_ADDR,
-+        IO_ACX_HW_SLAVE_REG_DATA,
-+        IO_ACX_HW_SLAVE_REG_CTRL,
-+
-+      IO_ACX_SLV_MEM_ADDR,
-+      IO_ACX_SLV_MEM_DATA,
-+      IO_ACX_SLV_MEM_CTL,
-+      IO_ACX_SLV_END_CTL,
-+      IO_ACX_CHIPID,
-+
-+      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_IN,
-+        IO_ACX_GPIO_OUT,
-+        IO_ACX_GPIO_PD,
-+        IO_ACX_GPIO_CFG,
-+
-+      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,
-+
-+      IO_ACX_HI_CTRL,
-+      IO_ACX_LPWR_MGR,
-+
-+      IO_ACX_PCI_ARB_CFG,
-+};
-+/* ***** 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 ACX_PACKED;                    /* 0x00 [u8 *] */
-+      u16     data_offset ACX_PACKED;                 /* 0x04 */
-+      u16     reserved ACX_PACKED;                    /* 0x06 */
-+      u16     Ctl_16 ACX_PACKED;      /* 16bit value, endianness!! */
-+      u16     length ACX_PACKED;                      /* 0x0a */
-+      acx_ptr desc_phy_next ACX_PACKED;               /* 0x0c [txhostdesc *] */
-+      acx_ptr pNext ACX_PACKED;                       /* 0x10 [txhostdesc *] */
-+      u32     Status ACX_PACKED;                      /* 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 ACX_PACKED;                    /* 0x00 [rxbuffer_t *] */
-+      u16     data_offset ACX_PACKED;                 /* 0x04 */
-+      u16     reserved ACX_PACKED;                    /* 0x06 */
-+      u16     Ctl_16 ACX_PACKED;                      /* 0x08; 16bit value, endianness!! */
-+      u16     length ACX_PACKED;                      /* 0x0a */
-+      acx_ptr desc_phy_next ACX_PACKED;               /* 0x0c [rxhostdesc_t *] */
-+      acx_ptr pNext ACX_PACKED;                       /* 0x10 [rxhostdesc_t *] */
-+      u32     Status ACX_PACKED;                      /* 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
-+
-+/* Buffer size for fw upload */
-+#define ACX100_USB_RWMEM_MAXLEN       2048
-+
-+/* Should be sent to the ctrlout endpoint */
-+#define ACX100_USB_ENBULKIN   6
-+
-+/* The number of bulk URBs to use */
-+#define ACX100_USB_NUM_BULK_URBS 8
-+
-+/* 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
-+
-+/* Used for usb_txbuffer.desc field */
-+#define USB_TXBUF_TXDESC      0xA
-+/* Used for usb_txbuffer.hostData field */
-+#define USB_TXBUF_HD_ISDATA     0x10000
-+#define USB_TXBUF_HD_DIRECTED   0x20000
-+#define USB_TXBUF_HD_BROADCAST  0x40000
-+/* Size of header (everything up to data[]) */
-+#define USB_TXBUF_HDRSIZE     14
-+typedef struct usb_txbuffer {
-+      u16     desc ACX_PACKED;
-+      u16     MPDUlen ACX_PACKED;
-+      u8      index ACX_PACKED;
-+      u8      txRate ACX_PACKED;
-+      u32     hostData ACX_PACKED;
-+      u8      ctrl1 ACX_PACKED;
-+      u8      ctrl2 ACX_PACKED;
-+      u16     dataLength ACX_PACKED;
-+      /* wlan packet content is placed here: */
-+      u8      data[WLAN_A4FR_MAXLEN_WEP_FCS] ACX_PACKED;
-+} usb_txbuffer_t;
-+
-+typedef struct {
-+      void    *device;
-+      int     number;
-+} acx_usb_bulk_context_t;
-+
-+typedef struct usb_tx {
-+      unsigned        busy:1;
-+      struct urb      *urb;
-+      wlandevice_t    *priv;
-+      client_t        *txc;
-+      /* actual USB bulk output data block is here: */
-+      usb_txbuffer_t  bulkout;
-+} usb_tx_t;
-+
-+#endif /* ACX_USB */
-+
-+
-+/*============================================================================*
-+ * Main acx per-device data structure (netdev_priv(dev))                      *
-+ *============================================================================*/
-+#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 wlandevice {
-+      /*** Device chain ***/
-+      struct wlandevice       *next;          /* link for list of devices */
-+
-+      /*** Linux network device ***/
-+      struct net_device       *netdev;        /* pointer to linux netdevice */
-+      struct net_device       *prev_nd;       /* FIXME: We should not chain via our
-+                                               * private struct wlandevice _and_
-+                                               * the struct net_device. */
-+      /*** 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;
-+
-+      /*** Locking ***/
-+      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
-+
-+      /*** Hardware identification ***/
-+      const char      *chip_name;
-+      u8              dev_type;
-+      u8              chip_type;
-+      u8              form_factor;
-+      u8              radio_type;
-+      u8              eeprom_version;
-+
-+      /*** Firmware identification ***/
-+      char            firmware_version[FW_ID_SIZE+1];
-+      u32             firmware_numver;
-+      u32             firmware_id;
-+
-+      /*** 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 */
-+      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) */
-+
-+      unsigned long   dup_msg_expiry;
-+      int             dup_count;
-+      int             nondup_count;
-+      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;
-+      u16             ps_enhanced_transition_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;
-+      u32             short_retry;
-+      u32             long_retry;
-+      u16             msdu_lifetime;
-+      u16             listen_interval;        /* given in units of beacon interval */
-+      u32             beacon_interval;
-+
-+      u16             capabilities;
-+      u8              capab_short;
-+      u8              capab_pbcc;
-+      u8              capab_agility;
-+      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];
-+
-+      /*** Card Rx/Tx management ***/
-+      u16             rx_config_1;
-+      u16             rx_config_2;
-+      u16             memblocksize;
-+      u32             tx_free;
-+
-+      /*** Unknown ***/
-+      u8              dtim_interval;
-+
-+/*** 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 ***/
-+#ifdef ACX_PCI
-+      /* pointers to tx buffers, tx host descriptors (in host memory)
-+      ** and tx descrs in device memory */
-+      u8              *txbuf_start;
-+      txhostdesc_t    *txhostdesc_start;
-+      txdesc_t        *txdesc_start;  /* points to PCI-mapped memory */
-+      /* same for rx */
-+      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; */
-+      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    rxbuf_area_size;
-+      unsigned int    rxhostdesc_area_size;
-+
-+      unsigned int    txdesc_size;    /* size per tx descr; ACX111 = ACX100 + 4 */
-+      unsigned int    tx_head;        /* current ring buffer pool member index */
-+      unsigned int    tx_tail;
-+      unsigned int    rx_tail;
-+
-+      client_t        *txc[TX_CNT];
-+
-+      u8              need_radio_fw;
-+      u8              irqs_active;    /* whether irq sending is activated */
-+
-+      const u16       *io;            /* points to ACX100 or ACX111 I/O register address set */
-+
-+#if defined(CONFIG_ACX_CFI)
-+      struct device   *dev;
-+#else
-+      struct pci_dev  *pdev;
-+#endif
-+
-+      unsigned long   membase;
-+      unsigned long   membase2;
-+      void            *iobase;
-+      void            *iobase2;
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 10)
-+      /* 2.6.9-rc3-mm2 (2.6.9-bk4, too) introduced a shorter API version,
-+         then it made its way into 2.6.10 */
-+      u32             pci_state[16];          /* saved PCI state for suspend/resume */
-+#endif
-+      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;
-+
-+      /* command interface */
-+      void            *cmd_area;      /* points to PCI mapped memory */
-+      void            *info_area;     /* points to PCI mapped memory */
-+      u16             cmd_type;
-+      u16             cmd_status;
-+      u16             info_type;
-+      u16             info_status;
-+#endif
-+
-+      /*** USB stuff ***/
-+#ifdef ACX_USB
-+      struct usb_device       *usbdev;
-+
-+      rxbuffer_t      rxtruncbuf;
-+      /* TODO: convert (bulkins,bulkrx_urbs,rxcons) triple into
-+      ** struct usb_rx (see struct usb_tx for an example) */
-+      rxbuffer_t      bulkins[ACX100_USB_NUM_BULK_URBS];
-+      struct urb      *bulkrx_urbs[ACX100_USB_NUM_BULK_URBS];
-+      /* Used by rx urb completion handler in order to find
-+      ** corresponding priv/index pair */
-+      acx_usb_bulk_context_t  rxcons[ACX100_USB_NUM_BULK_URBS];
-+      usb_tx_t        usb_tx[ACX100_USB_NUM_BULK_URBS];
-+
-+      int             bulkinep;       /* bulk-in endpoint */
-+      int             bulkoutep;      /* bulk-out endpoint */
-+      int             rxtruncsize;
-+#endif
-+
-+};
-+
-+/* 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
-+#define GETSET_ALL            0x80000000L
-+
-+
-+/*============================================================================*
-+ * Firmware loading                                                           *
-+ *============================================================================*/
-+/* Doh, 2.4.x also has CONFIG_FW_LOADER_MODULE
-+ * (but doesn't have the new device model yet which we require!)
-+ * FIXME: exact version that introduced new device handling? */
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
-+#if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE)
-+#define USE_FW_LOADER_26 1
-+#define USE_FW_LOADER_LEGACY 0
-+#else
-+#define USE_FW_LOADER_26 0
-+#define USE_FW_LOADER_LEGACY 1
-+#endif
-+#endif
-+
-+#if USE_FW_LOADER_26
-+#include <linux/firmware.h>   /* request_firmware() */
-+#include <linux/pci.h>                /* struct pci_device */
-+#endif
-+
-+
-+/***********************************************************************
-+*/
-+typedef struct acx100_ie_memblocksize {
-+      u16     type ACX_PACKED;
-+      u16     len ACX_PACKED;
-+      u16     size ACX_PACKED;
-+} acx100_ie_memblocksize_t;
-+
-+typedef struct acx100_ie_queueconfig {
-+      u16     type ACX_PACKED;
-+      u16     len ACX_PACKED;
-+      u32     AreaSize ACX_PACKED;
-+      u32     RxQueueStart ACX_PACKED;
-+      u8      QueueOptions ACX_PACKED;
-+      u8      NumTxQueues ACX_PACKED;
-+      u8      NumRxDesc ACX_PACKED;    /* for USB only */
-+      u8      pad1 ACX_PACKED;
-+      u32     QueueEnd ACX_PACKED;
-+      u32     HostQueueEnd ACX_PACKED; /* QueueEnd2 */
-+      u32     TxQueueStart ACX_PACKED;
-+      u8      TxQueuePri ACX_PACKED;
-+      u8      NumTxDesc ACX_PACKED;
-+      u16     pad2 ACX_PACKED;
-+} acx100_ie_queueconfig_t;
-+
-+typedef struct acx111_ie_queueconfig {
-+      u16     type ACX_PACKED;
-+      u16     len ACX_PACKED;
-+      u32     tx_memory_block_address ACX_PACKED;
-+      u32     rx_memory_block_address ACX_PACKED;
-+      u32     rx1_queue_address ACX_PACKED;
-+      u32     reserved1 ACX_PACKED;
-+      u32     tx1_queue_address ACX_PACKED;
-+      u8      tx1_attributes ACX_PACKED;
-+      u16     reserved2 ACX_PACKED;
-+      u8      reserved3 ACX_PACKED;
-+} acx111_ie_queueconfig_t;
-+
-+typedef struct acx100_ie_memconfigoption {
-+      u16     type ACX_PACKED;
-+      u16     len ACX_PACKED;
-+      u32     DMA_config ACX_PACKED;
-+      acx_ptr pRxHostDesc ACX_PACKED;
-+      u32     rx_mem ACX_PACKED;
-+      u32     tx_mem ACX_PACKED;
-+      u16     RxBlockNum ACX_PACKED;
-+      u16     TxBlockNum ACX_PACKED;
-+} acx100_ie_memconfigoption_t;
-+
-+typedef struct acx111_ie_memoryconfig {
-+      u16     type ACX_PACKED;
-+      u16     len ACX_PACKED;
-+      u16     no_of_stations ACX_PACKED;
-+      u16     memory_block_size ACX_PACKED;
-+      u8      tx_rx_memory_block_allocation ACX_PACKED;
-+      u8      count_rx_queues ACX_PACKED;
-+      u8      count_tx_queues ACX_PACKED;
-+      u8      options ACX_PACKED;
-+      u8      fragmentation ACX_PACKED;
-+      u16     reserved1 ACX_PACKED;
-+      u8      reserved2 ACX_PACKED;
-+
-+      /* start of rx1 block */
-+      u8      rx_queue1_count_descs ACX_PACKED;
-+      u8      rx_queue1_reserved1 ACX_PACKED;
-+      u8      rx_queue1_type ACX_PACKED; /* must be set to 7 */
-+      u8      rx_queue1_prio ACX_PACKED; /* must be set to 0 */
-+      acx_ptr rx_queue1_host_rx_start ACX_PACKED;
-+      /* end of rx1 block */
-+
-+      /* start of tx1 block */
-+      u8      tx_queue1_count_descs ACX_PACKED;
-+      u8      tx_queue1_reserved1 ACX_PACKED;
-+      u8      tx_queue1_reserved2 ACX_PACKED;
-+      u8      tx_queue1_attributes ACX_PACKED;
-+      /* end of tx1 block */
-+} acx111_ie_memoryconfig_t;
-+
-+typedef struct acx_ie_memmap {
-+      u16     type ACX_PACKED;
-+      u16     len ACX_PACKED;
-+      u32     CodeStart ACX_PACKED;
-+      u32     CodeEnd ACX_PACKED;
-+      u32     WEPCacheStart ACX_PACKED;
-+      u32     WEPCacheEnd ACX_PACKED;
-+      u32     PacketTemplateStart ACX_PACKED;
-+      u32     PacketTemplateEnd ACX_PACKED;
-+      u32     QueueStart ACX_PACKED;
-+      u32     QueueEnd ACX_PACKED;
-+      u32     PoolStart ACX_PACKED;
-+      u32     PoolEnd ACX_PACKED;
-+} acx_ie_memmap_t;
-+
-+typedef struct acx111_ie_feature_config {
-+      u16     type ACX_PACKED;
-+      u16     len ACX_PACKED;
-+      u32     feature_options ACX_PACKED;
-+      u32     data_flow_options ACX_PACKED;
-+} acx111_ie_feature_config_t;
-+
-+typedef struct acx111_ie_tx_level {
-+      u16     type ACX_PACKED;
-+      u16     len ACX_PACKED;
-+      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_STILL_RCV_BCASTS       0x01
-+
-+typedef struct acx100_ie_powermgmt {
-+      u32     type ACX_PACKED;
-+      u32     len ACX_PACKED;
-+      u8      wakeup_cfg ACX_PACKED;
-+      u8      listen_interval ACX_PACKED; /* for EACH_ITVL: wake up every "beacon units" interval */
-+      u8      options ACX_PACKED;
-+      u8      hangover_period ACX_PACKED; /* remaining wake time after Tx MPDU w/ PS bit, in values of 1/1024 seconds */
-+      u16     enhanced_ps_transition_time ACX_PACKED; /* rem. wake time for Enh. PS */
-+} acx100_ie_powermgmt_t;
-+
-+typedef struct acx111_ie_powermgmt {
-+      u32     type ACX_PACKED;
-+      u32     len ACX_PACKED;
-+      u8      wakeup_cfg ACX_PACKED;
-+      u8      listen_interval ACX_PACKED; /* for EACH_ITVL: wake up every "beacon units" interval */
-+      u8      options ACX_PACKED;
-+      u8      hangover_period ACX_PACKED; /* remaining wake time after Tx MPDU w/ PS bit, in values of 1/1024 seconds */
-+      u32     beaconRxTime ACX_PACKED;
-+      u32     enhanced_ps_transition_time ACX_PACKED; /* rem. wake time for Enh. PS */
-+} acx111_ie_powermgmt_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_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 ACX_PACKED;       /* number of scans to do, 0xffff == continuous */
-+      u16     start_chan ACX_PACKED;
-+      u16     flags ACX_PACKED;       /* channel list mask; 0x8000 == all channels? */
-+      u8      max_rate ACX_PACKED;    /* max. probe rate */
-+      u8      options ACX_PACKED;     /* bit mask, see defines above */
-+      u16     chan_duration ACX_PACKED;
-+      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 ACX_PACKED;               /* number of scans to do */
-+      u8      channel_list_select ACX_PACKED; /* 0: scan all channels, 1: from chan_list only */
-+      u16     reserved1 ACX_PACKED;
-+      u8      reserved2 ACX_PACKED;
-+      u8      rate ACX_PACKED;                /* rate for probe requests (if active scan) */
-+      u8      options ACX_PACKED;             /* bit mask, see defines above */
-+      u16     chan_duration ACX_PACKED;       /* 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 ACX_PACKED;     /* max time to wait for reply on one channel (active scan) */
-+                                              /* time to listen on a channel (passive scan) */
-+      u8      modulation ACX_PACKED;
-+      u8      channel_list[26] ACX_PACKED;    /* bits 7:0 first byte: channels 8:1 */
-+                                              /* bits 7:0 second byte: channels 16:9 */
-+                                              /* 26 bytes is enough to cover 802.11a */
-+} 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 ACX_PACKED;
-+      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 ACX_PACKED;
-+      u8      tim_eid ACX_PACKED;     /* 00 1 TIM IE ID * */
-+      u8      len ACX_PACKED;         /* 01 1 Length * */
-+      u8      dtim_cnt ACX_PACKED;    /* 02 1 DTIM Count */
-+      u8      dtim_period ACX_PACKED; /* 03 1 DTIM Period */
-+      u8      bitmap_ctrl ACX_PACKED; /* 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 acx100_template_probereq {
-+      u16     size ACX_PACKED;
-+      u16     fc ACX_PACKED;          /* 00 2 fc */
-+      u16     dur ACX_PACKED;         /* 02 2 Duration */
-+      u8      da[6] ACX_PACKED;       /* 04 6 Destination Address * */
-+      u8      sa[6] ACX_PACKED;       /* 0A 6 Source Address * */
-+      u8      bssid[6] ACX_PACKED;    /* 10 6 BSSID * */
-+      u16     seq ACX_PACKED;         /* 16 2 Sequence Control */
-+      u8      timestamp[8] ACX_PACKED;/* 18 8 Timestamp */
-+      u16     beacon_interval ACX_PACKED; /* 20 2 Beacon Interval * */
-+      u16     cap ACX_PACKED;         /* 22 2 Capability Information * */
-+                                      /* 24 n SSID * */
-+                                      /* nn n Supported Rates * */
-+      u8      variable[0x44 - 2-2-6-6-6-2-8-2-2] ACX_PACKED;
-+} acx100_template_probereq_t;
-+
-+typedef struct acx111_template_probereq {
-+      u16     size ACX_PACKED;
-+      u16     fc ACX_PACKED;          /* 00 2 fc * */
-+      u16     dur ACX_PACKED;         /* 02 2 Duration */
-+      u8      da[6] ACX_PACKED;       /* 04 6 Destination Address * */
-+      u8      sa[6] ACX_PACKED;       /* 0A 6 Source Address * */
-+      u8      bssid[6] ACX_PACKED;    /* 10 6 BSSID * */
-+      u16     seq ACX_PACKED;         /* 16 2 Sequence Control */
-+                                      /* 18 n SSID * */
-+                                      /* nn n Supported Rates * */
-+      u8      variable[0x44 - 2-2-6-6-6-2] ACX_PACKED;
-+} acx111_template_probereq_t;
-+
-+typedef struct acx_template_proberesp {
-+      u16     size ACX_PACKED;
-+      u16     fc ACX_PACKED;          /* 00 2 fc * (bits [15:12] and [10:8] per 802.11 section 7.1.3.1) */
-+      u16     dur ACX_PACKED;         /* 02 2 Duration */
-+      u8      da[6] ACX_PACKED;       /* 04 6 Destination Address */
-+      u8      sa[6] ACX_PACKED;       /* 0A 6 Source Address */
-+      u8      bssid[6] ACX_PACKED;    /* 10 6 BSSID */
-+      u16     seq ACX_PACKED;         /* 16 2 Sequence Control */
-+      u8      timestamp[8] ACX_PACKED;/* 18 8 Timestamp */
-+      u16     beacon_interval ACX_PACKED; /* 20 2 Beacon Interval * */
-+      u16     cap ACX_PACKED;         /* 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 ACX_PACKED;
-+      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] ACX_PACKED;
-+      u16     beacon_interval ACX_PACKED;
-+      union {
-+              struct {
-+                      u8      dtim_interval ACX_PACKED;
-+                      u8      rates_basic ACX_PACKED;
-+                      u8      rates_supported ACX_PACKED;
-+              } acx100 ACX_PACKED;
-+              struct {
-+                      u16     rates_basic ACX_PACKED;
-+                      u8      dtim_interval ACX_PACKED;
-+              } acx111 ACX_PACKED;
-+      } u ACX_PACKED;
-+      u8      genfrm_txrate ACX_PACKED;       /* generated frame (bcn, proberesp, RTS, PSpoll) tx rate */
-+      u8      genfrm_mod_pre ACX_PACKED;      /* generated frame modulation/preamble:
-+                                              ** bit7: PBCC, bit6: OFDM (else CCK/DQPSK/DBPSK)
-+                                              ** bit5: short pre */
-+      u8      macmode ACX_PACKED;     /* BSS Type, must be one of ACX_MODE_xxx */
-+      u8      channel ACX_PACKED;
-+      u8      essid_len ACX_PACKED;
-+      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 ACX_PACKED;
-+      u16     type ACX_PACKED; /* 0x0 int. RAM / 0xffff MAC reg. / 0x81 PHY RAM / 0x82 PHY reg. */
-+      u32     len ACX_PACKED;
-+      u32     data ACX_PACKED;
-+} mem_read_write_t;
-+
-+typedef struct firmware_image {
-+      u32     chksum ACX_PACKED;
-+      u32     size ACX_PACKED;
-+      u8      data[1] ACX_PACKED; /* the byte array of the actual firmware... */
-+} firmware_image_t;
-+
-+typedef struct acx_cmd_radioinit {
-+      u32     offset ACX_PACKED;
-+      u32     len ACX_PACKED;
-+} acx_cmd_radioinit_t;
-+
-+typedef struct acx100_ie_wep_options {
-+      u16     type ACX_PACKED;
-+      u16     len ACX_PACKED;
-+      u16     NumKeys ACX_PACKED;     /* max # of keys */
-+      u8      WEPOption ACX_PACKED;   /* 0 == decrypt default key only, 1 == override decrypt */
-+      u8      Pad ACX_PACKED;         /* used only for acx111 */
-+} acx100_ie_wep_options_t;
-+
-+typedef struct ie_dot11WEPDefaultKey {
-+      u16     type ACX_PACKED;
-+      u16     len ACX_PACKED;
-+      u8      action ACX_PACKED;
-+      u8      keySize ACX_PACKED;
-+      u8      defaultKeyNum ACX_PACKED;
-+      u8      key[29] ACX_PACKED;     /* check this! was Key[19]. */
-+} ie_dot11WEPDefaultKey_t;
-+
-+typedef struct acx111WEPDefaultKey {
-+      u8      MacAddr[ETH_ALEN] ACX_PACKED;
-+      u16     action ACX_PACKED; /* NOTE: this is a u16, NOT a u8!! */
-+      u16     reserved ACX_PACKED;
-+      u8      keySize ACX_PACKED;
-+      u8      type ACX_PACKED;
-+      u8      index ACX_PACKED;
-+      u8      defaultKeyNum ACX_PACKED;
-+      u8      counter[6] ACX_PACKED;
-+      u8      key[32] ACX_PACKED;     /* up to 32 bytes (for TKIP!) */
-+} acx111WEPDefaultKey_t;
-+
-+typedef struct ie_dot11WEPDefaultKeyID {
-+      u16     type ACX_PACKED;
-+      u16     len ACX_PACKED;
-+      u8      KeyID ACX_PACKED;
-+} ie_dot11WEPDefaultKeyID_t;
-+
-+typedef struct acx100_cmd_wep_mgmt {
-+      u8      MacAddr[ETH_ALEN] ACX_PACKED;
-+      u16     Action ACX_PACKED;
-+      u16     KeySize ACX_PACKED;
-+      u8      Key[29] ACX_PACKED; /* 29*8 == 232bits == WEP256 */
-+} acx100_cmd_wep_mgmt_t;
-+
-+typedef struct defaultkey {
-+      u8      num;
-+} defaultkey_t;
-+
-+typedef struct acx_ie_generic {
-+      u16     type ACX_PACKED;
-+      u16     len ACX_PACKED;
-+      union {
-+              /* struct wep wp ACX_PACKED; */
-+              /* Association ID IE: just a 16bit value: */
-+              u16     aid;
-+              /* UNUSED? struct defaultkey dkey ACX_PACKED; */
-+              /* generic member for quick implementation of commands */
-+              u8      bytes[32] ACX_PACKED;
-+      } m ACX_PACKED;
-+} acx_ie_generic_t;
-+
-+/* Config Option structs */
-+
-+typedef struct co_antennas {
-+      u8      type ACX_PACKED;
-+      u8      len ACX_PACKED;
-+      u8      list[2] ACX_PACKED;
-+} co_antennas_t;
-+
-+typedef struct co_powerlevels {
-+      u8      type ACX_PACKED;
-+      u8      len ACX_PACKED;
-+      u16     list[8] ACX_PACKED;
-+} co_powerlevels_t;
-+
-+typedef struct co_datarates {
-+      u8      type ACX_PACKED;
-+      u8      len ACX_PACKED;
-+      u8      list[8] ACX_PACKED;
-+} co_datarates_t;
-+
-+typedef struct co_domains {
-+      u8      type ACX_PACKED;
-+      u8      len ACX_PACKED;
-+      u8      list[6] ACX_PACKED;
-+} co_domains_t;
-+
-+typedef struct co_product_id {
-+      u8      type ACX_PACKED;
-+      u8      len ACX_PACKED;
-+      u8      list[128] ACX_PACKED;
-+} co_product_id_t;
-+
-+typedef struct co_manuf_id {
-+      u8      type ACX_PACKED;
-+      u8      len ACX_PACKED;
-+      u8      list[128] ACX_PACKED;
-+} co_manuf_t;
-+
-+typedef struct co_fixed {
-+      u8      type ACX_PACKED;
-+      u8      len ACX_PACKED;
-+      char    NVSv[8] ACX_PACKED;
-+      u8      MAC[6] ACX_PACKED;
-+      u16     probe_delay ACX_PACKED;
-+      u32     eof_memory ACX_PACKED;
-+      u8      dot11CCAModes ACX_PACKED;
-+      u8      dot11Diversity ACX_PACKED;
-+      u8      dot11ShortPreambleOption ACX_PACKED;
-+      u8      dot11PBCCOption ACX_PACKED;
-+      u8      dot11ChannelAgility ACX_PACKED;
-+      u8      dot11PhyType ACX_PACKED;
-+/*    u8      dot11TempType ACX_PACKED;
-+      u8      num_var ACX_PACKED;           seems to be erased     */
-+} co_fixed_t;
-+
-+
-+typedef struct acx111_ie_configoption {
-+      co_fixed_t              configoption_fixed ACX_PACKED;
-+      co_antennas_t           antennas ACX_PACKED;
-+      co_powerlevels_t        power_levels ACX_PACKED;
-+      co_datarates_t          data_rates ACX_PACKED;
-+      co_domains_t            domains ACX_PACKED;
-+      co_product_id_t         product_id ACX_PACKED;
-+      co_manuf_t              manufacturer ACX_PACKED;
-+} acx111_ie_configoption_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);
-+}
-+
-+
-+/*============================================================================*
-+ * Global data                                                                *
-+ *============================================================================*/
-+extern const u8 bitpos2ratebyte[];
-+extern const u8 bitpos2rate100[];
-+
-+extern const u8 reg_domain_ids[];
-+extern const u8 reg_domain_ids_len;
-+
-+extern const struct iw_handler_def acx_ioctl_handler_def;
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/net/wireless/tiacx/cfi.c bt_kernel/drivers/net/wireless/tiacx/cfi.c
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/net/wireless/tiacx/cfi.c    1970-01-01 02:00:00.000000000 +0200
-+++ bt_kernel/drivers/net/wireless/tiacx/cfi.c 2005-10-29 22:02:44.690471000 +0300
-@@ -0,0 +1,4779 @@
-+/***********************************************************************
-+** 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/config.h>
-+#include <linux/version.h>
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
-+#include <linux/moduleparam.h>
-+#endif
-+#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>
-+#if WIRELESS_EXT >= 13
-+#include <net/iw_handler.h>
-+#endif
-+#include <linux/device.h>
-+#include <linux/netdevice.h>
-+#include <linux/etherdevice.h>
-+#include <linux/ioport.h>
-+#include <linux/pm.h>
-+#include <linux/vmalloc.h>
-+
-+#include <asm/hardware.h>
-+#include <asm/mach-types.h>
-+#include <asm/sizes.h>
-+#include <asm/arch/tc.h>
-+
-+#include <asm/io.h>
-+#include <asm/irq.h>
-+#include <asm/arch/gpio.h>
-+#include <asm/arch/pca9535.h>
-+
-+#include "acx.h"
-+
-+#define CARDNAME "tnetw1100b"
-+
-+/*================================================================*/
-+/* Local Constants */
-+#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      0x280
-+
-+#define CARD_EEPROM_ID_SIZE 6
-+#define MAX_IRQLOOPS_PER_JIFFY  (20000/HZ) /* a la orinoco.c */
-+
-+
-+/***********************************************************************
-+*/
-+static void acx_l_disable_irq(wlandevice_t *priv);
-+static void acx_l_enable_irq(wlandevice_t *priv);
-+static int acx_drv_probe(struct device *dev);
-+static int acx_remove(struct device *dev);
-+
-+static inline void test(wlandevice_t *priv);
-+
-+#ifdef CONFIG_PM
-+static int acx_suspend(struct device *dev, pm_message_t state, u32 level);
-+static int acx_resume(struct device *dev, u32 level);
-+#endif
-+
-+static void acx_i_tx_timeout(netdevice_t *dev);
-+static struct net_device_stats *acx_e_get_stats(netdevice_t *dev);
-+static struct iw_statistics *acx_e_get_wireless_stats(netdevice_t *dev);
-+
-+static irqreturn_t acx_i_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-+static void acx_i_set_multicast_list(netdevice_t *dev);
-+
-+static int acx_e_open(netdevice_t *dev);
-+static int acx_e_close(netdevice_t *dev);
-+static void acx_s_up(netdevice_t *dev);
-+static void acx_s_down(netdevice_t *dev);
-+
-+
-+/***********************************************************************
-+** Register access
-+*/
-+
-+/* Pick one */
-+/* #define INLINE_IO static */
-+#define INLINE_IO static inline
-+
-+INLINE_IO u32
-+acx_read_reg32(wlandevice_t *priv, unsigned int offset)
-+{
-+#if ACX_IO_WIDTH == 32
-+      return readl((u8 *)priv->iobase + priv->io[offset]);
-+#else
-+      return readw((u8 *)priv->iobase + priv->io[offset])
-+          + (readw((u8 *)priv->iobase + priv->io[offset] + 2) << 16);
-+#endif
-+}
-+
-+INLINE_IO u16
-+acx_read_reg16(wlandevice_t *priv, unsigned int offset)
-+{
-+      return readw((u8 *)priv->iobase + priv->io[offset]);
-+}
-+
-+INLINE_IO u8
-+acx_read_reg8(wlandevice_t *priv, unsigned int offset)
-+{
-+      return readb((u8 *)priv->iobase + priv->io[offset]);
-+}
-+
-+INLINE_IO void
-+acx_write_reg32(wlandevice_t *priv, unsigned int offset, u32 val)
-+{
-+#if ACX_IO_WIDTH == 32
-+      writel(val, (u8 *)priv->iobase + priv->io[offset]);
-+#else
-+      writew(val & 0xffff, (u8 *)priv->iobase + priv->io[offset]);
-+      writew(val >> 16, (u8 *)priv->iobase + priv->io[offset] + 2);
-+#endif
-+}
-+
-+INLINE_IO void
-+acx_write_reg16(wlandevice_t *priv, unsigned int offset, u16 val)
-+{
-+      writew(val, (u8 *)priv->iobase + priv->io[offset]);
-+}
-+
-+INLINE_IO void
-+acx_write_reg8(wlandevice_t *priv, unsigned int offset, u8 val)
-+{
-+      writeb(val, (u8 *)priv->iobase + priv->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
-+acx_write_flush(wlandevice_t *priv)
-+{
-+      /* readb(priv->iobase + priv->io[IO_ACX_INFO_MAILBOX_OFFS]); */
-+      /* faster version (accesses the first register, IO_ACX_SOFT_RESET,
-+       * which should also be safe): */
-+      readb(priv->iobase);
-+}
-+
-+
-+INLINE_IO void acx_mailbox_fill(wlandevice_t *priv, unsigned int offset, unsigned char val, int len){
-+        unsigned int  addr  = offset;
-+        unsigned int  buff  = 0;
-+
-+      // Fill the buffer
-+      memset((void *) &buff, val, len);
-+
-+      acx_write_reg32(priv, IO_ACX_SLV_END_CTL, 0);
-+        acx_write_reg32(priv, IO_ACX_SLV_MEM_CTL, 0x00010000);
-+        acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR, addr);
-+
-+        while(len >= 4){
-+              // Write data
-+                acx_write_reg32(priv, IO_ACX_SLV_MEM_DATA,buff);
-+                acx_write_flush(priv);
-+
-+                addr += 4;
-+                len  -= 4;
-+        }
-+
-+        if(len > 0) {
-+                val = 0;
-+                memset((void *) &buff, val , len);
-+
-+                acx_write_reg32(priv, IO_ACX_SLV_MEM_DATA,buff);
-+                acx_write_flush(priv);
-+        }
-+}
-+
-+
-+INLINE_IO void acx_mailbox_write(wlandevice_t *priv, unsigned int offset, void *cmd, int len){
-+      unsigned char *buff = (unsigned char *) cmd;
-+        unsigned int  addr  = offset;
-+      unsigned int  val   = 0;
-+
-+      if(!cmd){
-+              return;
-+      }
-+
-+      acx_write_reg32(priv, IO_ACX_SLV_END_CTL, 0);
-+        acx_write_reg32(priv, IO_ACX_SLV_MEM_CTL, 0x00010000);
-+        acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR, addr);
-+
-+        while(len >= 4){
-+                acx_write_reg32(priv, IO_ACX_SLV_MEM_DATA,*((unsigned int *) buff));
-+              acx_write_flush(priv);
-+
-+                buff += 4;
-+                addr += 4;
-+              len  -= 4;
-+        }
-+
-+      if(len > 0) {
-+              val = 0;
-+              memcpy((void *) &val, (void *) buff, len);
-+
-+              acx_write_reg32(priv, IO_ACX_SLV_MEM_DATA,val);
-+              acx_write_flush(priv);
-+      }
-+}
-+
-+INLINE_IO void acx_mailbox_read(wlandevice_t *priv, unsigned int offset, void *data, int len){
-+        unsigned char *buff = (unsigned char *) data;
-+        unsigned int  addr  = offset;
-+      unsigned int  value = 0;
-+
-+      if(!data){
-+              return;
-+      }
-+
-+      acx_write_reg32(priv, IO_ACX_SLV_END_CTL, 0);
-+        acx_write_reg32(priv, IO_ACX_SLV_MEM_CTL, 0x00010000);
-+      acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR, addr);       
-+
-+        while(len >= 4){
-+              *buff = 0;
-+                *((unsigned int *) buff) = acx_read_reg32(priv, IO_ACX_SLV_MEM_DATA);
-+
-+                buff += 4;
-+                addr += 4;
-+              len  -= 4;
-+        }
-+
-+      if(len > 0){
-+              value = acx_read_reg32(priv, IO_ACX_SLV_MEM_DATA);
-+              memcpy((void *) buff, (void *) &value, len);
-+      }
-+}
-+
-+/***********************************************************************
-+*/
-+static const char name_acx100[] = "ACX100";
-+static const char name_tnetw1100a[] = "TNETW1100A";
-+static const char name_tnetw1100b[] = "TNETW1100B";
-+
-+static const char name_acx111[] = "ACX111";
-+static const char name_tnetw1130[] = "TNETW1130";
-+
-+struct device_driver acx_driver = {
-+        .name           = CARDNAME,
-+        .bus            = &platform_bus_type,
-+        .probe          = acx_drv_probe,
-+        .remove         = acx_remove,
-+#ifdef CONFIG_PM
-+        .suspend        = acx_suspend,
-+        .resume         = acx_resume
-+#endif
-+};
-+
-+typedef struct acx_device {
-+      netdevice_t *newest;
-+} acx_device_t;
-+
-+/* if this driver was only about PCI devices, then we probably wouldn't
-+ * need this linked list.
-+ * But if we want to register ALL kinds of devices in one global list,
-+ * then we need it and need to maintain it properly. */
-+static struct acx_device root_acx_dev = {
-+      .newest         = NULL,
-+};
-+DECLARE_MUTEX(root_acx_dev_sem);
-+
-+
-+/***********************************************************************
-+*/
-+static inline txdesc_t*
-+get_txdesc(wlandevice_t* priv, int index)
-+{
-+      return (txdesc_t*) (((u8*)priv->txdesc_start) + index * priv->txdesc_size);
-+}
-+
-+static inline txdesc_t*
-+move_txdesc(wlandevice_t* priv, txdesc_t* txdesc, int inc)
-+{
-+      return (txdesc_t*) (((u8*)txdesc) + inc * priv->txdesc_size);
-+}
-+
-+static txhostdesc_t*
-+acx_get_txhostdesc(wlandevice_t* priv, txdesc_t* txdesc)
-+{
-+      int index = (u8*)txdesc - (u8*)priv->txdesc_start;
-+      if (ACX_DEBUG && (index % priv->txdesc_size)) {
-+              printk("bad txdesc ptr %p\n", txdesc);
-+              return NULL;
-+      }
-+      index /= priv->txdesc_size;
-+      if (ACX_DEBUG && (index >= TX_CNT)) {
-+              printk("bad txdesc ptr %p\n", txdesc);
-+              return NULL;
-+      }
-+      return &priv->txhostdesc_start[index*2];
-+}
-+
-+static client_t*
-+acx_get_txc(wlandevice_t* priv, txdesc_t* txdesc)
-+{
-+      int index = (u8*)txdesc - (u8*)priv->txdesc_start;
-+      if (ACX_DEBUG && (index % priv->txdesc_size)) {
-+              printk("bad txdesc ptr %p\n", txdesc);
-+              return NULL;
-+      }
-+      index /= priv->txdesc_size;
-+      if (ACX_DEBUG && (index >= TX_CNT)) {
-+              printk("bad txdesc ptr %p\n", txdesc);
-+              return NULL;
-+      }
-+      return priv->txc[index];
-+}
-+
-+static void
-+acx_put_txc(wlandevice_t* priv, txdesc_t* txdesc, client_t* c)
-+{
-+      int index = (u8*)txdesc - (u8*)priv->txdesc_start;
-+      if (ACX_DEBUG && (index % priv->txdesc_size)) {
-+              printk("bad txdesc ptr %p\n", txdesc);
-+              return;
-+      }
-+      index /= priv->txdesc_size;
-+      if (ACX_DEBUG && (index >= TX_CNT)) {
-+              printk("bad txdesc ptr %p\n", txdesc);
-+              return;
-+      }
-+      priv->txc[index] = c;
-+}
-+
-+/***********************************************************************
-+** EEPROM and PHY read/write helpers
-+*/
-+/***********************************************************************
-+** acx_read_eeprom_offset
-+**
-+** Function called to read an octet in the EEPROM.
-+**
-+** This function is used by acx_probe_pci to check if the
-+** connected card is a legal one or not.
-+**
-+** Arguments:
-+**    priv            ptr to wlandevice structure
-+**    addr            address to read in the EEPROM
-+**    charbuf         ptr to a char. This is where the read octet
-+**                    will be stored
-+**
-+** Returns:
-+**    zero (0)        - failed
-+**    one (1)         - success
-+**
-+** NOT ADAPTED FOR ACX111!!
-+*/
-+int
-+acx_read_eeprom_offset(wlandevice_t *priv, u32 addr, u8 *charbuf)
-+{
-+      int result = NOT_OK;
-+      int count;
-+
-+      acx_write_reg32(priv, IO_ACX_EEPROM_CFG, 0);
-+      acx_write_reg32(priv, IO_ACX_EEPROM_ADDR, addr);
-+      acx_write_flush(priv);
-+      acx_write_reg32(priv, IO_ACX_EEPROM_CTL, 2);
-+
-+      count = 0xffff;
-+      while (acx_read_reg16(priv, 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",
-+                                                      priv->netdev->name);
-+                      goto fail;
-+              }
-+      }
-+
-+      *charbuf = acx_read_reg8(priv, IO_ACX_EEPROM_DATA);
-+      acxlog(L_DEBUG, "EEPROM at 0x%04X = 0x%02X\n", addr, *charbuf);
-+      result = OK;
-+
-+fail:
-+      return result;
-+}
-+
-+
-+/***********************************************************************
-+** Dummy EEPROM read? why?!
-+*/
-+static int
-+acx_read_eeprom_area(wlandevice_t *priv)
-+{
-+      int offs;
-+      u8 tmp[0x3b];
-+
-+      for (offs = 0x8c; offs < 0xb9; offs++) {
-+              acx_read_eeprom_offset(priv, offs, &tmp[offs - 0x8c]);
-+      }
-+      return OK;
-+}
-+
-+
-+/***********************************************************************
-+** 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
-+acx_s_write_eeprom_offset(wlandevice_t *priv, 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 = acx_read_reg16(priv, IO_ACX_GPIO_OE);
-+      acx_write_reg16(priv, IO_ACX_GPIO_OE, gpio_orig & ~1);
-+      acx_write_flush(priv);
-+
-+      /* ok, now start writing the data out */
-+      for (i = 0; i < len; i++) {
-+              acx_write_reg32(priv, IO_ACX_EEPROM_CFG, 0);
-+              acx_write_reg32(priv, IO_ACX_EEPROM_ADDR, addr + i);
-+              acx_write_reg32(priv, IO_ACX_EEPROM_DATA, *(charbuf + i));
-+              acx_write_flush(priv);
-+              acx_write_reg32(priv, IO_ACX_EEPROM_CTL, 1);
-+
-+              while (acx_read_reg16(priv, IO_ACX_EEPROM_CTL)) {
-+                      if (unlikely(++count > 0xffff)) {
-+                              printk("WARNING, DANGER!!! "
-+                                      "Timeout waiting for EEPROM write\n");
-+                              goto end;
-+                      }
-+              }
-+      }
-+
-+      /* disable EEPROM writing */
-+      acx_write_reg16(priv, IO_ACX_GPIO_OE, gpio_orig);
-+      acx_write_flush(priv);
-+
-+      /* now start a verification run */
-+      count = 0xffff;
-+      for (i = 0; i < len; i++) {
-+              acx_write_reg32(priv, IO_ACX_EEPROM_CFG, 0);
-+              acx_write_reg32(priv, IO_ACX_EEPROM_ADDR, addr + i);
-+              acx_write_flush(priv);
-+              acx_write_reg32(priv, IO_ACX_EEPROM_CTL, 2);
-+
-+              while (acx_read_reg16(priv, IO_ACX_EEPROM_CTL)) {
-+                      if (unlikely(!--count)) {
-+                              printk("timeout waiting for EEPROM read\n");
-+                              goto end;
-+                      }
-+              }
-+
-+              data_verify[i] = acx_read_reg16(priv, 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
-+** (acx_write_reg32(priv, IO_ACX_ENABLE, 0b000000xx)) kills traffic
-+*/
-+int
-+acxpci_s_read_phy_reg(wlandevice_t *priv, u32 reg, u8 *charbuf)
-+{
-+      int result = NOT_OK;
-+      int count;
-+
-+      FN_ENTER;
-+
-+      acx_write_reg32(priv, IO_ACX_PHY_ADDR, reg);
-+      acx_write_flush(priv);
-+      acx_write_reg32(priv, IO_ACX_PHY_CTL, 2);
-+
-+      count = 0xffff;
-+      while (acx_read_reg32(priv, 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",
-+                                                      priv->netdev->name);
-+                      *charbuf = 0;
-+                      goto fail;
-+              }
-+      }
-+
-+      acxlog(L_DEBUG, "count was %u\n", count);
-+      *charbuf = acx_read_reg8(priv, IO_ACX_PHY_DATA);
-+
-+      acxlog(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(wlandevice_t *priv, u32 reg, u8 value)
-+{
-+      FN_ENTER;
-+
-+      /* FIXME: we didn't use 32bit access here since mprusko said that
-+       * it results in distorted sensitivity on his card (huh!?!?
-+       * doesn't happen with my setup...)
-+       * But with the access reordering and flushing it
-+       * shouldn't happen any more...
-+       * FIXME: which radio is in the problematic card? My working one
-+       * is 0x11 */
-+      acx_write_reg32(priv, IO_ACX_PHY_DATA, value);
-+      acx_write_reg32(priv, IO_ACX_PHY_ADDR, reg);
-+      acx_write_flush(priv);
-+      acx_write_reg32(priv, IO_ACX_PHY_CTL, 1);
-+      acx_write_flush(priv);
-+      acxlog(L_DEBUG, "radio PHY write 0x%02X at 0x%04X\n", value, reg);
-+
-+      FN_EXIT1(OK);
-+      return OK;
-+}
-+
-+
-+#define NO_AUTO_INCREMENT     1
-+
-+/***********************************************************************
-+** acx_s_write_fw
-+**
-+** Write the firmware image into the card.
-+**
-+** Arguments:
-+**    priv            wlan device structure
-+**    apfw_image      firmware image.
-+**
-+** Returns:
-+**    1       firmware image corrupted
-+**    0       success
-+*/
-+static int
-+acx_s_write_fw(wlandevice_t *priv, const firmware_image_t *apfw_image, u32 offset)
-+{
-+      int len, size;
-+      u32 sum, v32;
-+      /* we skip the first four bytes which contain the control sum */
-+      const u8 *image = (u8*)apfw_image + 4;
-+
-+      /* start the image checksum by adding the image size value */
-+      sum = image[0]+image[1]+image[2]+image[3];
-+      image += 4;
-+
-+      acx_write_reg32(priv, IO_ACX_SLV_END_CTL, 0);
-+
-+#if NO_AUTO_INCREMENT
-+      acxlog(L_INIT, "not using auto increment for firmware loading\n");
-+      acx_write_reg32(priv, IO_ACX_SLV_MEM_CTL, 0); /* use basic mode */
-+#else
-+      acx_write_reg32(priv, IO_ACX_SLV_MEM_CTL, 1); /* use autoincrement mode */
-+      acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR, offset); /* configure start address */
-+      acx_write_flush(priv);
-+#endif
-+
-+      len = 0;
-+      size = le32_to_cpu(apfw_image->size) & (~3);
-+
-+      while (likely(len < size)) {
-+              v32 = be32_to_cpu(*(u32*)image);
-+              sum += image[0]+image[1]+image[2]+image[3];
-+              image += 4;
-+              len += 4;
-+
-+#if NO_AUTO_INCREMENT
-+              acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR, offset + len - 4);
-+              acx_write_flush(priv);
-+#endif
-+              acx_write_reg32(priv, IO_ACX_SLV_MEM_DATA, v32);
-+      }
-+
-+      acxlog(L_DEBUG, "%s: firmware written\n", __func__);
-+
-+      /* compare our checksum with the stored image checksum */
-+      return (sum != le32_to_cpu(apfw_image->chksum));
-+}
-+
-+
-+/***********************************************************************
-+** acx_s_validate_fw
-+**
-+** Compare the firmware image given with
-+** the firmware image written into the card.
-+**
-+** Arguments:
-+**    priv            wlan device structure
-+**   apfw_image  firmware image.
-+**
-+** Returns:
-+**    NOT_OK  firmware image corrupted or not correctly written
-+**    OK      success
-+*/
-+static int
-+acx_s_validate_fw(wlandevice_t *priv, const firmware_image_t *apfw_image,
-+                              u32 offset)
-+{
-+      u32 v32, w32, sum;
-+      int len, size;
-+      int result = OK;
-+      /* we skip the first four bytes which contain the control sum */
-+      const u8 *image = (u8*)apfw_image + 4;
-+
-+      /* start the image checksum by adding the image size value */
-+      sum = image[0]+image[1]+image[2]+image[3];
-+      image += 4;
-+
-+      acx_write_reg32(priv, IO_ACX_SLV_END_CTL, 0);
-+
-+#if NO_AUTO_INCREMENT
-+      acx_write_reg32(priv, IO_ACX_SLV_MEM_CTL, 0); /* use basic mode */
-+#else
-+      acx_write_reg32(priv, IO_ACX_SLV_MEM_CTL, 1); /* use autoincrement mode */
-+      acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR, offset); /* configure start address */
-+#endif
-+
-+      len = 0;
-+      size = le32_to_cpu(apfw_image->size) & (~3);
-+
-+      while (likely(len < size)) {
-+              v32 = be32_to_cpu(*(u32*)image);
-+              image += 4;
-+              len += 4;
-+
-+#if NO_AUTO_INCREMENT
-+              acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR, offset + len - 4);
-+#endif
-+              w32 = acx_read_reg32(priv, 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(apfw_image->chksum)) {
-+                      printk("acx: FATAL: firmware upload: "
-+                              "checksums don't match!\n");
-+                      result = NOT_OK;
-+              }
-+      }
-+
-+      return result;
-+}
-+
-+
-+/***********************************************************************
-+** acx_s_upload_fw
-+**
-+** Arguments:
-+**    wlandevice: private device that contains card device
-+** Returns:
-+**    NOT_OK: failed
-+**    OK: success
-+** Call context:
-+**    acx_reset_dev
-+*/
-+static int
-+acx_s_upload_fw(wlandevice_t *priv)
-+{
-+      firmware_image_t *apfw_image = NULL;
-+      int res = NOT_OK;
-+      int try;
-+      u32 size;
-+      char filename[sizeof("tiacx1NNcNN")];
-+
-+      FN_ENTER;
-+
-+      /* Try combined, then main image */
-+      priv->need_radio_fw = 0;
-+      sprintf(filename, "tiacx1%02dc%02X",
-+              IS_ACX111(priv)*11, priv->radio_type);
-+
-+      apfw_image = acx_s_read_fw(priv->dev, filename, &size);
-+      if (!apfw_image) {
-+              priv->need_radio_fw = 1;
-+              filename[sizeof("tiacx1NN")-1] = '\0';
-+              apfw_image = acx_s_read_fw(priv->dev, filename, &size);
-+              if (!apfw_image) {
-+                      FN_EXIT1(NOT_OK);
-+                      return NOT_OK;
-+              }
-+      }
-+
-+      for (try = 1; try <= 5; try++) {
-+              res = acx_s_write_fw(priv, apfw_image, 0);
-+              acxlog(L_DEBUG|L_INIT, "acx_write_fw (main/combined):%d\n", res);
-+              if (OK == res) {
-+                      res = acx_s_validate_fw(priv, apfw_image, 0);
-+                      acxlog(L_DEBUG|L_INIT, "acx_validate_fw "
-+                                      "(main/combined):%d\n", res);
-+              }
-+
-+              if (OK == res) {
-+                      SET_BIT(priv->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((void *) apfw_image);
-+
-+      FN_EXIT1(res);
-+      return res;
-+}
-+
-+
-+/***********************************************************************
-+** acx_s_upload_radio
-+**
-+** Uploads the appropriate radio module firmware
-+** into the card.
-+*/
-+int
-+acx_s_upload_radio(wlandevice_t *priv)
-+{
-+      acx_ie_memmap_t mm;
-+      firmware_image_t *radio_image = NULL;
-+      acx_cmd_radioinit_t radioinit;
-+      int res = NOT_OK;
-+      int try;
-+      u32 offset;
-+      u32 size;
-+      char filename[sizeof("tiacx1NNrNN")];
-+
-+      if (!priv->need_radio_fw) return OK;
-+
-+      FN_ENTER;
-+
-+      acx_s_interrogate(priv, &mm, ACX1xx_IE_MEMORY_MAP);
-+      offset = le32_to_cpu(mm.CodeEnd);
-+
-+      sprintf(filename, "tiacx1%02dr%02X",
-+              IS_ACX111(priv)*11,
-+              priv->radio_type);
-+      radio_image = acx_s_read_fw(priv->dev, filename, &size);
-+      if (!radio_image) {
-+              printk("acx: can't load radio module '%s'\n", filename);
-+              goto fail;
-+      }
-+
-+      acx_s_issue_cmd(priv, ACX1xx_CMD_SLEEP, NULL, 0);
-+
-+      for (try = 1; try <= 5; try++) {
-+              res = acx_s_write_fw(priv, radio_image, offset);
-+              acxlog(L_DEBUG|L_INIT, "acx_write_fw (radio): %d\n", res);
-+              if (OK == res) {
-+                      res = acx_s_validate_fw(priv, radio_image, offset);
-+                      acxlog(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(priv, 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(priv, ACX1xx_CMD_RADIOINIT,
-+              &radioinit, sizeof(radioinit), CMD_TIMEOUT_MS(1000));
-+
-+      res = acx_s_interrogate(priv, &mm, ACX1xx_IE_MEMORY_MAP);
-+fail:
-+      FN_EXIT1(res);
-+      return res;
-+}
-+
-+void write_reg(wlandevice_t *priv, int reg, u32 value){
-+        acx_write_reg32(priv,IO_ACX_HW_SLAVE_REG_ADDR,priv->io[reg]);
-+        acx_write_reg16(priv,IO_ACX_HW_SLAVE_REG_DATA,value);
-+}
-+
-+u32 read_reg(wlandevice_t *priv, int reg){
-+      u32 value;
-+
-+        acx_write_reg32(priv,IO_ACX_HW_SLAVE_REG_ADDR,reg);
-+        value = acx_read_reg32(priv,IO_ACX_HW_SLAVE_REG_DATA);
-+
-+      return value;
-+}
-+
-+
-+/***********************************************************************
-+** acx_l_reset_mac
-+**
-+** Arguments:
-+**    wlandevice: private device that contains card device
-+** Side effects:
-+**    MAC will be reset
-+** Call context:
-+**    acx_reset_dev
-+** Comment:
-+**    resets onboard acx100 MAC
-+**
-+** Requires lock to be taken
-+*/
-+static void
-+acx_l_reset_mac(wlandevice_t *priv)
-+{
-+      u16 temp;
-+
-+      FN_ENTER;
-+
-+      /* Pocket PC driver setting this register
-+       * with 2.
-+       */
-+      acx_write_reg16(priv,IO_ACX_PCI_ARB_CFG,0x2);
-+
-+      msleep(300);
-+      
-+      /* halt eCPU */
-+      acxlog(L_DEBUG, "%s: Halt eCPU ...\n", __func__);
-+      temp = acx_read_reg16(priv, IO_ACX_ECPU_CTRL) | 0x1;
-+      acx_write_reg16(priv, IO_ACX_ECPU_CTRL, temp);
-+      acx_write_flush(priv);
-+
-+      test(priv);
-+
-+      /* now do soft reset of eCPU */
-+      temp = acx_read_reg16(priv, IO_ACX_SOFT_RESET) | 0x1;
-+      acxlog(L_DEBUG, "%s: enable soft reset...\n", __func__);
-+      acx_write_reg16(priv, IO_ACX_SOFT_RESET, temp);
-+      acx_write_flush(priv);
-+
-+      test(priv);
-+
-+      /* now reset bit again */
-+      acxlog(L_DEBUG, "%s: disable soft reset and go to init mode...\n", __func__);
-+      /* deassert eCPU reset */
-+      acx_write_reg16(priv, IO_ACX_SOFT_RESET, temp & ~0x1);
-+
-+      /* now start a burst read from initial flash EEPROM */
-+      temp = acx_read_reg16(priv, IO_ACX_EE_START) | 0x1;
-+      acx_write_reg16(priv, IO_ACX_EE_START, temp);
-+      acx_write_flush(priv);
-+      
-+      test(priv);
-+
-+      FN_EXIT0;
-+}
-+
-+
-+/***********************************************************************
-+** acx_s_verify_init
-+*/
-+static int
-+acx_s_verify_init(wlandevice_t *priv)
-+{
-+      int result = NOT_OK;
-+      int timer;
-+
-+      FN_ENTER;
-+
-+      for (timer = 40; timer > 0; timer--) {
-+              u16 irqstat = acx_read_reg16(priv, IO_ACX_IRQ_STATUS_NON_DES);
-+              if (irqstat & HOST_INT_FCS_THRESHOLD) {
-+                      result = OK;
-+                      acx_write_reg16(priv, IO_ACX_IRQ_ACK, HOST_INT_FCS_THRESHOLD);
-+                      break;
-+              }
-+              /* HZ / 50 resulted in 24 schedules for ACX100 on my machine,
-+               * so better schedule away longer for greater efficiency,
-+               * decrease loop count */
-+              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
-+*/
-+
-+/***********************************************************************
-+** acx_read_info_status
-+*/
-+/* Info mailbox format:
-+2 bytes: type
-+2 bytes: status
-+more bytes may follow
-+    docs 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 is no message 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
-+acx_read_info_status(wlandevice_t *priv)
-+{
-+      u32 value;
-+
-+      acx_write_reg32(priv, IO_ACX_SLV_END_CTL, 0x0);
-+      acx_write_reg32(priv, IO_ACX_SLV_MEM_CTL, 0x1);
-+
-+      acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR,
-+              acx_read_reg32(priv, IO_ACX_INFO_MAILBOX_OFFS));
-+
-+      /* make sure we only read the data once all cfg registers are written: */
-+      acx_write_flush(priv);
-+      value = acx_read_reg32(priv, IO_ACX_SLV_MEM_DATA);
-+
-+      priv->info_type = (u16)value;
-+      priv->info_status = (value >> 16);
-+
-+      /* inform hw that we have read this info message */
-+      acx_write_reg32(priv, IO_ACX_SLV_MEM_DATA, priv->info_type | 0x00010000);
-+      acx_write_flush(priv);
-+      /* now bother hw to notice it: */
-+      acx_write_reg16(priv, IO_ACX_INT_TRIG, INT_TRIG_INFOACK);
-+      acx_write_flush(priv);
-+
-+      acxlog(L_CTL, "info_type 0x%04X, info_status 0x%04X\n",
-+                      priv->info_type, priv->info_status);
-+}
-+
-+
-+/***********************************************************************
-+** acx_write_cmd_type_or_status
-+*/
-+static void
-+acx_write_cmd_type_or_status(wlandevice_t *priv, u32 val)
-+{
-+      acx_write_reg32(priv, IO_ACX_SLV_END_CTL, 0x0);
-+      acx_write_reg32(priv, IO_ACX_SLV_MEM_CTL, 0x1); /* FIXME: why auto increment?? */
-+
-+      acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR,
-+              acx_read_reg32(priv, IO_ACX_CMD_MAILBOX_OFFS));
-+
-+      /* make sure we only write the data once all config registers are written */
-+      acx_write_flush(priv);
-+      acx_write_reg32(priv, IO_ACX_SLV_MEM_DATA, val);
-+      acx_write_flush(priv);
-+}
-+static inline void
-+acx_write_cmd_type(wlandevice_t *priv, u32 val)
-+{
-+      acx_write_cmd_type_or_status(priv, val);
-+}
-+static inline void
-+acx_write_cmd_status(wlandevice_t *priv, u32 val)
-+{
-+      acx_write_cmd_type_or_status(priv, val<<16);
-+}
-+
-+
-+/***********************************************************************
-+** acx_read_cmd_status
-+*/
-+static void
-+acx_read_cmd_status(wlandevice_t *priv)
-+{
-+      u32 value;
-+
-+      acx_write_reg32(priv, IO_ACX_SLV_END_CTL, 0x0);
-+      acx_write_reg32(priv, IO_ACX_SLV_MEM_CTL, 0x1); /* FIXME: why auto increment?? */
-+
-+      acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR,
-+              acx_read_reg32(priv, IO_ACX_CMD_MAILBOX_OFFS));
-+
-+      /* make sure we only read the data once all config registers are written */
-+      acx_write_flush(priv);
-+      value = acx_read_reg32(priv, IO_ACX_SLV_MEM_DATA);
-+
-+      priv->cmd_type = (u16)value;
-+      priv->cmd_status = (value >> 16);
-+
-+      acxlog(L_CTL, "cmd_type 0x%04X, cmd_status 0x%04X [%s]\n",
-+              priv->cmd_type, priv->cmd_status,
-+              acx_cmd_status_str(priv->cmd_status));
-+}
-+
-+/***********************************************************************
-+** acx_s_reset_dev
-+**
-+** Arguments:
-+**    netdevice that contains the wlandevice priv variable
-+** Returns:
-+**    NOT_OK on fail
-+**    OK on success
-+** Side effects:
-+**    device is hard reset
-+** Call context:
-+**    acx_probe_pci
-+** Comment:
-+**    This resets the acx100 device using low level hardware calls
-+**    as well as uploads and verifies the firmware to the card
-+*/
-+static int
-+acx_s_reset_dev(netdevice_t *dev)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+      const char* msg = "";
-+      unsigned long flags;
-+      int result = NOT_OK;
-+      u16 hardware_info;
-+      u16 ecpu_ctrl;
-+
-+      FN_ENTER;
-+
-+      /* we're doing a reset, so hardware is unavailable */
-+
-+      /* reset the device to make sure the eCPU is stopped
-+       * to upload the firmware correctly */
-+
-+      acx_lock(priv, flags);
-+
-+      acx_l_reset_mac(priv);
-+
-+      ecpu_ctrl = acx_read_reg16(priv, IO_ACX_ECPU_CTRL) & 1;
-+      if (!ecpu_ctrl) {
-+              msg = "eCPU is already running. ";
-+              goto fail_unlock;
-+      }
-+
-+#ifdef WE_DONT_NEED_THAT_DO_WE
-+      if (acx_read_reg16(priv, IO_ACX_SOR_CFG) & 2) {
-+              /* eCPU most likely means "embedded CPU" */
-+              msg = "eCPU did not start after boot from flash. ";
-+              goto fail_unlock;
-+      }
-+
-+      /* check sense on reset flags */
-+      if (acx_read_reg16(priv, IO_ACX_SOR_CFG) & 0x10) {
-+              printk("%s: eCPU did not start after boot (SOR), "
-+                      "is this fatal?\n", dev->name);
-+      }
-+#endif
-+      /* scan, if any, is stopped now, setting corresponding IRQ bit */
-+      priv->irq_status |= HOST_INT_SCAN_COMPLETE;
-+
-+      acx_unlock(priv, flags);
-+
-+      /* without this delay acx100 may fail to report hardware_info
-+      ** (see below). Most probably eCPU runs some init code */
-+      acx_s_msleep(10);
-+
-+      /* Need to know radio type before fw load */
-+      hardware_info = acx_read_reg16(priv, IO_ACX_EEPROM_INFORMATION);
-+      priv->form_factor = hardware_info & 0xff;
-+      priv->radio_type = hardware_info >> 8;
-+
-+      /* load the firmware */
-+      if (OK != acx_s_upload_fw(priv)){
-+              printk("Failed to load firmware\n");
-+              goto fail;
-+      }
-+
-+      acx_s_msleep(10);
-+
-+      /* now start eCPU by clearing bit */
-+      acxlog(L_DEBUG, "booted eCPU up and waiting for completion...\n");
-+      //acx_write_reg16(priv, IO_ACX_ECPU_CTRL, ecpu_ctrl & ~0x1);
-+      write_reg(priv, IO_ACX_ECPU_CTRL, ecpu_ctrl & ~0x1);
-+
-+      /* wait for eCPU bootup */
-+      if (OK != acx_s_verify_init(priv)) {
-+              msg = "timeout waiting for eCPU. ";
-+              goto fail;
-+      }
-+
-+      acxlog(L_DEBUG, "eCPU has woken up, card is ready to be configured\n");
-+
-+      if (IS_ACX111(priv)) {
-+              acxlog(L_DEBUG, "cleaning up cmd mailbox access area\n");
-+              acx_write_cmd_status(priv, 0);
-+              acx_read_cmd_status(priv);
-+              if (priv->cmd_status) {
-+                      msg = "error cleaning cmd mailbox area. ";
-+                      goto fail;
-+              }
-+      }
-+
-+      /* TODO what is this one doing ?? adapt for acx111 */
-+      if ((OK != acx_read_eeprom_area(priv)) && IS_ACX100(priv)) {
-+              /* does "CIS" mean "Card Information Structure"?
-+               * If so, then this would be a PCMCIA message...
-+               */
-+              msg = "CIS error. ";
-+              goto fail;
-+      }
-+
-+      result = OK;
-+      FN_EXIT1(result);
-+      return result;
-+
-+/* Finish error message. Indicate which function failed */
-+fail_unlock:
-+      acx_unlock(priv, flags);
-+fail:
-+      printk("acx: %sreset_dev() FAILED\n", msg);
-+      FN_EXIT1(result);
-+      return result;
-+}
-+
-+
-+/***********************************************************************
-+** acx_init_mboxes
-+*/
-+void
-+acx_init_mboxes(wlandevice_t *priv)
-+{
-+      u32 cmd_offs, info_offs;
-+
-+      FN_ENTER;
-+
-+      cmd_offs = acx_read_reg32(priv, IO_ACX_CMD_MAILBOX_OFFS);
-+      info_offs = acx_read_reg32(priv, IO_ACX_INFO_MAILBOX_OFFS);
-+      priv->cmd_area = (u8 *) cmd_offs + 0x4;
-+      priv->info_area = (u8 *) info_offs + 0x4;
-+      acxlog(L_DEBUG, "iobase2=%p\n"
-+              "cmd_mbox_offset=%X cmd_area=%p\n"
-+              "info_mbox_offset=%X info_area=%p\n",
-+              priv->iobase2,
-+              cmd_offs, priv->cmd_area,
-+              info_offs, priv->info_area);
-+
-+      FN_EXIT0;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_s_issue_cmd_timeo
-+* Excecutes a command in the command mailbox
-+*
-+* Arguments:
-+*   *pcmdparam = an pointer to the data. The data mustn't include
-+*                the 4 byte command header!
-+*
-+* 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(
-+      wlandevice_t *priv,
-+      unsigned int cmd,
-+      void *buffer,
-+      unsigned buflen,
-+      unsigned timeout)
-+{
-+#else
-+int
-+acxpci_s_issue_cmd_timeo_debug(
-+      wlandevice_t *priv,
-+      unsigned cmd,
-+      void *buffer,
-+      unsigned buflen,
-+      unsigned timeout,
-+      const char* cmdstr)
-+{
-+      unsigned long start = jiffies;
-+#endif
-+      const char *devname;
-+      unsigned counter;
-+      u16 irqtype;
-+      u16 cmd_status;
-+
-+      FN_ENTER;
-+
-+      devname = priv->netdev->name;
-+      if (!devname || !devname[0])
-+              devname = "acx";
-+
-+      acxlog(L_CTL, FUNC"(cmd:%s,buflen:%u,timeout:%ums,type:0x%04X)\n",
-+              cmdstr, buflen, timeout,
-+              buffer ? le16_to_cpu(((acx_ie_generic_t *)buffer)->type) : -1);
-+
-+      if (!(priv->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 pdr (len=%u):\n", buflen);
-+              acx_dump_bytes(buffer, buflen);
-+      }
-+
-+      /* wait for firmware to become idle for our command submission */
-+      counter = 199; /* in ms */
-+      do {
-+              acx_read_cmd_status(priv);
-+              /* Test for IDLE state */
-+              if (!priv->cmd_status)
-+                      break;
-+              if (counter % 10 == 0) {
-+                      /* we waited 10 iterations, no luck. Sleep 10 ms */
-+                      acx_s_msleep(10);
-+              }
-+      } while (--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, priv->cmd_status);
-+              goto bad;
-+      } else if (counter < 190) { /* if waited >10ms... */
-+              acxlog(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)
-+                      acx_mailbox_fill(priv, (unsigned int) priv->cmd_area, 0xAA, buflen);
-+#endif
-+              acx_mailbox_write(priv, 
-+                               (unsigned int) priv->cmd_area, 
-+                               buffer, (cmd == ACX1xx_CMD_INTERROGATE) ? 4 : buflen);
-+      }
-+
-+      /* now write the actual command type */
-+      priv->cmd_type = cmd;
-+      acx_write_cmd_type(priv, cmd);
-+      /* execute command */
-+      acx_write_reg16(priv, IO_ACX_INT_TRIG, INT_TRIG_CMD);
-+      acx_write_flush(priv);
-+
-+      /* 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 */
-+      timeout = (timeout-1) | 1;
-+      if (unlikely(timeout > 1199))
-+              timeout = 1199;
-+      /* clear CMD_COMPLETE bit. can be set only by IRQ handler: */
-+      priv->irq_status &= ~HOST_INT_CMD_COMPLETE;
-+
-+      /* we schedule away sometimes (timeout can be large) */
-+      counter = timeout;
-+      do {
-+              if (!priv->irqs_active) { /* IRQ disabled: poll */
-+                      irqtype = acx_read_reg16(priv, IO_ACX_IRQ_STATUS_NON_DES);
-+                      if (irqtype & HOST_INT_CMD_COMPLETE) {
-+                              acx_write_reg16(priv, IO_ACX_IRQ_ACK,
-+                                              HOST_INT_CMD_COMPLETE);
-+                              break;
-+                      }
-+              } else { /* Wait when IRQ will set the bit */
-+                      irqtype = priv->irq_status;
-+                      if (irqtype & HOST_INT_CMD_COMPLETE)
-+                              break;
-+              }
-+
-+              if (counter % 10 == 0) {
-+                      /* we waited 10 iterations, no luck. Sleep 10 ms */
-+                      acx_s_msleep(10);
-+              }
-+      } while (--counter);
-+
-+      /* save state for debugging */
-+      acx_read_cmd_status(priv);
-+      cmd_status = priv->cmd_status;
-+
-+      /* put the card in IDLE state */
-+      priv->cmd_status = 0;
-+      acx_write_cmd_status(priv, 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, (priv->irqs_active) ? "waiting" : "polling",
-+                      irqtype, priv->irq_status, timeout,
-+                      cmd_status, acx_cmd_status_str(cmd_status));
-+              goto bad;
-+      } else if (timeout - counter > 30) { /* if waited >30ms... */
-+              acxlog(L_CTL|L_DEBUG, FUNC"(): %s for CMD_COMPLETE %dms. "
-+                      "count:%d. Please report\n",
-+                      (priv->irqs_active) ? "waited" : "polled",
-+                      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),
-+                      timeout - counter, timeout);
-+              /* zero out result buffer */
-+              if (buffer && buflen)
-+                      memset(buffer, 0, buflen);
-+              goto bad;
-+      }
-+
-+      /* read in result parameters if needed */
-+      if (buffer && buflen && (cmd == ACX1xx_CMD_INTERROGATE)) {
-+              //memcpy(buffer, priv->cmd_area, buflen);
-+              acx_mailbox_read(priv, (unsigned int) priv->cmd_area, buffer, buflen);
-+              if (acx_debug & L_DEBUG) {
-+                      printk("output buffer (len=%u): ", buflen);
-+                      acx_dump_bytes(buffer, buflen);
-+              }
-+      }
-+/* ok: */
-+      acxlog(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;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_s_get_firmware_version
-+*----------------------------------------------------------------*/
-+static void
-+acx_s_get_firmware_version(wlandevice_t *priv)
-+{
-+      fw_ver_t fw;
-+      u8 hexarr[4] = { 0, 0, 0, 0 };
-+      int hexidx = 0, val = 0;
-+      const char *num;
-+      char c;
-+
-+      FN_ENTER;
-+
-+      acx_s_interrogate(priv, &fw, ACX1xx_IE_FWREV);
-+      memcpy(priv->firmware_version, fw.fw_id, FW_ID_SIZE);
-+      priv->firmware_version[FW_ID_SIZE] = '\0';
-+      acxlog(L_DEBUG, "fw_ver: fw_id='%s' hw_id=%08X\n",
-+                              priv->firmware_version, fw.hw_id);
-+
-+      if (strncmp(fw.fw_id, "Rev ", 4) != 0) {
-+              printk("acx: strange firmware version string "
-+                      "'%s', please report\n", priv->firmware_version);
-+              priv->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;
-+              }
-+
-+              priv->firmware_numver = (u32)(
-+                              (hexarr[0] << 24) + (hexarr[1] << 16)
-+                              + (hexarr[2] << 8) + hexarr[3]);
-+              acxlog(L_DEBUG, "firmware_numver 0x%08X\n", priv->firmware_numver);
-+      }
-+      if (IS_ACX111(priv)) {
-+              if (priv->firmware_numver == 0x00010011) {
-+                      /* This one does not survive floodpinging */
-+                      printk("acx: firmware '%s' is known to be buggy, "
-+                              "please upgrade\n", priv->firmware_version);
-+              }
-+              if (priv->firmware_numver == 0x02030131) {
-+                      /* With this one, all rx packets look mangled
-+                      ** Most probably we simply do not know how to use it
-+                      ** properly */
-+                      printk("acx: firmware '%s' does not work well "
-+                              "with this driver\n", priv->firmware_version);
-+              }
-+      }
-+
-+      priv->firmware_id = le32_to_cpu(fw.hw_id);
-+
-+      /* we're able to find out more detailed chip names now */
-+      switch (priv->firmware_id & 0xffff0000) {
-+              case 0x01010000:
-+              case 0x01020000:
-+                      priv->chip_name = name_tnetw1100a;
-+                      break;
-+              case 0x01030000:
-+                      priv->chip_name = name_tnetw1100b;
-+                      break;
-+              case 0x03000000:
-+              case 0x03010000:
-+                      priv->chip_name = name_tnetw1130;
-+                      break;
-+              default:
-+                      printk("acx: unknown chip ID 0x%08X, "
-+                              "please report\n", priv->firmware_id);
-+                      break;
-+      }
-+
-+      FN_EXIT0;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_display_hardware_details
-+*
-+* Arguments:
-+*     priv: ptr to wlandevice that contains all the details
-+*       displayed by this function
-+* Call context:
-+*     acx_probe_pci
-+* Comment:
-+*     This function will display strings to the system log according
-+* to device form_factor and radio type. It will needed to be
-+*----------------------------------------------------------------*/
-+static void
-+acx_display_hardware_details(wlandevice_t *priv)
-+{
-+      const char *radio_str, *form_str;
-+
-+      FN_ENTER;
-+
-+      switch (priv->radio_type) {
-+      case RADIO_MAXIM_0D:
-+              /* hmm, the DWL-650+ seems to have two variants,
-+               * according to a windows driver changelog comment:
-+               * RFMD and Maxim. */
-+              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;
-+      default:
-+              radio_str = "UNKNOWN, please report the radio type name!";
-+              break;
-+      }
-+
-+      switch (priv->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: form factor 0x%02X (%s), "
-+              "radio type 0x%02X (%s), EEPROM version 0x%02X, "
-+              "uploaded firmware '%s' (0x%08X)\n",
-+              priv->form_factor, form_str, priv->radio_type, radio_str,
-+              priv->eeprom_version, priv->firmware_version,
-+              priv->firmware_id);
-+
-+      FN_EXIT0;
-+}
-+
-+/***********************************************************************
-+*/
-+#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(wlandevice_t *priv)
-+{
-+      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 != acx_read_eeprom_offset(priv,
-+                                       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 */
-+
-+
-+/***********************************************************************
-+*/
-+static void
-+acx_s_device_chain_add(struct net_device *dev)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+
-+      down(&root_acx_dev_sem);
-+      priv->prev_nd = root_acx_dev.newest;
-+      root_acx_dev.newest = dev;
-+      priv->netdev = dev;
-+      up(&root_acx_dev_sem);
-+}
-+
-+static void
-+acx_s_device_chain_remove(struct net_device *dev)
-+{
-+      struct net_device *querydev;
-+      struct net_device *olderdev;
-+      struct net_device *newerdev;
-+
-+      down(&root_acx_dev_sem);
-+      querydev = root_acx_dev.newest;
-+      newerdev = NULL;
-+      while (querydev) {
-+              olderdev = ((wlandevice_t*)netdev_priv(querydev))->prev_nd;
-+              if (0 == strcmp(querydev->name, dev->name)) {
-+                      if (!newerdev) {
-+                              /* if we were at the beginning of the
-+                               * list, then it's the list head that
-+                               * we need to update to point at the
-+                               * next older device */
-+                              root_acx_dev.newest = olderdev;
-+                      } else {
-+                              /* it's the device that is newer than us
-+                               * that we need to update to point at
-+                               * the device older than us */
-+                              ((wlandevice_t*)netdev_priv(newerdev))->
-+                                      prev_nd = olderdev;
-+                      }
-+                      break;
-+              }
-+              /* "newerdev" is actually the device of the old iteration,
-+               * but since the list starts (root_acx_dev.newest)
-+               * with the newest devices,
-+               * it's newer than the ones following.
-+               * Oh the joys of iterating from newest to oldest :-\ */
-+              newerdev = querydev;
-+
-+              /* keep checking old devices for matches until we hit the end
-+               * of the list */
-+              querydev = olderdev;
-+      }
-+      up(&root_acx_dev_sem);
-+}
-+
-+
-+/***********************************************************************
-+** acx_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
-+acx_free_coherent(struct pci_dev *hwdev, size_t size,
-+                      void *vaddr, dma_addr_t dma_handle)
-+{
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 53)
-+      dma_free_coherent(hwdev == NULL ? NULL : &hwdev->dev,
-+                      size, vaddr, dma_handle);
-+#else
-+      pci_free_consistent(hwdev, size, vaddr, dma_handle);
-+#endif
-+}
-+
-+void
-+acx_free_desc_queues(wlandevice_t *priv)
-+{
-+#define ACX_FREE_QUEUE(size, ptr, phyaddr) \
-+      if (ptr) { \
-+              acx_free_coherent(0, size, ptr, phyaddr); \
-+              ptr = NULL; \
-+              size = 0; \
-+      }
-+
-+      FN_ENTER;
-+
-+      ACX_FREE_QUEUE(priv->txhostdesc_area_size, priv->txhostdesc_start, priv->txhostdesc_startphy);
-+      ACX_FREE_QUEUE(priv->txbuf_area_size, priv->txbuf_start, priv->txbuf_startphy);
-+
-+      priv->txdesc_start = NULL;
-+
-+      ACX_FREE_QUEUE(priv->rxhostdesc_area_size, priv->rxhostdesc_start, priv->rxhostdesc_startphy);
-+      ACX_FREE_QUEUE(priv->rxbuf_area_size, priv->rxbuf_start, priv->rxbuf_startphy);
-+
-+      priv->rxdesc_start = NULL;
-+
-+      FN_EXIT0;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_s_delete_dma_regions
-+*----------------------------------------------------------------*/
-+static void
-+acx_s_delete_dma_regions(wlandevice_t *priv)
-+{
-+      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? */
-+      acx_write_reg16(priv, IO_ACX_ENABLE, 0);
-+
-+      acx_s_msleep(100);
-+
-+      acx_lock(priv, flags);
-+      acx_free_desc_queues(priv);
-+      acx_unlock(priv, flags);
-+
-+      FN_EXIT0;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_e_probe_pci
-+*
-+* 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
-+*
-+* Arguments:
-+*     pdev            ptr to pci device structure containing info about
-+*                     pci configuration.
-+*     id              ptr to the device id entry that matched this device.
-+*
-+* Returns:
-+*     zero            - success
-+*     negative        - failed
-+*
-+* Call context:
-+*     process thread
-+----------------------------------------------------------------*/
-+static const u16
-+IO_ACX100[] =
-+{
-+      0x0000, /* IO_ACX_SOFT_RESET */
-+
-+      0x0004, /* IO_ACX_HW_SLAVE_REG_ADDR */
-+      0x0008, /* IO_ACX_HW_SLAVE_REG_DATA */
-+      0x000c, /* IO_ACX_HW_SLAVE_REG_REG_CTRL */
-+
-+      0x0014, /* IO_ACX_SLV_MEM_ADDR */
-+      0x0018, /* IO_ACX_SLV_MEM_DATA */
-+      0x001c, /* IO_ACX_SLV_MEM_CTL */
-+      0x0020, /* IO_ACX_SLV_END_CTL */
-+      0x0024, /* IO_ACX_CHIPID */
-+
-+      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 */
-+
-+      0x0294, /* IO_ACX_GPIO_IN */
-+      0x0298, /* IO_ACX_GPIO_OUT */
-+      0x029c, /* IO_ACX_GPIO_PD */
-+      0x02a0, /* IO_ACX_GPIO_CFG */
-+
-+      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 */
-+      
-+      0x0804, /* IO_ACX_HI_CTL */
-+      0x0808, /* IO_ACX_LPWR_MGN */
-+
-+      0x010c, /* IO_ACX_PCI_ARB_CFG */ 
-+      
-+};
-+
-+static void
-+acx_netdev_init(struct net_device *dev) {}
-+
-+//FIXME: do the same for USB
-+static int
-+acx_change_mtu(struct net_device *dev, int mtu)
-+{
-+      enum {
-+              MIN_MTU = 256,
-+              MAX_MTU = WLAN_DATA_MAXLEN - (ETH_HLEN)
-+      };
-+
-+      if (mtu < MIN_MTU || mtu > MAX_MTU)
-+              return -EINVAL;
-+
-+      dev->mtu = mtu;
-+      return 0;
-+}
-+
-+
-+static int acx_enable(struct platform_device *pdev){
-+        unsigned long flags;
-+
-+        /* We need to disabe the interrupt
-+         * around reset.
-+         */
-+        local_irq_save(flags);
-+
-+        /* Now lets turn on and
-+         * reset the device.
-+         */
-+        pca9535_gpio_write(GPIO6, LOW);
-+        pca9535_gpio_write(GPIO12, LOW);
-+
-+        /* TODO: someother configuration needs
-+         * to be done here.
-+         */
-+
-+        // Now we can enable interrupt.
-+        local_irq_restore(flags);
-+
-+
-+        return 0;
-+}
-+
-+static inline void test(wlandevice_t *priv) {
-+      printk("===============================\n");
-+      printk("Reset   : %04x\n",acx_read_reg16(priv, IO_ACX_SOFT_RESET));
-+      printk("eCPU CTL: %04x\n",acx_read_reg16(priv, IO_ACX_ECPU_CTRL));
-+      printk("SOR CFG : %08x\n",acx_read_reg32(priv, IO_ACX_SOR_CFG));
-+      printk("EE START: %08x\n",acx_read_reg32(priv, IO_ACX_EE_START));
-+      printk("HI CTRL : %08x\n",acx_read_reg32(priv, IO_ACX_HI_CTRL));
-+//    printk("Info    : %08x\n",acx_read_reg32(priv, IO_ACX_EEPROM_INFORMATION));
-+      printk("GPIO OE : %04x\n",acx_read_reg16(priv, IO_ACX_GPIO_OE));
-+      printk("GPIO OUT: %04x\n",acx_read_reg16(priv, IO_ACX_GPIO_OUT));
-+      printk("GPIO IN : %04x\n",acx_read_reg16(priv, IO_ACX_GPIO_IN));
-+      printk("GPIO PD : %04x\n",acx_read_reg16(priv, IO_ACX_GPIO_PD));
-+      printk("GPIO CFG: %04x\n",acx_read_reg16(priv, IO_ACX_GPIO_CFG));
-+      printk("Chip ID : %08x\n",acx_read_reg32(priv, IO_ACX_CHIPID));
-+
-+/*
-+      printk("HW CTRL : %08x\n",acx_read_reg32(priv,IO_ACX_HW_SLAVE_REG_CTRL));
-+      printk("HW ADDR : %08x\n",acx_read_reg32(priv,IO_ACX_HW_SLAVE_REG_ADDR));
-+      printk("HW DATA : %08x\n",acx_read_reg32(priv,IO_ACX_HW_SLAVE_REG_DATA));
-+*/
-+
-+      msleep(50);
-+
-+      printk("==============================\n");     
-+}
-+
-+static int __init acx_probe(struct net_device *ndev, void __iomem *addr, struct resource *res){
-+      wlandevice_t    *priv             = netdev_priv(ndev);
-+      int             ret               = 0;
-+
-+      ether_setup(ndev);
-+
-+      /* now that device init was successful, fill remaining fields... */
-+        ndev->open            = &acx_e_open;
-+        ndev->stop            = &acx_e_close;
-+      ndev->hard_start_xmit   = &acx_i_start_xmit;
-+        ndev->get_stats       = &acx_e_get_stats;
-+        ndev->get_wireless_stats = &acx_e_get_wireless_stats;
-+#if WIRELESS_EXT >= 13
-+        ndev->wireless_handlers = (struct iw_handler_def *)&acx_ioctl_handler_def;
-+#else
-+        ndev->do_ioctl = &acx_e_ioctl_old;
-+#endif
-+        ndev->set_multicast_list = &acx_i_set_multicast_list;
-+        ndev->tx_timeout       = &acx_i_tx_timeout;
-+        ndev->change_mtu       = &acx_change_mtu;
-+        ndev->watchdog_timeo   = 4 * HZ;
-+
-+      spin_lock_init(&priv->lock);    /* initial state: unlocked */
-+        /* We do not start with downed sem: we want PARANOID_LOCKING to work */
-+        sema_init(&priv->sem, 1);       /* initial state: 1 (upped) */
-+
-+      priv->iobase              = (unsigned char *) addr;
-+        priv->iobase2             = 0;
-+        priv->membase             = res->start;
-+        priv->chip_type           = CHIPTYPE_ACX100;
-+        priv->chip_name           = name_acx100;
-+        priv->io                  = IO_ACX100;
-+        priv->mgmt_timer.function = (void (*)(unsigned long))0x0000dead;
-+        spin_lock_init(&priv->lock);
-+      
-+      test(priv);
-+
-+#ifdef NONESSENTIAL_FEATURES
-+        acx_show_card_eeprom_id(priv);
-+#endif /* NONESSENTIAL_FEATURES */
-+
-+        /* 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, "after setup");
-+
-+      /* register new dev in linked list */
-+        acx_s_device_chain_add(ndev);
-+
-+      if((ret = acx_s_reset_dev(ndev)) != OK){
-+                /* Failed to reset device */
-+                ret = -EIO;
-+                goto reset_fail;
-+        }
-+
-+        /* ok, basic setup is finished, now start initialising the card */
-+#if 0
-+        hardware_info           = acx_read_reg16(priv, IO_ACX_EEPROM_INFORMATION);
-+        priv->form_factor = (u8)(hardware_info & 0xff);
-+        priv->radio_type  = (u8)(hardware_info >> 8 & 0xff);
-+#endif
-+
-+        if (OK != acx_read_eeprom_offset(priv, 0x05, &priv->eeprom_version)) {
-+                ret = -EIO;
-+                goto fail_read_eeprom_version;
-+        }
-+
-+        if (OK != acx_s_init_mac(ndev)) {
-+                acxlog(L_DEBUG | L_INIT,
-+                       "Danger Will Robinson, MAC did not come back\n");
-+                ret = -EIO;
-+                goto fail_init_mac;
-+        }
-+
-+      if (OK != acx_s_set_defaults(priv)) {
-+                printk("acx: set_defaults() FAILED\n");
-+                goto fail_set_defaults;
-+        }
-+
-+        /* needs to be after acx_init_mac() due to necessary init stuff */
-+        acx_s_get_firmware_version(priv);
-+
-+      acx_display_hardware_details(priv);
-+      
-+      /* ...and 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 */
-+        ret = register_netdev(ndev);
-+        if (OK != ret) {
-+                      printk(KERN_ERR
-+                       "%s:  Register net device of %s FAILED: %d\n",
-+                       __func__, ndev->name, ret);
-+                ret = -EIO;
-+                goto fail_register_netdev;
-+        }
-+      acx_carrier_off(ndev, "on probe");
-+
-+#ifdef CONFIG_PROC_FS
-+        if (OK != acx_proc_register_entries(ndev)) {
-+                ret = -EIO;
-+                goto fail_proc_register_entries;
-+        }
-+#endif
-+
-+#if CMD_DISCOVERY
-+        great_inquisitor(priv);
-+#endif
-+
-+
-+      return 0;
-+
-+#ifdef CONFIG_PROC_FS
-+fail_proc_register_entries:
-+#endif
-+
-+        if (priv->dev_state_mask & ACX_STATE_IFACE_UP)
-+                acx_s_down(ndev);
-+        unregister_netdev(ndev);
-+
-+fail_register_netdev:
-+        acx_s_delete_dma_regions(priv);
-+fail_set_defaults:
-+fail_init_mac:
-+fail_read_eeprom_version:
-+reset_fail:
-+      acx_s_device_chain_remove(ndev);
-+
-+      return ret;
-+}
-+
-+static void dumpRegs(char *msg, unsigned char *base) {
-+      u32 val  = 0;
-+      u16 addr = 0;
-+
-+      printk("============= [ %s ] ===============\n",msg);
-+
-+      for(addr = 0; addr <= 0x0be0; addr+=4){
-+              if(addr >= 0x0710 && addr <= 0x0740){
-+                      val = 0;
-+                      printk("Reg[%04x] : %08x\n",addr, val);
-+                      msleep(50);     
-+                      continue;
-+              }
-+
-+              val = readw((u8 *) base + addr)  +  (readw((u8 *) base + addr + 2) << 16);
-+
-+              printk("Reg[%04x] : %08x\n",addr, val);
-+              msleep(50);
-+      }
-+
-+      printk("=====================================\n");
-+}
-+
-+
-+static int __init acx_drv_probe(struct device *dev){
-+      struct platform_device *pdev   = to_platform_device(dev);
-+        struct net_device       *ndev  = NULL;
-+        struct resource         *res   = NULL;
-+        unsigned int __iomem    *addr  = NULL;
-+      wlandevice_t            *priv  = NULL;
-+        int ret;
-+
-+        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+        if (!res) {
-+                printk(KERN_ERR "Device not found\n");
-+                ret = -ENODEV;
-+                goto out;
-+        }
-+
-+
-+        if (!request_mem_region(res->start, SZ_32M, CARDNAME)) {
-+                printk(KERN_ERR "Device busy\n");
-+                ret = -EBUSY;
-+                goto out;
-+        }
-+
-+        // Create new ethernet device
-+        ndev = alloc_netdev(sizeof(wlandevice_t), "wlan%d", acx_netdev_init);
-+        if (!ndev) {
-+                printk("%s: could not allocate device.\n", CARDNAME);
-+                ret = -ENOMEM;
-+                goto out_release_io;
-+        }
-+        SET_MODULE_OWNER(ndev);
-+        SET_NETDEV_DEV(ndev, dev);
-+      
-+      // Get driver private data
-+      priv      = netdev_priv(ndev);
-+
-+      // Cleanup the private area
-+      memset((void *) priv, 0, sizeof(wlandevice_t));
-+
-+        ndev->dma = (unsigned char)-1;
-+        ndev->irq = platform_get_irq(pdev, 0);
-+      priv->dev = dev;
-+
-+        // Enable device
-+      acx_enable(pdev);
-+
-+        /* Create IOMEM port so we
-+         * can use to to read and write
-+         * from card registers.
-+         */
-+        if(!(addr = ioremap(res->start, SZ_32M))){
-+                printk(KERN_ERR "Failed to map ioport\n");
-+                ret = -ENOMEM;
-+                goto  free_device;
-+        }
-+
-+        dev_set_drvdata(dev, ndev);
-+
-+      //dumpRegs("After",addr);
-+
-+
-+        if((ret = acx_probe(ndev, addr,res))){
-+                /* Something wrong we couldn't
-+                 * talke to the device.
-+                 */
-+                printk(KERN_ERR "Failed to probe ACX\n");
-+                goto out_iounmap;
-+        }
-+
-+       printk("acx "WLAN_RELEASE": net device %s, driver compiled "
-+                "against wireless extensions %d and Linux %s\n",
-+                ndev->name, WIRELESS_EXT, UTS_RELEASE);
-+      
-+      return 0;
-+
-+out_iounmap:
-+        dev_set_drvdata(dev, NULL);
-+        iounmap(addr);
-+free_device:
-+        free_netdev(ndev);
-+out_release_io:
-+        release_mem_region(res->start, SZ_32M);
-+out:
-+        return ret;
-+}
-+
-+static int acx_remove(struct device *dev) 
-+{
-+      struct platform_device *pdev  = to_platform_device(dev);
-+        struct net_device       *ndev = (dev? dev_get_drvdata(dev) : NULL);
-+        wlandevice_t            *priv = (ndev? (wlandevice_t *) netdev_priv(ndev) : NULL);
-+        struct resource         *res  = NULL;
-+
-+        if(!ndev){
-+                printk(KERN_ERR "Invalid network device structure\n");
-+                return 0;
-+        }
-+
-+        dev_set_drvdata(dev, NULL);
-+        unregister_netdev(ndev);
-+
-+#if 0
-+        free_irq(ndev->irq, ndev);
-+#endif
-+
-+        iounmap(priv->iobase);
-+        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+        release_mem_region(res->start, SZ_32M);
-+
-+        free_netdev(ndev);
-+
-+        return 0;
-+}
-+
-+/***********************************************************************
-+*/
-+#ifdef CONFIG_PM
-+static int if_was_up = 0; /* FIXME: HACK, do it correctly sometime instead */
-+static int
-+acx_suspend(struct device *dev, pm_message_t state, u32 level)
-+{
-+#if 0
-+      struct net_device *ndev = pci_get_drvdata(pdev);
-+      wlandevice_t *priv = netdev_priv(dev);
-+
-+      FN_ENTER;
-+
-+      acx_sem_lock(priv);
-+
-+      printk("acx: experimental suspend handler called for %p\n", priv);
-+      if (netif_device_present(ndev)) {
-+              if_was_up = 1;
-+              acx_s_down(ndev);
-+      }
-+      else
-+              if_was_up = 0;
-+
-+      netif_device_detach(ndev);      /* This one cannot sleep */
-+      acx_s_delete_dma_regions(priv);
-+
-+      acx_sem_unlock(priv);
-+
-+      FN_EXIT0;
-+#endif
-+      return OK;
-+}
-+
-+static int
-+acx_resume(struct device *dev, u32 level)
-+{
-+#if 0
-+      struct platform_device *pdev  = to_platform_device(dev);
-+      struct net_device       *ndev;
-+      wlandevice_t            *priv;
-+
-+      printk(KERN_WARNING "rsm: resume\n");
-+      ndev = dev_get_drvdata(dev);
-+      printk(KERN_WARNING "rsm: got dev\n");
-+
-+      if (!netif_running(ndev))
-+              return 0;
-+
-+      priv = netdev_priv(ndev);
-+
-+      acx_sem_lock(priv);
-+
-+      printk(KERN_WARNING "rsm: got priv\n");
-+      FN_ENTER;
-+      printk("acx: experimental resume handler called for %p!\n", priv);
-+      // TODO
-+      acxlog(L_DEBUG, "rsm: power state set\n");
-+
-+      acxlog(L_DEBUG, "rsm: PCI state restored\n");
-+      acx_s_reset_dev(ndev);
-+      acxlog(L_DEBUG, "rsm: device reset done\n");
-+
-+      if (OK != acx_s_init_mac(ndev)) {
-+              printk("rsm: init_mac FAILED\n");
-+              goto fail;
-+      }
-+      acxlog(L_DEBUG, "rsm: init MAC done\n");
-+
-+      if (1 == if_was_up)
-+              acx_s_up(ndev);
-+      acxlog(L_DEBUG, "rsm: acx up\n");
-+
-+      /* now even reload all card parameters as they were before suspend,
-+       * and possibly be back in the network again already :-)
-+       * FIXME: should this be done in that scheduled task instead?? */
-+      if (ACX_STATE_IFACE_UP & priv->dev_state_mask)
-+              acx_s_update_card_settings(priv, 0, 1);
-+      acxlog(L_DEBUG, "rsm: settings updated\n");
-+      netif_device_attach(ndev);
-+      acxlog(L_DEBUG, "rsm: device attached\n");
-+fail: /* we need to return OK here anyway, right? */
-+      acx_sem_unlock(priv);
-+      FN_EXIT0;
-+#endif
-+      return OK;
-+}
-+#endif /* CONFIG_PM */
-+
-+
-+/*----------------------------------------------------------------
-+* acx_s_up
-+*
-+* Side effects:
-+*     - Enables on-card interrupt requests
-+*     - calls acx_start
-+* Call context:
-+*     - process thread
-+* Comment:
-+*     This function is called by acx_open (when ifconfig sets the
-+*     device as up).
-+*----------------------------------------------------------------*/
-+static void
-+acx_s_up(netdevice_t *dev)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+      unsigned long flags;
-+
-+      FN_ENTER;
-+
-+      acx_lock(priv, flags);
-+      acx_l_enable_irq(priv);
-+      acx_unlock(priv, 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(&priv->mgmt_timer);
-+      priv->mgmt_timer.function = acx_i_timer;
-+      priv->mgmt_timer.data = (unsigned long)priv;
-+
-+      /* Need to set ACX_STATE_IFACE_UP first, or else
-+      ** timer won't be started by acx_set_status() */
-+      SET_BIT(priv->dev_state_mask, ACX_STATE_IFACE_UP);
-+      switch (priv->mode) {
-+      case ACX_MODE_0_ADHOC:
-+      case ACX_MODE_2_STA:
-+              /* actual scan cmd will happen in start() */
-+              acx_set_status(priv, ACX_STATUS_1_SCANNING); break;
-+      case ACX_MODE_3_AP:
-+      case ACX_MODE_MONITOR:
-+              acx_set_status(priv, ACX_STATUS_4_ASSOCIATED); break;
-+      }
-+
-+      acx_s_start(priv);
-+
-+      FN_EXIT0;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_s_down
-+*
-+* Side effects:
-+*     - disables on-card interrupt request
-+* Call context:
-+*     process thread
-+* Comment:
-+*     this disables the netdevice
-+*----------------------------------------------------------------*/
-+static void
-+acx_s_down(netdevice_t *dev)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+      unsigned long flags;
-+
-+      FN_ENTER;
-+
-+      /* Disable IRQs first, so that IRQs cannot race with us */
-+      acx_lock(priv, flags);
-+      acx_l_disable_irq(priv);
-+      acx_unlock(priv, 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(priv);
-+      FLUSH_SCHEDULED_WORK();
-+      acx_sem_lock(priv);
-+
-+      /* 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(priv, flags);
-+      acx_stop_queue(dev, "during close");
-+      acx_set_status(priv, ACX_STATUS_0_STOPPED);
-+      acx_unlock(priv, 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(&priv->mgmt_timer);
-+
-+      FN_EXIT0;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_e_open
-+*
-+* WLAN device open method.  Called from p80211netdev when kernel
-+* device open (start) method is called in response to the
-+* SIOCSIFFLAGS ioctl changing the flags bit IFF_UP
-+* from clear to set.
-+*
-+* Returns:
-+*     0       success
-+*     >0      f/w reported error
-+*     <0      driver reported error
-+*
-+* Call context:
-+*     process thread
-+----------------------------------------------------------------*/
-+static int
-+acx_e_open(netdevice_t *dev)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+      int result = OK;
-+
-+      FN_ENTER;
-+
-+      acxlog(L_INIT, "module count++\n");
-+      WLAN_MOD_INC_USE_COUNT;
-+
-+      acx_sem_lock(priv);
-+
-+      acx_init_task_scheduler(priv);
-+
-+      /* request shared IRQ handler */
-+      if (request_irq(dev->irq, acx_i_interrupt, SA_SHIRQ, dev->name, dev)) {
-+              printk("%s: request_irq FAILED\n", dev->name);
-+              result = -EAGAIN;
-+              goto done;
-+      }
-+      acxlog(L_DEBUG|L_IRQ, "request_irq %d successful\n", dev->irq);
-+
-+      /* ifup device */
-+      acx_s_up(dev);
-+
-+      /* 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(priv);
-+
-+      FN_EXIT1(result);
-+      return result;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_e_close
-+*
-+* WLAN device close method.  Called from network core when kernel
-+* device close method is called in response to the
-+* SIOCSIIFFLAGS ioctl changing the flags bit IFF_UP
-+* from set to clear.
-+* (i.e. called for "ifconfig DEV down")
-+*
-+* Returns:
-+*     0       success
-+*     >0      f/w reported error
-+*     <0      driver reported error
-+*
-+* Call context:
-+*     process thread
-+----------------------------------------------------------------*/
-+static int
-+acx_e_close(netdevice_t *dev)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+
-+      FN_ENTER;
-+
-+      acx_sem_lock(priv);
-+
-+      /* ifdown device */
-+      CLEAR_BIT(priv->dev_state_mask, ACX_STATE_IFACE_UP);
-+      if (netif_device_present(dev)) {
-+              acx_s_down(dev);
-+      }
-+
-+      /* disable all IRQs, release shared IRQ handler */
-+      acx_write_reg16(priv, IO_ACX_IRQ_MASK, 0xffff);
-+      acx_write_reg16(priv, IO_ACX_FEMR, 0x0);
-+      free_irq(dev->irq, dev);
-+
-+      /* 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.
-+       */
-+      acxlog(L_INIT, "module count--\n");
-+      WLAN_MOD_DEC_USE_COUNT;
-+
-+      acx_sem_unlock(priv);
-+
-+      acxlog(L_INIT, "closed device\n");
-+      FN_EXIT0;
-+      return OK;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_i_tx_timeout
-+*
-+* Called from network core. Must not sleep!
-+*----------------------------------------------------------------*/
-+static void
-+acx_i_tx_timeout(netdevice_t *dev)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+      unsigned long flags;
-+      unsigned int tx_num_cleaned;
-+
-+      FN_ENTER;
-+
-+      acx_lock(priv, flags);
-+
-+      /* clean processed tx descs, they may have been completely full */
-+      tx_num_cleaned = acx_l_clean_tx_desc(priv);
-+
-+      /* 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 ((priv->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", dev->name);
-+              acx_l_clean_tx_desc_emergency(priv);
-+      }
-+
-+      if (acx_queue_stopped(dev) && (ACX_STATUS_4_ASSOCIATED == priv->status))
-+              acx_wake_queue(dev, "after tx timeout");
-+
-+      /* stall may have happened due to radio drift, so recalib radio */
-+      acx_schedule_after_interrupt_task(priv, ACX_AFTER_IRQ_CMD_RADIO_RECALIB);
-+
-+      /* do unimportant work last */
-+      printk("%s: tx timeout!\n", dev->name);
-+      priv->stats.tx_errors++;
-+
-+      acx_unlock(priv, flags);
-+
-+      FN_EXIT0;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_e_get_stats
-+*----------------------------------------------------------------*/
-+static struct net_device_stats*
-+acx_e_get_stats(netdevice_t *dev)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+      return &priv->stats;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_e_get_wireless_stats
-+*----------------------------------------------------------------*/
-+static struct iw_statistics*
-+acx_e_get_wireless_stats(netdevice_t *dev)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+      return &priv->wstats;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_i_set_multicast_list
-+* FIXME: most likely needs refinement
-+*----------------------------------------------------------------*/
-+static void
-+acx_i_set_multicast_list(netdevice_t *dev)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+      unsigned long flags;
-+
-+      FN_ENTER;
-+
-+      acx_lock(priv, flags);
-+
-+      /* firmwares don't have allmulti capability,
-+       * so just use promiscuous mode instead in this case. */
-+      if (dev->flags & (IFF_PROMISC|IFF_ALLMULTI)) {
-+              SET_BIT(priv->rx_config_1, RX_CFG1_RCV_PROMISCUOUS);
-+              CLEAR_BIT(priv->rx_config_1, RX_CFG1_FILTER_ALL_MULTI);
-+              SET_BIT(priv->set_mask, SET_RXCONFIG);
-+              /* let kernel know in case *we* needed to set promiscuous */
-+              dev->flags |= (IFF_PROMISC|IFF_ALLMULTI);
-+      } else {
-+              CLEAR_BIT(priv->rx_config_1, RX_CFG1_RCV_PROMISCUOUS);
-+              SET_BIT(priv->rx_config_1, RX_CFG1_FILTER_ALL_MULTI);
-+              SET_BIT(priv->set_mask, SET_RXCONFIG);
-+              dev->flags &= ~(IFF_PROMISC|IFF_ALLMULTI);
-+      }
-+
-+      /* cannot update card settings directly here, atomic context */
-+      acx_schedule_after_interrupt_task(priv, ACX_AFTER_IRQ_UPDATE_CARD_CFG);
-+
-+      acx_unlock(priv, flags);
-+
-+      FN_EXIT0;
-+}
-+
-+static void
-+acx_l_update_link_quality_led(wlandevice_t *priv)
-+{
-+      int qual;
-+
-+      qual = acx_signal_determine_quality(priv->wstats.qual.level, priv->wstats.qual.noise);
-+      if (qual > priv->brange_max_quality)
-+              qual = priv->brange_max_quality;
-+
-+      if (time_after(jiffies, priv->brange_time_last_state_change +
-+                              (HZ/2 - HZ/2 * (unsigned long) qual/priv->brange_max_quality ) )) {
-+              acx_l_power_led(priv, (priv->brange_last_state == 0));
-+              priv->brange_last_state ^= 1; /* toggle */
-+              priv->brange_time_last_state_change = jiffies;
-+      }
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_l_enable_irq
-+*----------------------------------------------------------------*/
-+static void
-+acx_l_enable_irq(wlandevice_t *priv)
-+{
-+      FN_ENTER;
-+      acx_write_reg16(priv, IO_ACX_IRQ_MASK, priv->irq_mask);
-+      acx_write_reg16(priv, IO_ACX_FEMR, 0x8000);
-+      priv->irqs_active = 1;
-+      FN_EXIT0;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_l_disable_irq
-+*----------------------------------------------------------------*/
-+static void
-+acx_l_disable_irq(wlandevice_t *priv)
-+{
-+      FN_ENTER;
-+      acx_write_reg16(priv, IO_ACX_IRQ_MASK, priv->irq_mask_off);
-+      acx_write_reg16(priv, IO_ACX_FEMR, 0x0);
-+      priv->irqs_active = 0;
-+      FN_EXIT0;
-+}
-+
-+/* 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
-+
-+static void
-+acx_l_handle_info_irq(wlandevice_t *priv)
-+{
-+#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
-+      acx_read_info_status(priv);
-+      acxlog(L_IRQ, "got Info IRQ: status 0x%04X type 0x%04X: %s\n",
-+              priv->info_status, priv->info_type,
-+              info_type_msg[(priv->info_type >= VEC_SIZE(info_type_msg)) ?
-+                              0 : priv->info_type]
-+      );
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_i_interrupt
-+*
-+* IRQ handler (atomic context, must not sleep, blah, blah)
-+*----------------------------------------------------------------*/
-+static void
-+acx_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) {
-+              acxlog(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");
-+      }
-+              /* 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 irqreturn_t
-+acx_i_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+      wlandevice_t *priv;
-+      unsigned long flags;
-+      unsigned int irqcount = MAX_IRQLOOPS_PER_JIFFY;
-+      u16 irqtype, unmasked;
-+
-+      priv = (wlandevice_t *) (((netdevice_t *) dev_id)->priv);
-+
-+      /* LOCKING: can just spin_lock() since IRQs are disabled anyway.
-+       * I am paranoid */
-+      acx_lock(priv, flags);
-+
-+      unmasked = acx_read_reg16(priv, IO_ACX_IRQ_STATUS_CLEAR);
-+      if (unlikely(0xffff == unmasked)) {
-+              /* 0xffff value hints at missing hardware,
-+               * so don't do anything.
-+               * FIXME: that's not very clean - maybe we are able to
-+               * establish a flag which definitely tells us that some
-+               * hardware is absent and which we could check here?
-+               * Hmm, but other drivers do the very same thing... */
-+              acxlog(L_IRQ, "IRQ type:FFFF - device removed? IRQ_NONE\n");
-+              goto none;
-+      }
-+
-+      /* We will check only "interesting" IRQ types */
-+      irqtype = unmasked & ~priv->irq_mask;
-+      if (!irqtype) {
-+              /* We are on a shared IRQ line and it wasn't our IRQ */
-+              acxlog(L_IRQ, "IRQ type:%04X, mask:%04X - all are masked, IRQ_NONE\n",
-+                      unmasked, priv->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 != priv->irq_last_jiffies) {
-+      priv->irq_loops_this_jiffy = 0;
-+      priv->irq_last_jiffies = jiffies;
-+}
-+
-+/* safety condition; we'll normally abort loop below
-+ * in case no IRQ type occurred */
-+while (--irqcount) {
-+#endif
-+      /* ACK all IRQs asap */
-+      acx_write_reg16(priv, IO_ACX_IRQ_ACK, 0xffff);
-+
-+      acxlog(L_IRQ, "IRQ type:%04X, mask:%04X, type & ~mask:%04X\n",
-+                              unmasked, priv->irq_mask, irqtype);
-+
-+      /* Handle most important IRQ types first */
-+      if (irqtype & HOST_INT_RX_COMPLETE) {
-+              acxlog(L_IRQ, "got Rx_Complete IRQ\n");
-+              acx_l_process_rx_desc(priv);
-+      }
-+      if (irqtype & HOST_INT_TX_COMPLETE) {
-+              acxlog(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
-+               * acx_l_clean_tx_desc() at a time when we won't wakeup
-+               * the net queue in there for some reason...) */
-+              if (priv->tx_free <= TX_START_CLEAN) {
-+#if TX_CLEANUP_IN_SOFTIRQ
-+                      acx_schedule_after_interrupt_task(priv, ACX_AFTER_IRQ_TX_CLEANUP);
-+#else
-+                      acx_l_clean_tx_desc(priv);
-+#endif
-+              }
-+      }
-+
-+      /* Less frequent ones */
-+      if (irqtype & (0
-+              | HOST_INT_CMD_COMPLETE
-+              | HOST_INT_INFO
-+              | HOST_INT_SCAN_COMPLETE
-+      )) {
-+              if (irqtype & HOST_INT_CMD_COMPLETE) {
-+                      acxlog(L_IRQ, "got Command_Complete IRQ\n");
-+                      /* save the state for the running issue_cmd() */
-+                      SET_BIT(priv->irq_status, HOST_INT_CMD_COMPLETE);
-+              }
-+              if (irqtype & HOST_INT_INFO) {
-+                      acx_l_handle_info_irq(priv);
-+              }
-+              if (irqtype & HOST_INT_SCAN_COMPLETE) {
-+                      acxlog(L_IRQ, "got Scan_Complete IRQ\n");
-+                      /* need to do that in process context */
-+                      acx_schedule_after_interrupt_task(priv, ACX_AFTER_IRQ_COMPLETE_SCAN);
-+                      /* remember that fw is not scanning anymore */
-+                      SET_BIT(priv->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
-+      )) {
-+              acx_log_unusual_irq(irqtype);
-+      }
-+
-+#if IRQ_ITERATE
-+      unmasked = acx_read_reg16(priv, IO_ACX_IRQ_STATUS_CLEAR);
-+      irqtype = unmasked & ~priv->irq_mask;
-+      /* Bail out if no new IRQ bits or if all are masked out */
-+      if (!irqtype)
-+              break;
-+
-+      if (unlikely(++priv->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 */
-+              acx_write_reg16(priv, IO_ACX_IRQ_MASK, 0xffff);
-+              /* This will short-circuit all future attempts to handle IRQ.
-+               * We cant do much more... */
-+              priv->irq_mask = 0;
-+              break;
-+      }
-+}
-+#endif
-+      /* Routine to perform blink with range */
-+      if (unlikely(priv->led_power == 2))
-+              acx_l_update_link_quality_led(priv);
-+
-+/* handled: */
-+      /* acx_write_flush(priv); - not needed, last op was read anyway */
-+      acx_unlock(priv, flags);
-+      FN_EXIT0;
-+      return IRQ_HANDLED;
-+
-+none:
-+      acx_unlock(priv, flags);
-+      return IRQ_NONE;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_l_power_led
-+*----------------------------------------------------------------*/
-+void
-+acx_l_power_led(wlandevice_t *priv, int enable)
-+{
-+      u16 gpio_pled = IS_ACX111(priv) ? 0x0040 : 0x0800;
-+
-+      /* A hack. Not moving message rate limiting to priv->xxx
-+       * (it's only a debug message after all) */
-+      static int rate_limit = 0;
-+
-+      if (rate_limit++ < 3)
-+              acxlog(L_IOCTL, "Please report in case toggling the power "
-+                              "LED doesn't work for your card!\n");
-+      if (enable)
-+              acx_write_reg16(priv, IO_ACX_GPIO_OUT,
-+                      acx_read_reg16(priv, IO_ACX_GPIO_OUT) & ~gpio_pled);
-+      else
-+              acx_write_reg16(priv, IO_ACX_GPIO_OUT,
-+                      acx_read_reg16(priv, IO_ACX_GPIO_OUT) | gpio_pled);
-+}
-+
-+
-+/***********************************************************************
-+** Ioctls
-+*/
-+
-+/***********************************************************************
-+*/
-+int
-+acx111pci_ioctl_info(
-+      struct net_device *dev,
-+      struct iw_request_info *info,
-+      struct iw_param *vwrq,
-+      char *extra)
-+{
-+#if ACX_DEBUG
-+      wlandevice_t *priv = netdev_priv(dev);
-+      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(priv);
-+
-+      if (!IS_ACX111(priv)) {
-+              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(priv, &memconf, ACX1xx_IE_QUEUE_CONFIG);
-+
-+      /* get Acx111 Queue Configuration */
-+      memset(&queueconf, 0, sizeof(queueconf));
-+      acx_s_interrogate(priv, &queueconf, ACX1xx_IE_MEMORY_CONFIG_OPTIONS);
-+
-+      /* get Acx111 Memory Map */
-+      memset(memmap, 0, sizeof(memmap));
-+      acx_s_interrogate(priv, &memmap, ACX1xx_IE_MEMORY_MAP);
-+
-+      /* get Acx111 Rx Config */
-+      memset(rxconfig, 0, sizeof(rxconfig));
-+      acx_s_interrogate(priv, &rxconfig, ACX1xx_IE_RXCONFIG);
-+
-+      /* get Acx111 fcs error count */
-+      memset(fcserror, 0, sizeof(fcserror));
-+      acx_s_interrogate(priv, &fcserror, ACX1xx_IE_FCS_ERROR_COUNT);
-+
-+      /* get Acx111 rate fallback */
-+      memset(ratefallback, 0, sizeof(ratefallback));
-+      acx_s_interrogate(priv, &ratefallback, ACX1xx_IE_RATE_FALLBACK);
-+
-+      /* force occurrence of a beacon interrupt */
-+      /* TODO: comment why is this necessary */
-+      acx_write_reg16(priv, 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]),
-+              priv->iobase,
-+              priv->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(priv, flags);
-+
-+      /* dump acx111 internal rx descriptor ring buffer */
-+      rxdesc = priv->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 = priv->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 = priv->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 = move_txdesc(priv, txdesc, 1);
-+      }
-+
-+      /* dump host tx descriptor ring buffer */
-+
-+      txhostdesc = priv->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++;
-+      }
-+
-+      /* acx_write_reg16(priv, 0xb4, 0x4); */
-+
-+      acx_unlock(priv, flags);
-+end_ok:
-+
-+      acx_sem_unlock(priv);
-+#endif /* ACX_DEBUG */
-+      return OK;
-+}
-+
-+
-+/***********************************************************************
-+*/
-+int
-+acx100pci_ioctl_set_phy_amp_bias(
-+      struct net_device *dev,
-+      struct iw_request_info *info,
-+      struct iw_param *vwrq,
-+      char *extra)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+      unsigned long flags;
-+      u16 gpio_old;
-+
-+      if (!IS_ACX100(priv)) {
-+              /* 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(priv);
-+
-+      /* Need to lock accesses to [IO_ACX_GPIO_OUT]:
-+       * IRQ handler uses it to update LED */
-+      acx_lock(priv, flags);
-+      gpio_old = acx_read_reg16(priv, IO_ACX_GPIO_OUT);
-+      acx_write_reg16(priv, IO_ACX_GPIO_OUT, (gpio_old & 0xf8ff) | ((u16)*extra << 8));
-+      acx_unlock(priv, flags);
-+
-+      acxlog(L_DEBUG, "gpio_old: 0x%04X\n", gpio_old);
-+      printk("%s: PHY power amplifier bias: old:%d, new:%d\n",
-+              dev->name,
-+              (gpio_old & 0x0700) >> 8, (unsigned char)*extra);
-+
-+      acx_sem_unlock(priv);
-+
-+      return OK;
-+}
-+
-+
-+/***************************************************************
-+** acxpci_l_alloc_tx
-+** Actually returns a txdesc_t* ptr
-+*/
-+tx_t*
-+acxpci_l_alloc_tx(wlandevice_t* priv)
-+{
-+      struct txdesc *txdesc;
-+      u8 ctl8;
-+
-+      FN_ENTER;
-+
-+      txdesc = get_txdesc(priv, priv->tx_head);
-+      ctl8 = txdesc->Ctl_8;
-+      if (unlikely(DESC_CTL_HOSTOWN != (ctl8 & DESC_CTL_DONE))) {
-+              /* whoops, descr at current index is not free, so probably
-+               * ring buffer already full */
-+              /* FIXME: this causes a deadlock situation (endless
-+               * loop) in case the current descriptor remains busy,
-+               * so handle it a bit better in the future!! */
-+              printk("acx: BUG: tx_head->Ctl8=0x%02X, (0x%02X & "
-+                      "0x"DESC_CTL_DONE_STR") != 0x"DESC_CTL_HOSTOWN_STR
-+                      ": failed to find free tx descr\n",
-+                      ctl8, ctl8);
-+              txdesc = NULL;
-+              goto end;
-+      }
-+
-+      priv->tx_free--;
-+      acxlog(L_BUFT, "tx: got desc %u, %u remain\n",
-+                      priv->tx_head, priv->tx_free);
-+
-+/*
-+ * This comment is probably not entirely correct, needs further discussion
-+ * (restored commented-out code below to fix Tx ring buffer overflow,
-+ * since it's much better to have a slightly less efficiently used ring
-+ * buffer rather than one which easily overflows):
-+ *
-+ * This doesn't do anything other than limit our maximum number of
-+ * buffers used at a single time (we might as well just declare
-+ * TX_STOP_QUEUE less descriptors when we open up.) We should just let it
-+ * slide here, and back off TX_STOP_QUEUE in acx_l_clean_tx_desc, when given the
-+ * opportunity to let the queue start back up.
-+ */
-+      if (priv->tx_free < TX_STOP_QUEUE) {
-+              acxlog(L_BUF, "stop queue (%u tx desc left)\n",
-+                              priv->tx_free);
-+              acx_stop_queue(priv->netdev, NULL);
-+      }
-+
-+      /* returning current descriptor, so advance to next free one */
-+      priv->tx_head = (priv->tx_head + 1) % TX_CNT;
-+end:
-+      FN_EXIT0;
-+
-+      return (tx_t*)txdesc;
-+}
-+
-+
-+/***********************************************************************
-+*/
-+void*
-+acxpci_l_get_txbuf(wlandevice_t *priv, tx_t* tx_opaque)
-+{
-+      return acx_get_txhostdesc(priv, (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).
-+*/
-+void
-+acxpci_l_tx_data(wlandevice_t *priv, tx_t* tx_opaque, int len)
-+{
-+      txdesc_t *txdesc = (txdesc_t*)tx_opaque;
-+      txhostdesc_t *hostdesc1, *hostdesc2;
-+      client_t *clt;
-+      u8 Ctl_8, Ctl2_8;
-+
-+      FN_ENTER;
-+
-+      /* fw doesn't tx such packets anyhow */
-+      if (len < WLAN_HDR_A3_LEN)
-+              goto end;
-+
-+      hostdesc1 = acx_get_txhostdesc(priv, txdesc);
-+      hostdesc2 = hostdesc1 + 1;
-+
-+      /* 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 = txdesc->Ctl2_8;
-+
-+      /* 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...
-+       * FIXME: what about Ctl2? Equally problematic? */
-+
-+      /* let chip do RTS/CTS handshaking before sending
-+       * in case packet size exceeds threshold */
-+      if (len > priv->rts_threshold)
-+              SET_BIT(Ctl2_8, DESC_CTL2_RTS);
-+      else
-+              CLEAR_BIT(Ctl2_8, DESC_CTL2_RTS);
-+
-+#ifdef DEBUG_WEP
-+      if (priv->wep_enabled)
-+              SET_BIT(Ctl2_8, DESC_CTL2_WEP);
-+      else
-+              CLEAR_BIT(Ctl2_8, DESC_CTL2_WEP);
-+#endif
-+
-+      switch (priv->mode) {
-+      case ACX_MODE_0_ADHOC:
-+      case ACX_MODE_3_AP:
-+              clt = acx_l_sta_list_get(priv, ((wlan_hdr_t*)hostdesc1->data)->a1);
-+              break;
-+      case ACX_MODE_2_STA:
-+              clt = priv->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;
-+      }
-+
-+      if (unlikely(clt && !clt->rate_cur)) {
-+              printk("acx: driver bug! bad ratemask\n");
-+              goto end;
-+      }
-+
-+      /* used in tx cleanup routine for auto rate and accounting: */
-+      acx_put_txc(priv, txdesc, clt);
-+
-+      txdesc->total_length = cpu_to_le16(len);
-+      hostdesc2->length = cpu_to_le16(len - WLAN_HDR_A3_LEN);
-+      if (IS_ACX111(priv)) {
-+              u16 rate_cur = clt ? clt->rate_cur : priv->rate_bcast;
-+              /* 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 : priv->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);
-+              hostdesc1->length = cpu_to_le16(WLAN_HDR_A3_LEN);
-+      }
-+      /* don't need to clean ack/rts statistics here, already
-+       * done on descr cleanup */
-+
-+      /* clears Ctl DESC_CTL_HOSTOWN bit, thus telling that the descriptors
-+       * are now owned by the acx100; do this as LAST operation */
-+      CLEAR_BIT(Ctl_8, DESC_CTL_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); */
-+//TODO: should it be a mmiowb() instead? we are protecting against race with write[bwl]()
-+      /* flush writes before we tell the adapter that it's its turn now */
-+      wmb(); 
-+      acx_write_reg16(priv, IO_ACX_INT_TRIG, INT_TRIG_TXPRC);
-+      acx_write_flush(priv);
-+
-+      /* 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(priv))
-+                      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)" : "",
-+                              priv->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)" : "",
-+                              priv->status);
-+
-+              if (acx_debug & L_DATA) {
-+                      printk("tx: 802.11 [%d]: ", len);
-+                      acx_dump_bytes(hostdesc1->data, len);
-+              }
-+      }
-+end:
-+      FN_EXIT0;
-+}
-+
-+
-+/***********************************************************************
-+*/
-+static void
-+acx_l_handle_tx_error(wlandevice_t *priv, 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";
-+              priv->wstats.discard.fragment++;
-+              break;
-+      case 0x02:
-+              err = "Tx aborted";
-+              priv->stats.tx_aborted_errors++;
-+              break;
-+      case 0x04:
-+              err = "Tx desc wrong parameters";
-+              priv->wstats.discard.misc++;
-+              break;
-+      case 0x08:
-+              err = "WEP key not found";
-+              priv->wstats.discard.misc++;
-+              break;
-+      case 0x10:
-+              err = "MSDU lifetime timeout? - try changing "
-+                              "'iwconfig retry lifetime XXX'";
-+              priv->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'";
-+              priv->wstats.discard.retries++;
-+              /* FIXME: set (GETSET_TX|GETSET_RX) here
-+               * (this seems to recalib radio on ACX100)
-+               * after some more jiffies passed??
-+               * But OTOH Tx error 0x20 also seems to occur on
-+               * overheating, so I'm not sure whether we
-+               * actually want that, 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.
-+               * ENABLE_TX|ENABLE_RX helps, so even do
-+               * DISABLE_TX and DISABLE_RX in order to perhaps
-+               * have more impact. */
-+              if (++priv->retry_errors_msg_ratelimit % 4 == 0) {
-+                      if (priv->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",
-+                                      priv->netdev->name);
-+                      if (priv->retry_errors_msg_ratelimit == 20)
-+                              printk("disabling above "
-+                                      "notification message\n");
-+
-+                      acx_schedule_after_interrupt_task(priv, ACX_AFTER_IRQ_CMD_RADIO_RECALIB);
-+              }
-+              break;
-+      case 0x40:
-+              err = "Tx buffer overflow";
-+              priv->stats.tx_fifo_errors++;
-+              break;
-+      case 0x80:
-+              err = "DMA error";
-+              priv->wstats.discard.misc++;
-+              break;
-+      }
-+      priv->stats.tx_errors++;
-+      if (priv->stats.tx_errors <= 20)
-+              printk("%s: tx error 0x%02X, buf %02u! (%s)\n",
-+                              priv->netdev->name, error, finger, err);
-+      else
-+              printk("%s: tx error 0x%02X, buf %02u!\n",
-+                              priv->netdev->name, error, finger);
-+}
-+
-+
-+/***********************************************************************
-+*/
-+/* 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_2;
-+      }
-+}
-+
-+
-+static void
-+acx_l_handle_txrate_auto(wlandevice_t *priv, struct client *txc,
-+                      unsigned int idx, u8 rate100, u16 rate111, u8 error)
-+{
-+      u16 sent_rate;
-+      u16 cur = txc->rate_cur;
-+      int slower_rate_was_used;
-+
-+      /* FIXME: need to implement some kind of rate success memory
-+       * which stores the success percentage per rate, to be taken
-+       * into account when considering allowing a new rate, since it
-+       * doesn't really help to stupidly count fallback/stepup,
-+       * since one invalid rate will spoil the party anyway
-+       * (such as 22M in case of 11M-only peers) */
-+
-+      /* 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 */
-+
-+      /* do some preparations, i.e. calculate the one rate that was
-+       * used to send this packet */
-+      if (IS_ACX111(priv)) {
-+              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 */
-+      acxlog(L_DEBUG, "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, priv->fallback_threshold,
-+              txc->stepup_count, priv->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 here only, in order to have the 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 & 0x30)) {
-+              txc->stepup_count = 0;
-+              if (++txc->fallback_count <= priv->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! */
-+                      acxlog(L_XFER, "tx: falling back to ratemask %04X\n", cur);
-+                      txc->rate_cur = cur;
-+                      txc->ignore_count = TX_CNT - priv->tx_free;
-+              }
-+      } else if (!slower_rate_was_used) {
-+              txc->fallback_count = 0;
-+              if (++txc->stepup_count <= priv->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);
-+              acxlog(L_XFER, "tx: stepping up to ratemask %04X\n", cur);
-+              txc->rate_cur = cur;
-+              /* FIXME: totally bogus - we could be sending to many peers at once... */
-+              txc->ignore_count = TX_CNT - priv->tx_free;
-+      }
-+
-+      /* calculate acx100 style rate byte if needed */
-+      if (IS_ACX100(priv)) {
-+              txc->rate_100 = bitpos2rate100[highest_bit(cur)];
-+      }
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_l_log_txbuffer
-+*----------------------------------------------------------------*/
-+#if !ACX_DEBUG
-+static inline void acx_l_log_txbuffer(const wlandevice_t *priv) {}
-+#else
-+static void
-+acx_l_log_txbuffer(wlandevice_t *priv)
-+{
-+      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 = priv->txdesc_start;
-+      if (!txdesc) return;
-+      for (i = 0; i < TX_CNT; i++) {
-+              if ((txdesc->Ctl_8 & DESC_CTL_DONE) == DESC_CTL_DONE)
-+                      printk("tx: buf %d done\n", i);
-+              txdesc = move_txdesc(priv, txdesc, 1);
-+      }
-+}
-+#endif
-+
-+
-+/*----------------------------------------------------------------
-+* acx_l_clean_tx_desc
-+*
-+* 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.
-+* Oops, now we have our own index, so everytime we get called we know
-+* where the next packet to be cleaned is.
-+* Hmm, still need to loop through the whole ring buffer now,
-+* since we lost sync for some reason when ping flooding or so...
-+* (somehow we don't get the IRQ for acx_l_clean_tx_desc any more when
-+* too many packets are being sent!)
-+* FIXME: currently we only process one packet, but this gets out of
-+* sync for some reason when ping flooding, so we need to loop,
-+* but the previous smart loop implementation causes the ping latency
-+* to rise dramatically (~3000 ms), at least on CardBus PheeNet WL-0022.
-+* Dunno what to do :-\
-+*----------------------------------------------------------------*/
-+unsigned int
-+acx_l_clean_tx_desc(wlandevice_t *priv)
-+{
-+      txdesc_t *txdesc;
-+      struct client *txc;
-+      int finger;
-+      int num_cleaned;
-+      int to_process;
-+      u16 r111;
-+      u8 error, ack_failures, rts_failures, rts_ok, r100;
-+
-+      FN_ENTER;
-+
-+      if (unlikely(acx_debug & L_DEBUG))
-+              acx_l_log_txbuffer(priv);
-+
-+      acxlog(L_BUFT, "tx: cleaning up bufs from %u\n", priv->tx_tail);
-+
-+      finger = priv->tx_tail;
-+      num_cleaned = 0;
-+      to_process = TX_CNT;
-+      do {
-+              txdesc = get_txdesc(priv, finger);
-+
-+              /* abort if txdesc is not marked as "Tx finished" and "owned" */
-+              if ((txdesc->Ctl_8 & DESC_CTL_DONE) != DESC_CTL_DONE) {
-+                      /* we do need to have at least one cleaned,
-+                       * otherwise we wouldn't get called in the first place
-+                       */
-+                      if (num_cleaned)
-+                              break;
-+              }
-+
-+              /* remember descr 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 = txdesc->u.r2.rate111;
-+
-+#if WIRELESS_EXT > 13 /* wireless_send_event() and IWEVTXDROP are WE13 */
-+              /* 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 = acx_get_txhostdesc(priv, txdesc);
-+                      hdr = (wlan_hdr_t *)hostdesc->data;
-+                      MAC_COPY(wrqu.addr.sa_data, hdr->a1);
-+                      wireless_send_event(priv->netdev, IWEVTXDROP, &wrqu, NULL);
-+              }
-+#endif
-+              /* ...and free the descr */
-+              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:
-+               * if _OWN is set at the beginning instead, our own get_tx
-+               * might choose a Tx desc that isn't fully cleared
-+               * (in case of bad locking). */
-+              txdesc->Ctl_8 = DESC_CTL_HOSTOWN;
-+              priv->tx_free++;
-+              num_cleaned++;
-+
-+              if ((priv->tx_free >= TX_START_QUEUE)
-+              && (priv->status == ACX_STATUS_4_ASSOCIATED)
-+              && (acx_queue_stopped(priv->netdev))
-+              ) {
-+                      acxlog(L_BUF, "tx: wake queue (avail. Tx desc %u)\n",
-+                                      priv->tx_free);
-+                      acx_wake_queue(priv->netdev, NULL);
-+              }
-+
-+              /* do error checking, rate handling and logging
-+               * AFTER having done the work, it's faster */
-+
-+              /* do rate handling */
-+              txc = acx_get_txc(priv, txdesc);
-+              if (txc && priv->rate_auto) {
-+                      acx_l_handle_txrate_auto(priv, txc, finger, r100, r111, error);
-+              }
-+
-+              if (unlikely(error))
-+                      acx_l_handle_tx_error(priv, error, finger);
-+
-+              if (IS_ACX111(priv))
-+                      acxlog(L_BUFT, "tx: cleaned %u: !ACK=%u !RTS=%u RTS=%u r111=%04X\n",
-+                              finger, ack_failures, rts_failures, rts_ok, r111);
-+              else
-+                      acxlog(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;
-+      } while (--to_process);
-+
-+      /* remember last position */
-+      priv->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
-+acx_l_clean_tx_desc_emergency(wlandevice_t *priv)
-+{
-+      txdesc_t *txdesc;
-+      unsigned int i;
-+
-+      FN_ENTER;
-+
-+      for (i = 0; i < TX_CNT; i++) {
-+              txdesc = get_txdesc(priv, i);
-+
-+              /* free it */
-+              txdesc->ack_failures = 0;
-+              txdesc->rts_failures = 0;
-+              txdesc->rts_ok = 0;
-+              txdesc->error = 0;
-+              txdesc->Ctl_8 = DESC_CTL_HOSTOWN;
-+      }
-+
-+      priv->tx_free = TX_CNT;
-+
-+      FN_EXIT0;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_l_log_rxbuffer
-+*
-+* Called from IRQ context only
-+*----------------------------------------------------------------*/
-+#if !ACX_DEBUG
-+static inline void acx_l_log_rxbuffer(const wlandevice_t *priv) {}
-+#else
-+static void
-+acx_l_log_rxbuffer(const wlandevice_t *priv)
-+{
-+      const struct rxhostdesc *rxhostdesc;
-+      int i;
-+
-+      /* no FN_ENTER here, we don't want that */
-+
-+      rxhostdesc = priv->rxhostdesc_start;
-+      if (!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
-+
-+
-+/***************************************************************
-+** acx_l_process_rx_desc
-+**
-+** Called directly and only from the IRQ handler
-+*/
-+void
-+acx_l_process_rx_desc(wlandevice_t *priv)
-+{
-+      rxhostdesc_t *hostdesc;
-+      /* unsigned int curr_idx; */
-+      unsigned int count = 0;
-+
-+      FN_ENTER;
-+
-+      if (unlikely(acx_debug & L_BUFR)) {
-+              acx_l_log_rxbuffer(priv);
-+      }
-+
-+      /* 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. */
-+      while (1) {
-+              /* curr_idx = priv->rx_tail; */
-+              hostdesc = &priv->rxhostdesc_start[priv->rx_tail];
-+              priv->rx_tail = (priv->rx_tail + 1) % RX_CNT;
-+              if ((hostdesc->Ctl_16 & cpu_to_le16(DESC_CTL_HOSTOWN))
-+               && (hostdesc->Status & cpu_to_le32(DESC_STATUS_FULL))) {
-+                      /* found it! */
-+                      break;
-+              }
-+              count++;
-+              if (unlikely(count > RX_CNT)) {
-+                      /* hmm, no luck: all descriptors empty, bail out */
-+                      goto end;
-+              }
-+      }
-+
-+      /* now process descriptors, starting with the first we figured out */
-+      while (1) {
-+              acxlog(L_BUFR, "rx: tail=%u Ctl_16=%04X Status=%08X\n",
-+                      priv->rx_tail, hostdesc->Ctl_16, hostdesc->Status);
-+
-+              acx_l_process_rxbuf(priv, 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 */
-+              /* curr_idx = priv->rx_tail; */
-+              hostdesc = &priv->rxhostdesc_start[priv->rx_tail];
-+
-+              /* if next descriptor is empty, then bail out */
-+              /* FIXME: is this check really entirely correct?? */
-+              /*
-+//FIXME: inconsistent with check in prev while() loop
-+              if (!(hostdesc->Ctl & cpu_to_le16(DESC_CTL_HOSTOWN))
-+               && !(hostdesc->Status & cpu_to_le32(DESC_STATUS_FULL))) */
-+              if (!(hostdesc->Status & cpu_to_le32(DESC_STATUS_FULL)))
-+                      break;
-+
-+              priv->rx_tail = (priv->rx_tail + 1) % RX_CNT;
-+      }
-+end:
-+      FN_EXIT0;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_s_create_tx_host_desc_queue
-+*----------------------------------------------------------------*/
-+static inline void*
-+acx_alloc_coherent(struct device *dev, size_t size,
-+                      dma_addr_t *dma_handle, int flag)
-+{
-+      printk("Size : %ld\n",size);
-+      dev->coherent_dma_mask      = 0xffffffff;
-+      return dma_alloc_coherent(dev, size, dma_handle, flag);
-+}
-+
-+static void*
-+allocate(wlandevice_t *priv, size_t size, dma_addr_t *phy, const char *msg)
-+{
-+      void *ptr = acx_alloc_coherent(priv->dev, size, phy, GFP_KERNEL);
-+      if (ptr) {
-+              acxlog(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
-+acx_s_create_tx_host_desc_queue(wlandevice_t *priv)
-+{
-+      txhostdesc_t *hostdesc;
-+      u8 *txbuf;
-+      dma_addr_t hostdesc_phy;
-+      dma_addr_t txbuf_phy;
-+      int i;
-+
-+      FN_ENTER;
-+
-+      /* allocate TX buffer */
-+      priv->txbuf_area_size = TX_CNT * WLAN_A4FR_MAXLEN_WEP_FCS;
-+      priv->txbuf_start = allocate(priv, priv->txbuf_area_size,
-+                      &priv->txbuf_startphy, "txbuf_start");
-+      if (!priv->txbuf_start)
-+              goto fail;
-+
-+      /* allocate the TX host descriptor queue pool */
-+      priv->txhostdesc_area_size = TX_CNT * 2*sizeof(txhostdesc_t);
-+      priv->txhostdesc_start = allocate(priv, priv->txhostdesc_area_size,
-+                      &priv->txhostdesc_startphy, "txhostdesc_start");
-+      if (!priv->txhostdesc_start)
-+              goto fail;
-+      /* check for proper alignment of TX host descriptor pool */
-+      if ((long) priv->txhostdesc_start & 3) {
-+              printk("acx: driver bug: dma alloc returns unaligned address\n");
-+              goto fail;
-+      }
-+
-+/* Each tx frame buffer is accessed by hardware via
-+** txdesc -> txhostdesc(s) -> framebuffer(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 hostdesc.length = 3 (or larger)
-+** Storing NULL into hostdesc.desc_phy_next
-+** doesn't seem to help.
-+*/
-+/* It is not known whether we need to have 'extra' second
-+** txhostdescs for acx100. Maybe it is acx111-only bug.
-+*/
-+      hostdesc = priv->txhostdesc_start;
-+      hostdesc_phy = priv->txhostdesc_startphy;
-+      txbuf = priv->txbuf_start;
-+      txbuf_phy = priv->txbuf_startphy;
-+
-+      for (i = 0; i < TX_CNT*2; i++) {
-+              hostdesc_phy += sizeof(txhostdesc_t);
-+              if (!(i & 1)) {
-+                      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 = ... */
-+                      /* below: non-hardware fields */
-+                      hostdesc->data = txbuf;
-+
-+                      txbuf += WLAN_HDR_A3_LEN;
-+                      txbuf_phy += WLAN_HDR_A3_LEN;
-+              } else {
-+                      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 = ... */
-+                      /* below: non-hardware fields */
-+                      hostdesc->data = txbuf;
-+
-+                      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(priv->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;
-+}
-+
-+
-+/***************************************************************
-+** acx_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
-+acx_s_create_rx_host_desc_queue(wlandevice_t *priv)
-+{
-+      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 */
-+      priv->rxhostdesc_area_size = RX_CNT * sizeof(rxhostdesc_t);
-+      priv->rxhostdesc_start = allocate(priv, priv->rxhostdesc_area_size,
-+                      &priv->rxhostdesc_startphy, "rxhostdesc_start");
-+      if (!priv->rxhostdesc_start)
-+              goto fail;
-+      /* check for proper alignment of RX host descriptor pool */
-+      if ((long) priv->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 */
-+      priv->rxbuf_area_size = RX_CNT * RX_BUFFER_SIZE;
-+      priv->rxbuf_start = allocate(priv, priv->rxbuf_area_size,
-+                      &priv->rxbuf_startphy, "rxbuf_start");
-+      if (!priv->rxbuf_start)
-+              goto fail;
-+
-+      rxbuf = priv->rxbuf_start;
-+      rxbuf_phy = priv->rxbuf_startphy;
-+      hostdesc = priv->rxhostdesc_start;
-+      hostdesc_phy = priv->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(rxbuffer_t);
-+              hostdesc_phy += sizeof(rxhostdesc_t);
-+              hostdesc->desc_phy_next = cpu2acx(hostdesc_phy);
-+              hostdesc++;
-+      }
-+      hostdesc--;
-+      hostdesc->desc_phy_next = cpu2acx(priv->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;
-+}
-+
-+
-+/***************************************************************
-+** acx_s_create_hostdesc_queues
-+*/
-+int
-+acx_s_create_hostdesc_queues(wlandevice_t *priv)
-+{
-+      int result;
-+      result = acx_s_create_tx_host_desc_queue(priv);
-+      if (OK != result) return result;
-+      result = acx_s_create_rx_host_desc_queue(priv);
-+      return result;
-+}
-+
-+
-+/***************************************************************
-+** acx_create_tx_desc_queue
-+*/
-+static void
-+acx_create_tx_desc_queue(wlandevice_t *priv, u32 tx_queue_start)
-+{
-+      txdesc_t *txdesc;
-+      txhostdesc_t *hostdesc;
-+      dma_addr_t hostmemptr;
-+      u32 mem_offs;
-+      int i;
-+
-+      FN_ENTER;
-+
-+      priv->txdesc_size = sizeof(txdesc_t);
-+
-+      if (IS_ACX111(priv)) {
-+              /* the acx111 txdesc is 4 bytes larger */
-+              priv->txdesc_size = sizeof(txdesc_t) + 4;
-+      }
-+
-+#if 0
-+      priv->txdesc_start = (txdesc_t *) (priv->iobase2 + tx_queue_start);
-+
-+      acxlog(L_DEBUG, "priv->iobase2=%p\n"
-+                      "tx_queue_start=%08X\n"
-+                      "priv->txdesc_start=%p\n",
-+                      priv->iobase2,
-+                      tx_queue_start,
-+                      priv->txdesc_start);
-+
-+      priv->tx_free = TX_CNT;
-+#endif
-+      /* done by memset: priv->tx_head = 0; */
-+      /* done by memset: priv->tx_tail = 0; */
-+      txdesc     = priv->txdesc_start;
-+      mem_offs   = tx_queue_start;
-+      hostmemptr = priv->txhostdesc_startphy;
-+      hostdesc   = priv->txhostdesc_start;
-+
-+#if 0
-+      if (IS_ACX111(priv)) {
-+              /* 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(txhostdesc_t);
-+                      txdesc = move_txdesc(priv, txdesc, 1);
-+              }
-+      } else {
-+              /* ACX100 Tx buffer needs to be initialized by us */
-+              /* clear whole send pool. sizeof is safe here (we are acx100) */
-+              memset(priv->txdesc_start, 0, TX_CNT * sizeof(txdesc_t));
-+
-+              /* loop over whole send pool */
-+              for (i = 0; i < TX_CNT; i++) {
-+                      acxlog(L_DEBUG, "configure card tx descriptor: 0x%p, "
-+                              "size: 0x%X\n", txdesc, priv->txdesc_size);
-+
-+                      /* pointer to hostdesc memory */
-+                      /* FIXME: type-incorrect assignment, might cause trouble
-+                       * in some cases */
-+                      txdesc->HostMemPtr = ptr2acx(hostmemptr);
-+                      /* initialise ctl */
-+                      txdesc->Ctl_8   = DESC_CTL_INIT;
-+                      txdesc->Ctl2_8  = 0;
-+                      /* point to next txdesc */
-+                      txdesc->pNextDesc = cpu2acx(mem_offs + priv->txdesc_size);
-+                      /* reserve two (hdr desc and payload desc) */
-+                      hostdesc   += 2;
-+                      hostmemptr += 2 * sizeof(txhostdesc_t);
-+                      /* go to the next one */
-+                      mem_offs   += priv->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);
-+      }
-+#endif
-+      FN_EXIT0;
-+}
-+
-+
-+/***************************************************************
-+** acx_create_rx_desc_queue
-+*/
-+static void
-+acx_create_rx_desc_queue(wlandevice_t *priv, u32 rx_queue_start)
-+{
-+      rxdesc_t *rxdesc;
-+      u32 mem_offs;
-+      int i;
-+
-+      FN_ENTER;
-+
-+      /* done by memset: priv->rx_tail = 0; */
-+
-+      /* ACX111 doesn't need any further config: preconfigures itself.
-+       * Simply print ring buffer for debugging */
-+      if (IS_ACX111(priv)) {
-+              /* rxdesc_start already set here */
-+
-+              priv->rxdesc_start = (rxdesc_t *) ((u8 *)priv->iobase2 + rx_queue_start);
-+
-+              rxdesc = priv->rxdesc_start;
-+              for (i = 0; i < RX_CNT; i++) {
-+                      acxlog(L_DEBUG, "rx descriptor %d @ 0x%p\n", i, rxdesc);
-+                      rxdesc = priv->rxdesc_start = (rxdesc_t *)
-+                              (priv->iobase2 + acx2cpu(rxdesc->pNextDesc));
-+              }
-+      } else {
-+              /* we didn't pre-calculate rxdesc_start in case of ACX100 */
-+              /* rxdesc_start should be right AFTER Tx pool */
-+              priv->rxdesc_start = (rxdesc_t *)
-+                      ((u8 *) priv->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(priv->rxdesc_start, 0, RX_CNT * sizeof(rxdesc_t));
-+
-+              /* loop over whole receive pool */
-+              rxdesc = priv->rxdesc_start;
-+              mem_offs = rx_queue_start;
-+              for (i = 0; i < RX_CNT; i++) {
-+                      acxlog(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_t));
-+                      /* go to the next one */
-+                      mem_offs += sizeof(rxdesc_t);
-+                      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;
-+}
-+
-+
-+/***************************************************************
-+** acx_create_desc_queues
-+*/
-+void
-+acx_create_desc_queues(wlandevice_t *priv, u32 tx_queue_start, u32 rx_queue_start)
-+{
-+      acx_create_tx_desc_queue(priv, tx_queue_start);
-+      acx_create_rx_desc_queue(priv, rx_queue_start);
-+}
-+
-+
-+/***************************************************************
-+** acxpci_s_proc_diag_output
-+*/
-+char*
-+acxpci_s_proc_diag_output(char *p, wlandevice_t *priv)
-+{
-+      const char *rtl, *thd, *ttl;
-+      rxhostdesc_t *rxhostdesc;
-+      txdesc_t *txdesc;
-+      int i;
-+
-+      FN_ENTER;
-+
-+      p += sprintf(p, "** Rx buf **\n");
-+      rxhostdesc = priv->rxhostdesc_start;
-+      if (rxhostdesc) for (i = 0; i < RX_CNT; i++) {
-+              rtl = (i == priv->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", priv->tx_free,
-+                              acx_queue_stopped(priv->netdev) ? "STOPPED" : "running");
-+      txdesc = priv->txdesc_start;
-+      if (txdesc) for (i = 0; i < TX_CNT; i++) {
-+              thd = (i == priv->tx_head) ? " [head]" : "";
-+              ttl = (i == priv->tx_tail) ? " [tail]" : "";
-+              if (txdesc->Ctl_8 & DESC_CTL_ACXDONE)
-+                      p += sprintf(p, "%02u DONE   (%02X)%s%s\n", i, txdesc->Ctl_8, thd, ttl);
-+              else
-+              if (!(txdesc->Ctl_8 & DESC_CTL_HOSTOWN))
-+                      p += sprintf(p, "%02u TxWait (%02X)%s%s\n", i, txdesc->Ctl_8, thd, ttl);
-+              else
-+                      p += sprintf(p, "%02u empty  (%02X)%s%s\n", i, txdesc->Ctl_8, thd, ttl);
-+              txdesc = move_txdesc(priv, 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",
-+              priv->txbuf_start, priv->txbuf_area_size, (u64)priv->txbuf_startphy,
-+              priv->txdesc_size, priv->txdesc_start,
-+              priv->txhostdesc_start, priv->txhostdesc_area_size, (u64)priv->txhostdesc_startphy,
-+              priv->rxdesc_start,
-+              priv->rxhostdesc_start, priv->rxhostdesc_area_size, (u64)priv->rxhostdesc_startphy,
-+              priv->rxbuf_start, priv->rxbuf_area_size, (u64)priv->rxbuf_startphy);
-+
-+      FN_EXIT0;
-+      return p;
-+}
-+
-+
-+/***********************************************************************
-+*/
-+int
-+acx_proc_eeprom_output(char *buf, wlandevice_t *priv)
-+{
-+      char *p = buf;
-+      int i;
-+
-+      FN_ENTER;
-+
-+      for (i = 0; i < 0x400; i++) {
-+              acx_read_eeprom_offset(priv, i, p++);
-+      }
-+
-+      FN_EXIT1(p - buf);
-+      return p - buf;
-+}
-+
-+
-+/***********************************************************************
-+*/
-+void
-+acx_set_interrupt_mask(wlandevice_t *priv)
-+{
-+      if (IS_ACX111(priv)) {
-+              priv->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        */
-+                              );
-+              priv->irq_mask_off = (u16)~( HOST_INT_CMD_COMPLETE ); /* 0xfdff */
-+      } else {
-+              priv->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        */
-+                              );
-+              priv->irq_mask_off = (u16)~( HOST_INT_UNKNOWN ); /* 0x7fff */
-+      }
-+}
-+
-+
-+/***********************************************************************
-+*/
-+int
-+acx100_s_set_tx_level(wlandevice_t *priv, 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 (priv->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",
-+                              priv->netdev->name);
-+              return NOT_OK;
-+      }
-+      printk("%s: changing radio power level to %u dBm (%u)\n",
-+                      priv->netdev->name, level_dbm, table[level_dbm]);
-+      acxpci_s_write_phy_reg(priv, 0x11, table[level_dbm]);
-+      return OK;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_e_init_module
-+*
-+* Module initialization routine, called once at module load time.
-+*
-+* Returns:
-+*     0       - success
-+*     ~0      - failure, module is unloaded.
-+*
-+* Call context:
-+*     process thread (insmod or modprobe)
-+----------------------------------------------------------------*/
-+int __init
-+acxcfi_e_init_module(void)
-+{
-+      int res;
-+
-+      FN_ENTER;
-+
-+      printk("acx: compiled to use 16bit I/O access only "
-+              "(compatibility mode)\n");
-+
-+      acxlog(L_INIT, "running on a little-endian CPU\n");
-+
-+      acxlog(L_INIT, 
-+             "Compact Flash module " WLAN_RELEASE " initialized, "
-+              "waiting for cards to probe...\n");
-+
-+      /*
-+         * Now let configure device
-+         * GPIOs
-+         */
-+        pca9535_gpio_direction(GPIO6, GPIO_OUTPUT);
-+        pca9535_gpio_direction(GPIO12, GPIO_OUTPUT);
-+
-+        if ((omap_request_gpio(11)) < 0) {
-+                printk("Error requesting gpio 11\n");
-+                return -EIO;
-+        }
-+      omap_set_gpio_direction (11, 1);
-+        omap_set_gpio_dataout (11, 1);
-+
-+        res = driver_register(&acx_driver);
-+
-+      FN_EXIT1(res);
-+      return res;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_cleanup_module
-+*
-+* Called at module unload time.  This is our last chance to
-+* clean up after ourselves.
-+*
-+* Call context:
-+*     process thread
-+----------------------------------------------------------------*/
-+void __exit
-+acxcfi_e_cleanup_module(void)
-+{
-+      struct net_device *dev;
-+      unsigned long flags;
-+
-+      FN_ENTER;
-+
-+      /* Since the whole module is about to be unloaded,
-+       * we recursively shutdown all cards we handled instead
-+       * of doing it in remove_pci() (which will be activated by us
-+       * via pci_unregister_driver at the end).
-+       * remove_pci() might just get called after a card eject,
-+       * that's why hardware operations have to be done here instead
-+       * when the hardware is available. */
-+
-+      down(&root_acx_dev_sem);
-+
-+      dev = root_acx_dev.newest;
-+      while (dev != NULL) {
-+              /* doh, netdev_priv() doesn't have const! */
-+              wlandevice_t *priv = netdev_priv(dev);
-+
-+              acx_sem_lock(priv);
-+
-+              /* disable both Tx and Rx to shut radio down properly */
-+              acx_s_issue_cmd(priv, ACX1xx_CMD_DISABLE_TX, NULL, 0);
-+              acx_s_issue_cmd(priv, 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(priv, ACX100_CMD_SLEEP, NULL, 0);
-+#endif
-+              acx_lock(priv, flags);
-+
-+              /* disable power LED to save power :-) */
-+              acxlog(L_INIT, "switching off power LED to save power :-)\n");
-+              acx_l_power_led(priv, 0);
-+
-+              /* stop our eCPU */
-+              if (IS_ACX111(priv)) {
-+                      /* FIXME: does this actually keep halting the eCPU?
-+                       * I don't think so...
-+                       */
-+                      acx_l_reset_mac(priv);
-+              } else {
-+                      u16 temp;
-+
-+                      /* halt eCPU */
-+                      temp = acx_read_reg16(priv, IO_ACX_ECPU_CTRL) | 0x1;
-+                      acx_write_reg16(priv, IO_ACX_ECPU_CTRL, temp);
-+                      acx_write_flush(priv);
-+              }
-+
-+              acx_unlock(priv, flags);
-+
-+              acx_sem_unlock(priv);
-+
-+              dev = priv->prev_nd;
-+      }
-+
-+      up(&root_acx_dev_sem);
-+
-+      omap_free_gpio(11);
-+        driver_unregister(&acx_driver);
-+
-+      FN_EXIT0;
-+}
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/net/wireless/tiacx/common.c bt_kernel/drivers/net/wireless/tiacx/common.c
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/net/wireless/tiacx/common.c 1970-01-01 02:00:00.000000000 +0200
-+++ bt_kernel/drivers/net/wireless/tiacx/common.c      2005-09-28 23:54:23.938287000 +0300
-@@ -0,0 +1,6590 @@
-+/***********************************************************************
-+** 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/config.h>
-+#include <linux/version.h>
-+#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 <asm/bug.h>
-+#if WIRELESS_EXT >= 13
-+#include <net/iw_handler.h>
-+#endif /* WE >= 13 */
-+
-+#include "acx.h"
-+
-+
-+#define rdtscl(a)
-+
-+/***********************************************************************
-+*/
-+static client_t *acx_l_sta_list_alloc(wlandevice_t *priv);
-+static client_t *acx_l_sta_list_get_from_hash(wlandevice_t *priv, const u8 *address);
-+
-+static int acx_l_process_data_frame_master(wlandevice_t *priv, rxbuffer_t *rxbuf);
-+static int acx_l_process_data_frame_client(wlandevice_t *priv, rxbuffer_t *rxbuf);
-+/* static int acx_l_process_NULL_frame(wlandevice_t *priv, rxbuffer_t *rxbuf, int vala); */
-+static int acx_l_process_mgmt_frame(wlandevice_t *priv, rxbuffer_t *rxbuf);
-+static void acx_l_process_disassoc_from_sta(wlandevice_t *priv, const wlan_fr_disassoc_t *req);
-+static void acx_l_process_disassoc_from_ap(wlandevice_t *priv, const wlan_fr_disassoc_t *req);
-+static void acx_l_process_deauth_from_sta(wlandevice_t *priv, const wlan_fr_deauthen_t *req);
-+static void acx_l_process_deauth_from_ap(wlandevice_t *priv, const wlan_fr_deauthen_t *req);
-+static int acx_l_process_probe_response(wlandevice_t *priv, wlan_fr_proberesp_t *req, const rxbuffer_t *rxbuf);
-+static int acx_l_process_assocresp(wlandevice_t *priv, const wlan_fr_assocresp_t *req);
-+static int acx_l_process_reassocresp(wlandevice_t *priv, const wlan_fr_reassocresp_t *req);
-+static int acx_l_process_authen(wlandevice_t *priv, const wlan_fr_authen_t *req);
-+static int acx_l_transmit_assocresp(wlandevice_t *priv, const wlan_fr_assocreq_t *req);
-+static int acx_l_transmit_reassocresp(wlandevice_t *priv, const wlan_fr_reassocreq_t *req);
-+static int acx_l_transmit_deauthen(wlandevice_t *priv, const u8 *addr, u16 reason);
-+static int acx_l_transmit_authen1(wlandevice_t *priv);
-+static int acx_l_transmit_authen2(wlandevice_t *priv, const wlan_fr_authen_t *req, client_t *clt);
-+static int acx_l_transmit_authen3(wlandevice_t *priv, const wlan_fr_authen_t *req);
-+static int acx_l_transmit_authen4(wlandevice_t *priv, const wlan_fr_authen_t *req);
-+static int acx_l_transmit_assoc_req(wlandevice_t *priv);
-+
-+
-+/***********************************************************************
-+*/
-+#if ACX_DEBUG
-+unsigned int acx_debug = L_ASSOC|L_INIT;
-+#endif
-+#if USE_FW_LOADER_LEGACY
-+static char *firmware_dir;
-+#endif
-+#if SEPARATE_DRIVER_INSTANCES
-+static int card;
-+#endif
-+
-+/* introduced earlier than 2.6.10, but takes more memory, so don't use it
-+ * if there's no compile warning by kernel */
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
-+
-+#if ACX_DEBUG
-+/* parameter is 'debug', corresponding var is acx_debug */
-+module_param_named(debug, acx_debug, uint, 0);
-+#endif
-+#if USE_FW_LOADER_LEGACY
-+module_param(firmware_dir, charp, 0);
-+#endif
-+
-+#else
-+
-+#if ACX_DEBUG
-+/* doh, 2.6.x screwed up big time: here the define has its own ";"
-+ * ("double ; detected"), yet in 2.4.x it DOESN'T (the sane thing to do),
-+ * grrrrr! */
-+MODULE_PARM(acx_debug, "i");
-+#endif
-+#if USE_FW_LOADER_LEGACY
-+MODULE_PARM(firmware_dir, "s");
-+#endif
-+
-+#endif
-+
-+#if ACX_DEBUG
-+MODULE_PARM_DESC(debug, "Debug level mask (see L_xxx constants)");
-+#endif
-+#if USE_FW_LOADER_LEGACY
-+MODULE_PARM_DESC(firmware_dir, "Directory to load acx100 firmware files from");
-+#endif
-+#if SEPARATE_DRIVER_INSTANCES
-+MODULE_PARM(card, "i");
-+MODULE_PARM_DESC(card, "Associate only with card-th acx100 card from this driver instance");
-+#endif
-+
-+/* Shoundn't be needed now, acx.firmware_dir= should work */
-+#if 0 /* USE_FW_LOADER_LEGACY */
-+static int __init
-+acx_get_firmware_dir(const char *str)
-+{
-+      /* I've seen other drivers just pass the string pointer,
-+       * so hopefully that's safe */
-+      firmware_dir = str;
-+      return OK;
-+}
-+__setup("acx_firmware_dir=", acx_get_firmware_dir);
-+#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 itermediate 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
-+
-+const u8 reg_domain_ids[] =
-+      { 0x10, 0x20, 0x30, 0x31, 0x32, 0x40, 0x41, 0x51 };
-+/* stupid workaround for the fact that in C the size of an external array
-+ * cannot be determined from within a second file */
-+const u8 reg_domain_ids_len = sizeof(reg_domain_ids);
-+static const u16 reg_domain_channel_masks[] =
-+      { 0x07ff, 0x07ff, 0x1fff, 0x0600, 0x1e00, 0x2000, 0x3fff, 0x01fc };
-+
-+
-+/***********************************************************************
-+** 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(wlandevice_t *priv, const char* where)
-+{
-+      int count = 100*1000*1000;
-+      where = sanitize_str(where);
-+      while (--count) {
-+              if (!spin_is_locked(&priv->lock)) break;
-+              cpu_relax();
-+      }
-+      if (!count) {
-+              printk(KERN_EMERG "LOCKUP: already taken at %s!\n", priv->last_lock);
-+              BUG();
-+      }
-+      priv->last_lock = where;
-+      rdtscl(priv->lock_time);
-+}
-+void
-+acx_unlock_debug(wlandevice_t *priv, const char* where)
-+{
-+#ifdef SMP
-+      if (!spin_is_locked(&priv->lock)) {
-+              where = sanitize_str(where);
-+              printk(KERN_EMERG "STRAY UNLOCK at %s!\n", where);
-+              BUG();
-+      }
-+#endif
-+      if (acx_debug & L_LOCK) {
-+              unsigned diff;
-+              rdtscl(diff);
-+              diff -= priv->lock_time;
-+              if (diff > max_lock_time) {
-+                      where = sanitize_str(where);
-+                      printk("max lock hold time %d CPU ticks from %s "
-+                              "to %s\n", diff, priv->last_lock, where);
-+                      max_lock_time = diff;
-+              }
-+      }
-+}
-+void
-+acx_down_debug(wlandevice_t *priv, const char* where)
-+{
-+      int sem_count;
-+      int count = 5000/5;
-+      where = sanitize_str(where);
-+
-+      while (--count) {
-+              sem_count = atomic_read(&priv->sem.count);
-+              if (sem_count) break;
-+              msleep(5);
-+      }
-+      if (!count) {
-+              printk(KERN_EMERG "D STATE at %s! last sem at %s\n",
-+                      where, priv->last_sem);
-+              dump_stack();
-+      }
-+      priv->last_sem = where;
-+      priv->sem_time = jiffies;
-+      down(&priv->sem);
-+      if (acx_debug & L_LOCK) {
-+              printk("%s: sem_down %d -> %d\n",
-+                      where, sem_count, atomic_read(&priv->sem.count));
-+      }
-+}
-+void
-+acx_up_debug(wlandevice_t *priv, const char* where)
-+{
-+      int sem_count = atomic_read(&priv->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 diff = jiffies - priv->sem_time;
-+              if (diff > max_sem_time) {
-+                      where = sanitize_str(where);
-+                      printk("max sem hold time %d jiffies from %s "
-+                              "to %s\n", diff, priv->last_sem, where);
-+                      max_sem_time = diff;
-+              }
-+      }
-+      up(&priv->sem);
-+      if (acx_debug & L_LOCK) {
-+              where = sanitize_str(where);
-+              printk("%s: sem_up %d -> %d\n",
-+                      where, sem_count, atomic_read(&priv->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??"
-+      };
-+      return str[(status < VEC_SIZE(str)) ? status : VEC_SIZE(str)-1];
-+}
-+
-+
-+/***********************************************************************
-+** 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 = "UNKNOWN";
-+      u8 fstype = (WF_FC_FSTYPE & fc) >> 4;
-+      u8 ctl;
-+
-+      switch (WF_FC_FTYPE & fc) {
-+      case WF_FTYPE_MGMT:
-+              str = "MGMT/UNKNOWN";
-+              if (fstype < VEC_SIZE(mgmt_arr))
-+                      str = mgmt_arr[fstype];
-+              break;
-+      case WF_FTYPE_CTL:
-+              ctl = fstype - 0x0a;
-+              str = "CTL/UNKNOWN";
-+              if (ctl < VEC_SIZE(ctl_arr))
-+                      str = ctl_arr[ctl];
-+              break;
-+      case WF_FTYPE_DATA:
-+              str = "DATA/UNKNOWN";
-+              if (fstype < VEC_SIZE(data_arr))
-+                      str = data_arr[fstype];
-+              break;
-+      }
-+      return str;
-+}
-+#endif
-+
-+
-+/***********************************************************************
-+** 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] : "UNKNOWN REASON";
-+}
-+
-+
-+/***********************************************************************
-+** get_status_string
-+*/
-+static 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",
-+      /*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)
-+{
-+      acxlog(L_ASSOC, "acx: unknown EID %d in mgmt frame at offset %d\n",
-+                              ie_ptr->eid, (int) ((u8*)ie_ptr - (u8*)hdr));
-+      if (acx_debug & (L_DATA|L_ASSOC)) {
-+              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
-+
-+
-+/***********************************************************************
-+** maps acx111 tx descr rate field to acx100 one
-+*/
-+const u8
-+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 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
-+*/
-+static const u16
-+CtlLength[] = {
-+      0,
-+      ACX100_IE_ACX_TIMER_LEN,
-+      ACX1xx_IE_POWER_MGMT_LEN,
-+      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,
-+      ACX1xx_IE_FIRMWARE_STATISTICS_LEN,
-+      0,
-+      ACX1xx_IE_FEATURE_CONFIG_LEN,
-+      ACX111_IE_KEY_CHOOSE_LEN,
-+};
-+
-+static const u16
-+CtlLengthDot11[] = {
-+      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(wlandevice_t *priv, void *pdr, int type)
-+{
-+#else
-+int
-+acx_s_configure_debug(wlandevice_t *priv, void *pdr, int type, const char* typestr)
-+{
-+#endif
-+      u16 len;
-+      int res;
-+
-+      if (type < 0x1000)
-+              len = CtlLength[type];
-+      else
-+              len = CtlLengthDot11[type - 0x1000];
-+
-+      acxlog(L_CTL, FUNC"(type:%s,len:%u)\n", typestr, len);
-+      if (unlikely(!len)) {
-+              acxlog(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(priv, ACX1xx_CMD_CONFIGURE, pdr, len + 4);
-+      if (OK != res) {
-+#if ACX_DEBUG
-+              printk("%s: "FUNC"(type:%s) FAILED\n", priv->netdev->name, typestr);
-+#else
-+              printk("%s: "FUNC"(type:0x%X) FAILED\n", priv->netdev->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(wlandevice_t *priv, void *pdr, int type)
-+{
-+#else
-+int
-+acx_s_interrogate_debug(wlandevice_t *priv, void *pdr, int type,
-+              const char* typestr)
-+{
-+#endif
-+      u16 len;
-+      int res;
-+
-+      if (type < 0x1000)
-+              len = CtlLength[type];
-+      else
-+              len = CtlLengthDot11[type-0x1000];
-+      acxlog(L_CTL, FUNC"(type:%s,len:%u)\n", typestr, len);
-+
-+      printk("Type : %08x, Len : %04x\n",type,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(priv, ACX1xx_CMD_INTERROGATE, pdr, len + 4);
-+      if (OK != res) {
-+#if ACX_DEBUG
-+              printk("%s: "FUNC"(type:%s) FAILED\n", priv->netdev->name, typestr);
-+#else
-+              printk("%s: "FUNC"(type:0x%X) FAILED\n", priv->netdev->name, type);
-+#endif
-+              /* dump_stack() is already done in issue_cmd() */
-+      }
-+      return res;
-+}
-+
-+#if CMD_DISCOVERY
-+void
-+great_inquisitor(wlandevice_t *priv)
-+{
-+      static struct {
-+              u16     type ACX_PACKED;
-+              u16     len ACX_PACKED;
-+              /* 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(priv, 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
-+**    priv is the usual pointer to our private struct wlandevice
-+** Returns:
-+**    number of bytes actually written to buf
-+** Side effects:
-+**    none
-+*/
-+static int
-+acx_l_proc_output(char *buf, wlandevice_t *priv)
-+{
-+      char *p = buf;
-+      int i;
-+
-+      FN_ENTER;
-+
-+      p += sprintf(p,
-+              "acx driver version:\t\t" WLAN_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",
-+              priv->chip_name, priv->firmware_id,
-+              priv->radio_type,
-+              priv->form_factor,
-+              priv->eeprom_version,
-+              priv->firmware_version, priv->firmware_numver);
-+
-+      for (i = 0; i < VEC_SIZE(priv->sta_list); i++) {
-+              struct client *bss = &priv->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",
-+                      priv->status, acx_get_status_name(priv->status));
-+
-+      FN_EXIT1(p - buf);
-+      return p - buf;
-+}
-+
-+
-+/***********************************************************************
-+*/
-+static int
-+acx_s_proc_diag_output(char *buf, wlandevice_t *priv)
-+{
-+      char *p = buf;
-+      fw_stats_t *fw_stats;
-+      unsigned long flags;
-+
-+      FN_ENTER;
-+
-+      fw_stats = kmalloc(sizeof(fw_stats_t), GFP_KERNEL);
-+      if (!fw_stats) {
-+              FN_EXIT1(0);
-+              return 0;
-+      }
-+      memset(fw_stats, 0, sizeof(fw_stats_t));
-+
-+      acx_lock(priv, flags);
-+
-+      if (IS_PCI(priv))
-+              p = acxpci_s_proc_diag_output(p, priv);
-+
-+      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, ",
-+              priv->dev_state_mask,
-+              priv->status, acx_get_status_name(priv->status),
-+              priv->mode, priv->channel,
-+              priv->reg_dom_id, priv->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",
-+              priv->essid, priv->essid_active, (int)priv->essid_len,
-+              priv->essid_for_assoc, priv->nick,
-+              priv->wep_enabled, priv->wep_restricted,
-+              priv->wep_current_index);
-+      p += sprintf(p, "dev_addr  "MACSTR"\n", MAC(priv->dev_addr));
-+      p += sprintf(p, "bssid     "MACSTR"\n", MAC(priv->bssid));
-+      p += sprintf(p, "ap_filter "MACSTR"\n", MAC(priv->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"
-+              "rts_threshold %d, short_retry %d, long_retry %d, msdu_lifetime %d, listen_interval %d, beacon_interval %d\n",
-+              priv->tx_disabled, priv->tx_level_dbm, /* priv->tx_level_val, priv->tx_level_auto, */
-+              priv->sensitivity, priv->antenna, priv->ed_threshold, priv->cca, priv->preamble_mode,
-+              priv->rts_threshold, priv->short_retry, priv->long_retry, priv->msdu_lifetime, priv->listen_interval, priv->beacon_interval);
-+
-+      acx_unlock(priv, flags);
-+
-+      if (OK != acx_s_interrogate(priv, fw_stats, ACX1xx_IE_FIRMWARE_STATISTICS))
-+              p += sprintf(p,
-+                      "\n"
-+                      "** Firmware **\n"
-+                      "QUERY FAILED!!\n");
-+      else {
-+              p += sprintf(p,
-+                      "\n"
-+                      "** Firmware **\n"
-+                      "version \"%s\"\n"
-+                      "tx_desc_overfl %u, rx_OutOfMem %u, rx_hdr_overfl %u, rx_hdr_use_next %u\n"
-+                      "rx_dropped_frame %u, rx_frame_ptr_err %u, rx_xfr_hint_trig %u, rx_dma_req %u\n"
-+                      "rx_dma_err %u, tx_dma_req %u, tx_dma_err %u, cmd_cplt %u, fiq %u\n"
-+                      "rx_hdrs %u, rx_cmplt %u, rx_mem_overfl %u, rx_rdys %u, irqs %u\n"
-+                      "acx_trans_procs %u, decrypt_done %u, dma_0_done %u, dma_1_done %u\n",
-+                      priv->firmware_version,
-+                      le32_to_cpu(fw_stats->tx_desc_of),
-+                      le32_to_cpu(fw_stats->rx_oom),
-+                      le32_to_cpu(fw_stats->rx_hdr_of),
-+                      le32_to_cpu(fw_stats->rx_hdr_use_next),
-+                      le32_to_cpu(fw_stats->rx_dropped_frame),
-+                      le32_to_cpu(fw_stats->rx_frame_ptr_err),
-+                      le32_to_cpu(fw_stats->rx_xfr_hint_trig),
-+                      le32_to_cpu(fw_stats->rx_dma_req),
-+                      le32_to_cpu(fw_stats->rx_dma_err),
-+                      le32_to_cpu(fw_stats->tx_dma_req),
-+                      le32_to_cpu(fw_stats->tx_dma_err),
-+                      le32_to_cpu(fw_stats->cmd_cplt),
-+                      le32_to_cpu(fw_stats->fiq),
-+                      le32_to_cpu(fw_stats->rx_hdrs),
-+                      le32_to_cpu(fw_stats->rx_cmplt),
-+                      le32_to_cpu(fw_stats->rx_mem_of),
-+                      le32_to_cpu(fw_stats->rx_rdys),
-+                      le32_to_cpu(fw_stats->irqs),
-+                      le32_to_cpu(fw_stats->acx_trans_procs),
-+                      le32_to_cpu(fw_stats->decrypt_done),
-+                      le32_to_cpu(fw_stats->dma_0_done),
-+                      le32_to_cpu(fw_stats->dma_1_done));
-+              p += sprintf(p,
-+                      "tx_exch_complet %u, commands %u, acx_rx_procs %u\n"
-+                      "hw_pm_mode_changes %u, host_acks %u, pci_pm %u, acm_wakeups %u\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",
-+                      le32_to_cpu(fw_stats->tx_exch_complet),
-+                      le32_to_cpu(fw_stats->commands),
-+                      le32_to_cpu(fw_stats->acx_rx_procs),
-+                      le32_to_cpu(fw_stats->hw_pm_mode_changes),
-+                      le32_to_cpu(fw_stats->host_acks),
-+                      le32_to_cpu(fw_stats->pci_pm),
-+                      le32_to_cpu(fw_stats->acm_wakeups),
-+                      le32_to_cpu(fw_stats->wep_key_count),
-+                      le32_to_cpu(fw_stats->wep_default_key_count),
-+                      le32_to_cpu(fw_stats->dot11_def_key_mib),
-+                      le32_to_cpu(fw_stats->wep_key_not_found),
-+                      le32_to_cpu(fw_stats->wep_decrypt_fail));
-+      }
-+
-+      kfree(fw_stats);
-+
-+      FN_EXIT1(p - buf);
-+      return p - buf;
-+}
-+
-+
-+/***********************************************************************
-+*/
-+static int
-+acx_s_proc_phy_output(char *buf, wlandevice_t *priv)
-+{
-+      char *p = buf;
-+      int i;
-+
-+      FN_ENTER;
-+
-+      /*
-+      if (RADIO_RFMD_11 != priv->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(priv, 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)
-+{
-+      wlandevice_t *priv = (wlandevice_t *)data;
-+      unsigned long flags;
-+      int length;
-+
-+      FN_ENTER;
-+
-+      acx_sem_lock(priv);
-+      acx_lock(priv, flags);
-+      /* fill buf */
-+      length = acx_l_proc_output(buf, priv);
-+      acx_unlock(priv, flags);
-+      acx_sem_unlock(priv);
-+
-+      /* 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_diag(char *buf, char **start, off_t offset, int count,
-+                   int *eof, void *data)
-+{
-+      wlandevice_t *priv = (wlandevice_t *)data;
-+      int length;
-+
-+      FN_ENTER;
-+
-+      acx_sem_lock(priv);
-+      /* fill buf */
-+      length = acx_s_proc_diag_output(buf, priv);
-+      acx_sem_unlock(priv);
-+
-+      /* 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_eeprom(char *buf, char **start, off_t offset, int count,
-+                   int *eof, void *data)
-+{
-+      wlandevice_t *priv = (wlandevice_t *)data;
-+      int length;
-+
-+      FN_ENTER;
-+
-+      /* fill buf */
-+      length = 0;
-+      if (IS_PCI(priv)) {
-+              acx_sem_lock(priv);
-+              length = acx_proc_eeprom_output(buf, priv);
-+              acx_sem_unlock(priv);
-+      }
-+
-+      /* 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)
-+{
-+      wlandevice_t *priv = (wlandevice_t *)data;
-+      int length;
-+
-+      FN_ENTER;
-+
-+      acx_sem_lock(priv);
-+      /* fill buf */
-+      length = acx_s_proc_phy_output(buf, priv);
-+      acx_sem_unlock(priv);
-+
-+      /* 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
-+acx_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 *dev, int remove)
-+{
-+      /* doh, netdev_priv() doesn't have const! */
-+      wlandevice_t *priv = netdev_priv((struct net_device *)dev);
-+      char procbuf[80];
-+      int i;
-+
-+      for (i = 0; i < 4; i++) {
-+              sprintf(procbuf, "driver/acx_%s", dev->name);
-+              strcat(procbuf, proc_files[i]);
-+              if (!remove) {
-+                      acxlog(L_INIT, "creating /proc entry %s\n", procbuf);
-+                      if (!create_proc_read_entry(procbuf, 0, 0, acx_proc_funcs[i], priv))
-+                              return NOT_OK;
-+              } else {
-+                      acxlog(L_INIT, "removing /proc entry %s\n", procbuf);
-+                      remove_proc_entry(procbuf, NULL);
-+              }
-+      }
-+      return OK;
-+}
-+
-+int
-+acx_proc_register_entries(const struct net_device *dev)
-+{
-+      return manage_proc_entries(dev, 0);
-+}
-+
-+int
-+acx_proc_unregister_entries(const struct net_device *dev)
-+{
-+      return manage_proc_entries(dev, 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 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(wlandevice_t *priv, const u8 *bssid)
-+{
-+      acx_joinbss_t tmp;
-+      int dtim_interval;
-+      int i;
-+
-+      FN_ENTER;
-+
-+      dtim_interval = (ACX_MODE_0_ADHOC == priv->mode) ?
-+                      1 : priv->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(priv->beacon_interval);
-+
-+      /* basic rate set. Control frame responses (such as ACK or CTS frames)
-+      ** are sent with one of these rates */
-+      if (IS_ACX111(priv)) {
-+              /* 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(priv->rate_basic);
-+              acxlog(L_ASSOC, "%s rates_basic %04X, rates_supported %04X\n",
-+                      __func__, priv->rate_basic, priv->rate_oper);
-+      } else {
-+              tmp.u.acx100.dtim_interval = dtim_interval;
-+              tmp.u.acx100.rates_basic = rate111to5bits(priv->rate_basic);
-+              tmp.u.acx100.rates_supported = rate111to5bits(priv->rate_oper);
-+              acxlog(L_ASSOC, "%s rates_basic %04X->%02X, "
-+                      "rates_supported %04X->%02X\n",
-+                      __func__,
-+                      priv->rate_basic, tmp.u.acx100.rates_basic,
-+                      priv->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.genfrm_txrate = bitpos2genframe_txrate[lowest_bit(priv->rate_basic)];
-+      tmp.genfrm_mod_pre = 0; /* FIXME: was = priv->capab_short (which is 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 = (priv->mode != ACX_MODE_MONITOR ? priv->mode : ACX_MODE_2_STA);
-+      tmp.channel = priv->channel;
-+      tmp.essid_len = priv->essid_len;
-+      /* NOTE: the code memcpy'd essid_len + 1 before, which is WRONG! */
-+      memcpy(tmp.essid, priv->essid, tmp.essid_len);
-+      acx_s_issue_cmd(priv, ACX1xx_CMD_JOIN, &tmp, tmp.essid_len + 0x11);
-+
-+      acxlog(L_ASSOC|L_DEBUG, "BSS_Type = %u\n", tmp.macmode);
-+      acxlog_mac(L_ASSOC|L_DEBUG, "JoinBSSID MAC:", priv->bssid, "\n");
-+
-+      acx_update_capabilities(priv);
-+      FN_EXIT0;
-+}
-+
-+
-+/***********************************************************************
-+** acx_s_cmd_start_scan
-+**
-+** Issue scan command to the hardware
-+*/
-+static void
-+acx100_s_scan_chan(wlandevice_t *priv)
-+{
-+      acx100_scan_t s;
-+
-+      FN_ENTER;
-+
-+      memset(&s, 0, sizeof(s));
-+      s.count = cpu_to_le16(priv->scan_count);
-+      s.start_chan = cpu_to_le16(1);
-+      s.flags = cpu_to_le16(0x8000);
-+      s.max_rate = priv->scan_rate;
-+      s.options = priv->scan_mode;
-+      s.chan_duration = cpu_to_le16(priv->scan_duration);
-+      s.max_probe_delay = cpu_to_le16(priv->scan_probe_delay);
-+
-+      acx_s_issue_cmd(priv, ACX1xx_CMD_SCAN, &s, sizeof(s));
-+      FN_EXIT0;
-+}
-+
-+static void
-+acx111_s_scan_chan(wlandevice_t *priv)
-+{
-+      acx111_scan_t s;
-+
-+      FN_ENTER;
-+
-+      memset(&s, 0, sizeof(s));
-+      s.count = cpu_to_le16(priv->scan_count);
-+      s.channel_list_select = 0; /* scan every allowed channel */
-+      /*s.channel_list_select = 1;*/ /* scan given channels */
-+      s.rate = priv->scan_rate;
-+      s.options = priv->scan_mode;
-+      s.chan_duration = cpu_to_le16(priv->scan_duration);
-+      s.max_probe_delay = cpu_to_le16(priv->scan_probe_delay);
-+      /*s.modulation = 0x40;*/ /* long preamble? OFDM? -> only for active scan */
-+      s.modulation = 0;
-+      /*s.channel_list[0] = 6;
-+      s.channel_list[1] = 4;*/
-+
-+      acx_s_issue_cmd(priv, ACX1xx_CMD_SCAN, &s, sizeof(s));
-+      FN_EXIT0;
-+}
-+
-+void
-+acx_s_cmd_start_scan(wlandevice_t *priv)
-+{
-+      /* time_before check is 'just in case' thing */
-+      if (!(priv->irq_status & HOST_INT_SCAN_COMPLETE)
-+       && time_before(jiffies, priv->scan_start + 10*HZ)
-+      ) {
-+              acxlog(L_INIT, "start_scan: seems like previous scan "
-+              "is still running. Not starting anew. Please report\n");
-+              return;
-+      }
-+
-+      acxlog(L_INIT, "starting radio scan\n");
-+      /* remember that fw is commanded to do scan */
-+      priv->scan_start = jiffies;
-+      CLEAR_BIT(priv->irq_status, HOST_INT_SCAN_COMPLETE);
-+      /* issue it */
-+      if (IS_ACX100(priv)) {
-+              acx100_s_scan_chan(priv);
-+      } else {
-+              acx111_s_scan_chan(priv);
-+      }
-+}
-+
-+
-+/***********************************************************************
-+** acx111 feature config
-+*/
-+static int
-+acx111_s_get_feature_config(wlandevice_t *priv,
-+              u32 *feature_options, u32 *data_flow_options)
-+{
-+      struct acx111_ie_feature_config fc;
-+
-+      if (!IS_ACX111(priv)) {
-+              return NOT_OK;
-+      }
-+
-+      memset(&fc, 0, sizeof(fc));
-+
-+      if (OK != acx_s_interrogate(priv, &fc, ACX1xx_IE_FEATURE_CONFIG)) {
-+              return NOT_OK;
-+      }
-+      acxlog(L_DEBUG,
-+              "got Feature option:0x%X, DataFlow option: 0x%X\n",
-+              fc.feature_options,
-+              fc.data_flow_options);
-+
-+      if (feature_options)
-+              *feature_options = le32_to_cpu(fc.feature_options);
-+      if (data_flow_options)
-+              *data_flow_options = le32_to_cpu(fc.data_flow_options);
-+
-+      return OK;
-+}
-+
-+static int
-+acx111_s_set_feature_config(wlandevice_t *priv,
-+      u32 feature_options, u32 data_flow_options,
-+      unsigned int mode /* 0 == remove, 1 == add, 2 == set */)
-+{
-+      struct acx111_ie_feature_config fc;
-+
-+      if (!IS_ACX111(priv)) {
-+              return NOT_OK;
-+      }
-+
-+      if ((mode < 0) || (mode > 2))
-+              return NOT_OK;
-+
-+      if (mode != 2)
-+              /* need to modify old data */
-+              acx111_s_get_feature_config(priv, &fc.feature_options, &fc.data_flow_options);
-+      else {
-+              /* need to set a completely new value */
-+              fc.feature_options = 0;
-+              fc.data_flow_options = 0;
-+      }
-+
-+      if (mode == 0) { /* remove */
-+              CLEAR_BIT(fc.feature_options, cpu_to_le32(feature_options));
-+              CLEAR_BIT(fc.data_flow_options, cpu_to_le32(data_flow_options));
-+      } else { /* add or set */
-+              SET_BIT(fc.feature_options, cpu_to_le32(feature_options));
-+              SET_BIT(fc.data_flow_options, cpu_to_le32(data_flow_options));
-+      }
-+
-+      acxlog(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(fc.feature_options),
-+              le32_to_cpu(fc.data_flow_options));
-+
-+      if (OK != acx_s_configure(priv, &fc, ACX1xx_IE_FEATURE_CONFIG)) {
-+              return NOT_OK;
-+      }
-+
-+      return OK;
-+}
-+
-+static inline int
-+acx111_s_feature_off(wlandevice_t *priv, u32 f, u32 d)
-+{
-+      return acx111_s_set_feature_config(priv, f, d, 0);
-+}
-+static inline int
-+acx111_s_feature_on(wlandevice_t *priv, u32 f, u32 d)
-+{
-+      return acx111_s_set_feature_config(priv, f, d, 1);
-+}
-+static inline int
-+acx111_s_feature_set(wlandevice_t *priv, u32 f, u32 d)
-+{
-+      return acx111_s_set_feature_config(priv, f, d, 2);
-+}
-+
-+
-+/***********************************************************************
-+** acx100_s_init_memory_pools
-+*/
-+static int
-+acx100_s_init_memory_pools(wlandevice_t *priv, 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(priv->memblocksize);
-+
-+      /* Then we alert the card to our decision of block size */
-+      if (OK != acx_s_configure(priv, &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)) / priv->memblocksize;
-+
-+      acxlog(L_DEBUG, "TotalMemoryBlocks=%u (%u bytes)\n",
-+              TotalMemoryBlocks, TotalMemoryBlocks*priv->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      // use local memory block linked list (else what?)
-+      0x00010000      // use host indirect descriptors (else host must access ACX memory?)
-+      */
-+      if (IS_PCI(priv)) {
-+              MemoryConfigOption.DMA_config = cpu_to_le32(0x30000);
-+              /* Declare start of the Rx host pool */
-+              MemoryConfigOption.pRxHostDesc = cpu2acx(priv->rxhostdesc_startphy);
-+              acxlog(L_DEBUG, "pRxHostDesc 0x%08X, rxhostdesc_startphy 0x%lX\n",
-+                              acx2cpu(MemoryConfigOption.pRxHostDesc),
-+                              (long)priv->rxhostdesc_startphy);
-+      } else {
-+              MemoryConfigOption.DMA_config = cpu_to_le32(0x20000);
-+      }
-+
-+      /* 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 * priv->memblocksize;
-+      TotalRxBlockSize = RxBlockNum * priv->memblocksize;
-+      acxlog(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);
-+      acxlog(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(priv, &MemoryConfigOption, ACX1xx_IE_MEMORY_CONFIG_OPTIONS)) {
-+              goto bad;
-+      }
-+
-+      /* and tell the device to kick it into gear */
-+      if (OK != acx_s_issue_cmd(priv, ACX100_CMD_INIT_MEMORY, NULL, 0)) {
-+              goto bad;
-+      }
-+      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(wlandevice_t *priv)
-+{
-+      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(priv, &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);
-+
-+      acxlog(L_DEBUG, "initializing Queue Indicator\n");
-+
-+      memset(&queueconf, 0, sizeof(queueconf));
-+
-+      /* Not needed for PCI, so we can avoid setting them altogether */
-+      if (IS_USB(priv)) {
-+              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(priv, &queueconf, ACX1xx_IE_QUEUE_CONFIG)) {
-+              goto fail;
-+      }
-+
-+#if 0
-+      if (IS_PCI(priv)) {
-+      /* sets the beginning of the rx descriptor queue, after the tx descrs */
-+              if (OK != acx_s_create_hostdesc_queues(priv))
-+                      goto fail;
-+              acx_create_desc_queues(priv, tx_queue_start, rx_queue_start);
-+      }
-+#endif
-+
-+      if (OK != acx_s_interrogate(priv, &memmap, ACX1xx_IE_MEMORY_MAP)) {
-+              goto fail;
-+      }
-+
-+      memmap.PoolStart = cpu_to_le32(
-+                      (le32_to_cpu(memmap.QueueEnd) + 4 + 0x1f) & ~0x1f
-+                      );
-+
-+      if (OK != acx_s_configure(priv, &memmap, ACX1xx_IE_MEMORY_MAP)) {
-+              goto fail;
-+      }
-+
-+      if (OK != acx100_s_init_memory_pools(priv, &memmap)) {
-+              goto fail;
-+      }
-+
-+      res = OK;
-+      goto end;
-+
-+fail:
-+      acx_s_msleep(1000); /* ? */
-+      if (IS_PCI(priv))
-+              acx_free_desc_queues(priv);
-+end:
-+      FN_EXIT1(res);
-+      return res;
-+}
-+
-+
-+/***********************************************************************
-+** acx111_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
-+*/
-+#define ACX111_PERCENT(percent) ((percent)/5)
-+
-+static int
-+acx111_s_create_dma_regions(wlandevice_t *priv)
-+{
-+      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 (IS_PCI(priv)) {
-+              if (OK != acx_s_create_hostdesc_queues(priv))
-+                      goto fail;
-+      }
-+
-+      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(priv->sta_list));
-+      /* specify the memory block size. Default is 256 */
-+      memconf.memory_block_size = cpu_to_le16(priv->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 (IS_PCI(priv)) {
-+              memconf.rx_queue1_host_rx_start = cpu2acx(priv->rxhostdesc_startphy);
-+      }
-+      /* 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(priv, &memconf, ACX1xx_IE_QUEUE_CONFIG)) {
-+              goto fail;
-+      }
-+
-+      acx_s_interrogate(priv, &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);
-+
-+      acxlog(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 (IS_PCI(priv))
-+              acx_create_desc_queues(priv, tx_queue_start, rx_queue_start);
-+
-+      FN_EXIT1(OK);
-+      return OK;
-+fail:
-+      if (IS_PCI(priv))
-+              acx_free_desc_queues(priv);
-+
-+      FN_EXIT1(NOT_OK);
-+      return NOT_OK;
-+}
-+
-+
-+/***********************************************************************
-+** acx_s_set_defaults
-+** Called from acx_s_init_mac
-+*/
-+int
-+acx_s_set_defaults(wlandevice_t *priv)
-+{
-+      unsigned long flags;
-+
-+      FN_ENTER;
-+
-+      /* 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!! */
-+      priv->get_mask = GETSET_ANTENNA|GETSET_SENSITIVITY|GETSET_STATION_ID|GETSET_REG_DOMAIN;
-+      /* Only ACX100 supports ED and CCA */
-+      if (IS_ACX100(priv))
-+              priv->get_mask |= GETSET_CCA|GETSET_ED_THRESH;
-+
-+      acx_s_update_card_settings(priv, 0, 0);
-+
-+      acx_lock(priv, flags);
-+
-+      /* set our global interrupt mask */
-+      if (IS_PCI(priv))
-+              acx_set_interrupt_mask(priv);
-+
-+      priv->led_power = 1; /* LED is active on startup */
-+      priv->brange_max_quality = 60; /* LED blink max quality is 60 */
-+      priv->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(priv->dev_addr, priv->netdev->dev_addr);
-+      sprintf(priv->essid, "STA%02X%02X%02X",
-+              priv->dev_addr[3], priv->dev_addr[4], priv->dev_addr[5]);
-+      priv->essid_len = sizeof("STAxxxxxx") - 1; /* make sure to adapt if changed above! */
-+      priv->essid_active = 1;
-+
-+      /* we have a nick field to waste, so why not abuse it
-+       * to announce the driver version? ;-) */
-+      strncpy(priv->nick, "acx " WLAN_RELEASE, IW_ESSID_MAX_SIZE);
-+
-+      if (IS_PCI(priv)) {
-+              if (IS_ACX111(priv)) {
-+                      /* Hope this is correct, only tested with domain 0x30 */
-+                      acx_read_eeprom_offset(priv, 0x16F, &priv->reg_dom_id);
-+              } else if (priv->eeprom_version < 5) {
-+                      acx_read_eeprom_offset(priv, 0x16F, &priv->reg_dom_id);
-+              } else {
-+                      acx_read_eeprom_offset(priv, 0x171, &priv->reg_dom_id);
-+              }
-+      }
-+
-+      priv->channel = 1;
-+      /* 0xffff would be better, but then we won't get a "scan complete"
-+       * interrupt, so our current infrastructure will fail: */
-+      priv->scan_count = 1;
-+      priv->scan_mode = ACX_SCAN_OPT_PASSIVE;
-+      /* Doesn't work for acx100, do it only for acx111 for now */
-+      if (IS_ACX111(priv)) {
-+              priv->scan_mode = ACX_SCAN_OPT_ACTIVE;
-+      }
-+      priv->scan_duration = 100;
-+      priv->scan_probe_delay = 200;
-+      priv->scan_rate = ACX_SCAN_RATE_1;
-+
-+      priv->auth_alg = WLAN_AUTH_ALG_OPENSYSTEM;
-+      priv->preamble_mode = 2; /* auto */
-+      priv->listen_interval = 100;
-+      priv->beacon_interval = DEFAULT_BEACON_INTERVAL;
-+      priv->mode = ACX_MODE_2_STA;
-+      priv->dtim_interval = DEFAULT_DTIM_INTERVAL;
-+
-+      priv->msdu_lifetime = DEFAULT_MSDU_LIFETIME;
-+      SET_BIT(priv->set_mask, SET_MSDU_LIFETIME);
-+
-+      priv->rts_threshold = DEFAULT_RTS_THRESHOLD;
-+
-+      /* use standard default values for retry limits */
-+      priv->short_retry = 7; /* max. retries for (short) non-RTS packets */
-+      priv->long_retry = 4; /* max. retries for long (RTS) packets */
-+      SET_BIT(priv->set_mask, GETSET_RETRY);
-+
-+      priv->fallback_threshold = 3;
-+      priv->stepup_threshold = 10;
-+      priv->rate_bcast = RATE111_1;
-+      priv->rate_bcast100 = RATE100_1;
-+      priv->rate_basic = RATE111_1 | RATE111_2;
-+      priv->rate_auto = 1;
-+      if (IS_ACX111(priv)) {
-+              priv->rate_oper = RATE111_ALL;
-+      } else {
-+              priv->rate_oper = RATE111_ACX100_COMPAT;
-+      }
-+
-+      /* configure card to do rate fallback when in auto rate mode. */
-+      SET_BIT(priv->set_mask, SET_RATE_FALLBACK);
-+
-+      /* 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(priv);
-+
-+      priv->capab_short = 0;
-+      priv->capab_pbcc = 1;
-+      priv->capab_agility = 0;
-+
-+      SET_BIT(priv->set_mask, SET_RXCONFIG);
-+
-+      /* set some more defaults */
-+      if (IS_ACX111(priv)) {
-+              /* 30mW (15dBm) is default, at least in my acx111 card: */
-+              priv->tx_level_dbm = 15;
-+      } else {
-+              /* don't use max. level, since it might be dangerous
-+               * (e.g. WRT54G people experience
-+               * excessive Tx power damage!) */
-+              priv->tx_level_dbm = 18;
-+      }
-+      /* priv->tx_level_auto = 1; */
-+      SET_BIT(priv->set_mask, GETSET_TXPOWER);
-+
-+      if (IS_ACX111(priv)) {
-+              /* start with sensitivity level 1 out of 3: */
-+              priv->sensitivity = 1;
-+      }
-+
-+      /* better re-init the antenna value we got above */
-+      SET_BIT(priv->set_mask, GETSET_ANTENNA);
-+
-+      priv->ps_wakeup_cfg = 0;
-+      priv->ps_listen_interval = 0;
-+      priv->ps_options = 0;
-+      priv->ps_hangover_period = 0;
-+      priv->ps_enhanced_transition_time = 0;
-+#ifdef POWER_SAVE_80211
-+      SET_BIT(priv->set_mask, GETSET_POWER_80211);
-+#endif
-+
-+      MAC_BCAST(priv->ap);
-+
-+      acx_unlock(priv, flags);
-+      acx_lock_unhold(); // hold time 844814 CPU ticks @2GHz
-+
-+      acx_s_initialize_rx_config(priv);
-+
-+      FN_EXIT1(OK);
-+      return OK;
-+}
-+
-+
-+/***********************************************************************
-+** 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(wlandevice_t *priv, 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.
-+       * Ideally we would query it here, but we first need a
-+       * standard way to query individual configoptions easily. */
-+      if (level_dbm <= 12) {
-+              tx_level.level = 2; /* 10 dBm */
-+              priv->tx_level_dbm = 10;
-+      } else {
-+              tx_level.level = 1; /* 15 dBm */
-+              priv->tx_level_dbm = 15;
-+      }
-+      if (level_dbm != priv->tx_level_dbm)
-+              acxlog(L_INIT, "acx111 firmware has specific "
-+                      "power levels only: adjusted %d dBm to %d dBm!\n",
-+                      level_dbm, priv->tx_level_dbm);
-+
-+      return acx_s_configure(priv, &tx_level, ACX1xx_IE_DOT11_TX_POWER_LEVEL);
-+}
-+
-+static int
-+acx_s_set_tx_level(wlandevice_t *priv, u8 level_dbm)
-+{
-+      if (IS_ACX111(priv)) {
-+              return acx111_s_set_tx_level(priv, level_dbm);
-+      }
-+      if (IS_PCI(priv)) {
-+              return acx100_s_set_tx_level(priv, level_dbm);
-+      }
-+      return OK;
-+}
-+
-+
-+/***********************************************************************
-+*/
-+#ifdef UNUSED
-+/* Returns the current tx level (ACX111) */
-+static u8
-+acx111_s_get_tx_level(wlandevice_t *priv)
-+{
-+      struct acx111_ie_tx_level tx_level;
-+
-+      tx_level.level = 0;
-+      acx_s_interrogate(priv, &tx_level, ACX1xx_IE_DOT11_TX_POWER_LEVEL);
-+      return tx_level.level;
-+}
-+#endif
-+
-+
-+/***********************************************************************
-+** acx_s_init_mac
-+*/
-+int
-+acx_s_init_mac(netdevice_t *dev)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+      int result = NOT_OK;
-+
-+      FN_ENTER;
-+
-+      if (IS_PCI(priv)) {
-+              priv->memblocksize = 256; /* 256 is default */
-+              acx_init_mboxes(priv);
-+              /* 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 */
-+              acx_s_upload_radio(priv);
-+      } else {
-+              priv->memblocksize = 128;
-+      }
-+
-+      if (IS_ACX111(priv)) {
-+              /* 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 != acx111_s_init_packet_templates(priv))
-+                      goto fail;
-+
-+              if (OK != acx111_s_create_dma_regions(priv)) {
-+                      printk("%s: acx111_create_dma_regions FAILED\n",
-+                                                      dev->name);
-+                      goto fail;
-+              }
-+#ifdef DEBUG_WEP
-+              /* don't decrypt WEP in firmware */
-+              if (OK != acx111_s_feature_on(priv, 0, FEATURE2_SNIFFER))
-+                      goto fail;
-+#endif
-+      } else {
-+              if (OK != acx100_s_init_wep(priv))
-+                      goto fail;
-+              acxlog(L_DEBUG, "between init_wep and init_packet_templates\n");
-+              if (OK != acx100_s_init_packet_templates(priv))
-+                      goto fail;
-+
-+              if (OK != acx100_s_create_dma_regions(priv)) {
-+                      printk("%s: acx100_create_dma_regions FAILED\n",
-+                                                      dev->name);
-+                      goto fail;
-+              }
-+      }
-+
-+      MAC_COPY(dev->dev_addr, priv->dev_addr);
-+      result = OK;
-+
-+fail:
-+      FN_EXIT1(result);
-+      return result;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_l_rxmonitor
-+* Called from IRQ context only
-+*----------------------------------------------------------------*/
-+static void
-+acx_l_rxmonitor(wlandevice_t *priv, 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(priv, rxbuf) - (u8*)rxbuf);
-+      skb_len = RXBUF_BYTES_USED(rxbuf) - payload_offset;
-+
-+      /* sanity check */
-+      if (skb_len > WLAN_A4FR_MAXLEN_WEP) {
-+              printk("%s: monitor mode panic: oversized frame!\n",
-+                              priv->netdev->name);
-+              goto end;
-+      }
-+
-+      if (priv->netdev->type == ARPHRD_IEEE80211_PRISM)
-+              skb_len += sizeof(*msg);
-+
-+      /* allocate skb */
-+      skb = dev_alloc_skb(skb_len);
-+      if (!skb) {
-+              printk("%s: no memory for skb (%u bytes)\n",
-+                              priv->netdev->name, skb_len);
-+              goto end;
-+      }
-+
-+      skb_put(skb, skb_len);
-+
-+              /* when in raw 802.11 mode, just copy frame as-is */
-+      if (priv->netdev->type == ARPHRD_IEEE80211)
-+              datap = skb->data;
-+      else { /* otherwise, emulate prism header */
-+              msg = (wlansniffrm_t*)skb->data;
-+              datap = msg + 1;
-+
-+              msg->msgcode = WLANSNIFFFRM;
-+              msg->msglen = sizeof(*msg);
-+              strncpy(msg->devname, priv->netdev->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 = priv->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;
-+      }
-+
-+      memcpy(datap, ((unsigned char*)rxbuf)+payload_offset, skb_len);
-+
-+      skb->dev = priv->netdev;
-+      skb->dev->last_rx = jiffies;
-+
-+      skb->mac.raw = skb->data;
-+      skb->ip_summed = CHECKSUM_NONE;
-+      skb->pkt_type = PACKET_OTHERHOST;
-+      skb->protocol = htons(ETH_P_80211_RAW);
-+      netif_rx(skb);
-+
-+      priv->stats.rx_packets++;
-+      priv->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. */
-+static inline int
-+acx_l_handle_dup(wlandevice_t *priv, u16 seq)
-+{
-+      if (priv->dup_count) {
-+              priv->nondup_count++;
-+              if (time_after(jiffies, priv->dup_msg_expiry)) {
-+                      /* Log only if more than 1 dup in 64 packets */
-+                      if (priv->nondup_count/64 < priv->dup_count) {
-+                              printk(KERN_INFO "%s: rx: %d DUPs in "
-+                                      "%d packets received in 10 secs\n",
-+                                      priv->netdev->name,
-+                                      priv->dup_count,
-+                                      priv->nondup_count);
-+                      }
-+                      priv->dup_count = 0;
-+                      priv->nondup_count = 0;
-+              }
-+      }
-+      if (unlikely(seq == priv->last_seq_ctrl)) {
-+              if (!priv->dup_count++)
-+                      priv->dup_msg_expiry = jiffies + 10*HZ;
-+              priv->stats.rx_errors++;
-+              return 1; /* a dup */
-+      }
-+      priv->last_seq_ctrl = seq;
-+      return 0;
-+}
-+
-+static int
-+acx_l_rx_ieee802_11_frame(wlandevice_t *priv, rxbuffer_t *rxbuf)
-+{
-+      unsigned int ftype, fstype;
-+      const wlan_hdr_t *hdr;
-+      int result = NOT_OK;
-+
-+      FN_ENTER;
-+
-+      hdr = acx_get_wlan_hdr(priv, rxbuf);
-+
-+      /* see IEEE 802.11-1999.pdf chapter 7 "MAC frame formats" */
-+      if ((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(priv, 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(priv, rxbuf);
-+                              break;
-+                      }
-+                      */
-+
-+                      switch (priv->mode) {
-+                      case ACX_MODE_3_AP:
-+                              result = acx_l_process_data_frame_master(priv, rxbuf);
-+                              break;
-+                      case ACX_MODE_0_ADHOC:
-+                      case ACX_MODE_2_STA:
-+                              result = acx_l_process_data_frame_client(priv, 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(priv, rxbuf, 3); */
-+                      break;
-+              case WF_FSTYPE_NULLi:
-+                      /* acx_l_process_NULL_frame(priv, 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(priv, 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(priv, 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(wlandevice_t *priv, rxbuffer_t *rxbuf)
-+{
-+      struct wlan_hdr *hdr;
-+      unsigned int buf_len;
-+      unsigned int qual;
-+      u16 fc;
-+
-+      hdr = acx_get_wlan_hdr(priv, rxbuf);
-+      /* length of frame from control field to last byte of FCS */
-+      buf_len = RXBUF_BYTES_RCVD(rxbuf);
-+      fc = le16_to_cpu(hdr->fc);
-+
-+      if ( ((WF_FC_FSTYPE & fc) != WF_FSTYPE_BEACON)
-+        || (acx_debug & L_XFER_BEACON)
-+      ) {
-+              acxlog(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,
-+                      priv->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(priv->mode == ACX_MODE_MONITOR)) {
-+              acx_l_rxmonitor(priv, rxbuf);
-+      } else if (likely(buf_len >= WLAN_HDR_A3_LEN)) {
-+              acx_l_rx_ieee802_11_frame(priv, rxbuf);
-+      } else {
-+              acxlog(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 (priv->ap_client
-+       && mac_is_equal(hdr->a2, priv->ap_client->address)) {
-+#endif
-+              priv->wstats.qual.level = acx_signal_to_winlevel(rxbuf->phy_level);
-+              priv->wstats.qual.noise = acx_signal_to_winlevel(rxbuf->phy_snr);
-+#ifndef OLD_QUALITY
-+              qual = acx_signal_determine_quality(priv->wstats.qual.level,
-+                              priv->wstats.qual.noise);
-+#else
-+              qual = (priv->wstats.qual.noise <= 100) ?
-+                              100 - priv->wstats.qual.noise : 0;
-+#endif
-+              priv->wstats.qual.qual = qual;
-+              priv->wstats.qual.updated = 7; /* all 3 indicators updated */
-+#ifdef FROM_SCAN_SOURCE_ONLY
-+      }
-+#endif
-+}
-+
-+
-+/***********************************************************************
-+** acx_i_start_xmit
-+**
-+** Called by network core. Can be called outside of process context.
-+*/
-+int
-+acx_i_start_xmit(struct sk_buff *skb, netdevice_t *dev)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+      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(!priv)) {
-+              goto end_no_unlock;
-+      }
-+
-+      acx_lock(priv, flags);
-+
-+      if (unlikely(!(priv->dev_state_mask & ACX_STATE_IFACE_UP))) {
-+              goto end;
-+      }
-+      if (unlikely(priv->mode == ACX_MODE_OFF)) {
-+              goto end;
-+      }
-+      if (unlikely(acx_queue_stopped(dev))) {
-+              acxlog(L_DEBUG, "%s: called when queue stopped\n", __func__);
-+              goto end;
-+      }
-+      if (unlikely(ACX_STATUS_4_ASSOCIATED != priv->status)) {
-+              acxlog(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 */
-+              priv->stats.tx_errors++;
-+              goto end;
-+      }
-+
-+      tx = acx_l_alloc_tx(priv);
-+      if (unlikely(!tx)) {
-+              printk("%s: start_xmit: txdesc ring is full, dropping tx\n",
-+                      dev->name);
-+              txresult = NOT_OK;
-+              goto end;
-+      }
-+
-+      txbuf = acx_l_get_txbuf(priv, tx);
-+      if (!txbuf) {
-+              /* Card was removed */
-+              txresult = NOT_OK;
-+              goto end;
-+      }
-+      len = acx_l_ether_to_txbuf(priv, txbuf, skb);
-+      if (len < 0) {
-+              /* Error in packet conversion */
-+              txresult = NOT_OK;
-+              goto end;
-+      }
-+      acx_l_tx_data(priv, tx, len);
-+      dev->trans_start = jiffies;
-+
-+      txresult = OK;
-+      priv->stats.tx_packets++;
-+      priv->stats.tx_bytes += skb->len;
-+
-+end:
-+      acx_unlock(priv, flags);
-+
-+end_no_unlock:
-+      if ((txresult == OK) && skb)
-+              dev_kfree_skb_any(skb);
-+
-+      FN_EXIT1(txresult);
-+      return txresult;
-+}
-+
-+
-+/***********************************************************************
-+** acx_l_update_ratevector
-+**
-+** Updates priv->rate_supported[_len] according to rate_{basic,oper}
-+*/
-+const u8
-+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(wlandevice_t *priv)
-+{
-+      u16 bcfg = priv->rate_basic;
-+      u16 ocfg = priv->rate_oper;
-+      u8 *supp = priv->rate_supported;
-+      const u8 *dot11 = bitpos2ratebyte;
-+
-+      FN_ENTER;
-+
-+      while (ocfg) {
-+              if (ocfg & 1) {
-+                      *supp = *dot11;
-+                      if (bcfg & 1) {
-+                              *supp |= 0x80;
-+                      }
-+                      supp++;
-+              }
-+              dot11++;
-+              ocfg >>= 1;
-+              bcfg >>= 1;
-+      }
-+      priv->rate_supported_len = supp - priv->rate_supported;
-+      if (acx_debug & L_ASSOC) {
-+              printk("new ratevector: ");
-+              acx_dump_bytes(priv->rate_supported, priv->rate_supported_len);
-+      }
-+      FN_EXIT0;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_l_sta_list_init
-+*----------------------------------------------------------------*/
-+static void
-+acx_l_sta_list_init(wlandevice_t *priv)
-+{
-+      FN_ENTER;
-+      memset(priv->sta_hash_tab, 0, sizeof(priv->sta_hash_tab));
-+      memset(priv->sta_list, 0, sizeof(priv->sta_list));
-+      FN_EXIT0;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_l_sta_list_get_from_hash
-+*----------------------------------------------------------------*/
-+static inline client_t*
-+acx_l_sta_list_get_from_hash(wlandevice_t *priv, const u8 *address)
-+{
-+      return priv->sta_hash_tab[address[5] % VEC_SIZE(priv->sta_hash_tab)];
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_l_sta_list_get
-+*----------------------------------------------------------------*/
-+client_t*
-+acx_l_sta_list_get(wlandevice_t *priv, const u8 *address)
-+{
-+      client_t *client;
-+      FN_ENTER;
-+      client = acx_l_sta_list_get_from_hash(priv, 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(wlandevice_t *priv, client_t *victim)
-+{
-+      client_t *client, *next;
-+
-+      client = acx_l_sta_list_get_from_hash(priv, 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(wlandevice_t *priv)
-+{
-+      int i;
-+      unsigned long age, oldest_age;
-+      client_t *client, *oldest;
-+
-+      FN_ENTER;
-+
-+      oldest = &priv->sta_list[0];
-+      oldest_age = 0;
-+      for (i = 0; i < VEC_SIZE(priv->sta_list); i++) {
-+              client = &priv->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(priv, 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(wlandevice_t *priv, const u8 *address)
-+{
-+      client_t *client;
-+      int index;
-+
-+      FN_ENTER;
-+
-+      client = acx_l_sta_list_alloc(priv);
-+
-+      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 = priv->rate_basic;
-+      client->rate_cfg = priv->rate_basic;
-+      client->rate_cur = 1 << lowest_bit(priv->rate_basic);
-+
-+      index = address[5] % VEC_SIZE(priv->sta_hash_tab);
-+      client->next = priv->sta_hash_tab[index];
-+      priv->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(wlandevice_t *priv, const u8 *address)
-+{
-+      client_t *client = acx_l_sta_list_get(priv, address);
-+      if (!client)
-+              client = acx_l_sta_list_add(priv, 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(wlandevice_t *priv, u16 new_status)
-+{
-+#define QUEUE_OPEN_AFTER_ASSOC 1 /* this really seems to be needed now */
-+      u16 old_status = priv->status;
-+
-+      FN_ENTER;
-+
-+      acxlog(L_ASSOC, "%s(%d):%s\n",
-+             __func__, new_status, acx_get_status_name(new_status));
-+
-+#if WIRELESS_EXT > 13 /* wireless_send_event() and SIOCGIWSCAN */
-+      /* 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(priv->netdev, SIOCGIWSCAN, &wrqu, NULL);
-+
-+              wrqu.data.length = 0;
-+              wrqu.data.flags = 0;
-+              MAC_COPY(wrqu.ap_addr.sa_data, priv->bssid);
-+              wrqu.ap_addr.sa_family = ARPHRD_ETHER;
-+              wireless_send_event(priv->netdev, 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(priv->netdev, SIOCGIWAP, &wrqu, NULL);
-+      }
-+#endif
-+
-+      priv->status = new_status;
-+
-+      switch (new_status) {
-+      case ACX_STATUS_1_SCANNING:
-+              priv->scan_retries = 0;
-+              /* 1.0 s initial scan time */
-+              acx_set_timer(priv, 1000000);
-+              break;
-+      case ACX_STATUS_2_WAIT_AUTH:
-+      case ACX_STATUS_3_AUTHENTICATED:
-+              priv->auth_or_assoc_retries = 0;
-+              acx_set_timer(priv, 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(priv->netdev, "after association");
-+                      acx_wake_queue(priv->netdev, "after association");
-+              }
-+      } else {
-+              /* not associated any more, so let's kill carrier */
-+              if (old_status >= ACX_STATUS_4_ASSOCIATED) {
-+                      acx_carrier_off(priv->netdev, "after losing association");
-+                      acx_stop_queue(priv->netdev, "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;
-+      wlandevice_t *priv = (wlandevice_t *)address;
-+
-+      FN_ENTER;
-+
-+      acx_lock(priv, flags);
-+
-+      acxlog(L_DEBUG|L_ASSOC, "%s: priv->status=%d (%s)\n",
-+              __func__, priv->status, acx_get_status_name(priv->status));
-+
-+      switch (priv->status) {
-+      case ACX_STATUS_1_SCANNING:
-+              /* was set to 0 by set_status() */
-+              if (++priv->scan_retries < 7) {
-+                      acx_set_timer(priv, 1000000);
-+                      /* used to interrogate for scan status.
-+                      ** We rely on SCAN_COMPLETE IRQ instead */
-+                      acxlog(L_ASSOC, "continuing scan (%d sec)\n",
-+                                      priv->scan_retries);
-+              } else {
-+                      acxlog(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_after_interrupt_task(priv,
-+                              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 (++priv->auth_or_assoc_retries < 10) {
-+                      acxlog(L_ASSOC, "resend authen1 request (attempt %d)\n",
-+                                      priv->auth_or_assoc_retries + 1);
-+                      acx_l_transmit_authen1(priv);
-+              } else {
-+                      /* time exceeded: fall back to scanning mode */
-+                      acxlog(L_ASSOC,
-+                             "authen1 request reply timeout, giving up\n");
-+                      /* we are a STA, need to find AP anyhow */
-+                      acx_set_status(priv, ACX_STATUS_1_SCANNING);
-+                      acx_schedule_after_interrupt_task(priv, ACX_AFTER_IRQ_RESTART_SCAN);
-+              }
-+              /* used to be 1500000, but some other driver uses 2.5s */
-+              acx_set_timer(priv, 2500000);
-+              break;
-+      case ACX_STATUS_3_AUTHENTICATED:
-+              /* was set to 0 by set_status() */
-+              if (++priv->auth_or_assoc_retries < 10) {
-+                      acxlog(L_ASSOC, "resend assoc request (attempt %d)\n",
-+                                      priv->auth_or_assoc_retries + 1);
-+                      acx_l_transmit_assoc_req(priv);
-+              } else {
-+                      /* time exceeded: give up */
-+                      acxlog(L_ASSOC,
-+                              "association request reply timeout, giving up\n");
-+                      /* we are a STA, need to find AP anyhow */
-+                      acx_set_status(priv, ACX_STATUS_1_SCANNING);
-+                      acx_schedule_after_interrupt_task(priv, ACX_AFTER_IRQ_RESTART_SCAN);
-+              }
-+              acx_set_timer(priv, 2500000); /* see above */
-+              break;
-+      case ACX_STATUS_4_ASSOCIATED:
-+      default:
-+              break;
-+      }
-+
-+      acx_unlock(priv, flags);
-+
-+      FN_EXIT0;
-+}
-+
-+
-+/*------------------------------------------------------------------------------
-+ * acx_set_timer
-+ *
-+ * Sets the 802.11 state management timer's timeout.
-+ *----------------------------------------------------------------------------*/
-+void
-+acx_set_timer(wlandevice_t *priv, int timeout_us)
-+{
-+      FN_ENTER;
-+
-+      acxlog(L_DEBUG|L_IRQ, "%s(%u ms)\n", __func__, timeout_us/1000);
-+      if (!(priv->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 (priv->mgmt_timer.function) {
-+              mod_timer(&priv->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 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(wlandevice_t *priv, 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(priv, 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(priv, da, WLAN_MGMT_REASON_CLASS2_NONAUTH);
-+              goto bad;
-+      }
-+
-+      clt->used = CLIENT_ASSOCIATED_3;
-+
-+      if (clt->aid == 0) {
-+              clt->aid = ++priv->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 & priv->rate_oper;
-+      if (!clt->rate_cfg) clt->rate_cfg = 1 << lowest_bit(priv->rate_oper);
-+      clt->rate_cur = 1 << lowest_bit(clt->rate_cfg);
-+      clt->fallback_count = clt->stepup_count = 0;
-+      clt->ignore_count = 16;
-+
-+      tx = acx_l_alloc_tx(priv);
-+      if (!tx)
-+              goto bad;
-+      head = acx_l_get_txbuf(priv, tx);
-+      if (!head)
-+              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, sa); */
-+      MAC_COPY(head->sa, priv->dev_addr);
-+      MAC_COPY(head->bssid, bssid);
-+      head->seq = req->hdr->seq;
-+
-+      body->cap_info = host2ieee16(priv->capabilities);
-+      body->status = host2ieee16(0);
-+      body->aid = host2ieee16(clt->aid);
-+      p = wlan_fill_ie_rates((u8*)&body->rates, priv->rate_supported_len,
-+                                                      priv->rate_supported);
-+      p = wlan_fill_ie_rates_ext(p, priv->rate_supported_len,
-+                                                      priv->rate_supported);
-+
-+      acx_l_tx_data(priv, 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 a hell is ReAuth.
-+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(wlandevice_t *priv, 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(priv, 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(priv, da, WLAN_MGMT_REASON_CLASS2_NONAUTH);
-+              goto bad;
-+      }
-+
-+      clt->used = CLIENT_ASSOCIATED_3;
-+      if (clt->aid == 0) {
-+              clt->aid = ++priv->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 & priv->rate_oper;
-+      if (!clt->rate_cfg) clt->rate_cfg = 1 << lowest_bit(priv->rate_oper);
-+      clt->rate_cur = 1 << lowest_bit(clt->rate_cfg);
-+      clt->fallback_count = clt->stepup_count = 0;
-+      clt->ignore_count = 16;
-+
-+      tx = acx_l_alloc_tx(priv);
-+      if (!tx)
-+              goto ok;
-+      head = acx_l_get_txbuf(priv, tx);
-+      if (!head)
-+              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, sa); */
-+      MAC_COPY(head->sa, priv->dev_addr);
-+      MAC_COPY(head->bssid, bssid);
-+      head->seq = req->hdr->seq;
-+
-+      /* IEs: 1. caps */
-+      body->cap_info = host2ieee16(priv->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, priv->rate_supported_len,
-+                                                      priv->rate_supported);
-+      /* 5. ext supp rates */
-+      p = wlan_fill_ie_rates_ext(p, priv->rate_supported_len,
-+                                                      priv->rate_supported);
-+
-+      acx_l_tx_data(priv, 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(wlandevice_t *priv, const wlan_fr_disassoc_t *req)
-+{
-+      const u8 *ta;
-+      client_t *clt;
-+
-+      FN_ENTER;
-+
-+      ta = req->hdr->a2;
-+      clt = acx_l_sta_list_get(priv, 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(priv, 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(wlandevice_t *priv, 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("DEAUTHEN priv->addr=", priv->dev_addr, " ");
-+              acx_print_mac("a1", hdr->a1, " ");
-+              acx_print_mac("a2", hdr->a2, " ");
-+              acx_print_mac("a3", hdr->a3, " ");
-+              acx_print_mac("priv->bssid", priv->bssid, "\n");
-+      }
-+
-+      if (!mac_is_equal(priv->dev_addr, hdr->a1)) {
-+              goto end;
-+      }
-+
-+      acxlog_mac(L_DEBUG, "STA ", hdr->a2, " sent us deauthen packet\n");
-+
-+      client = acx_l_sta_list_get(priv, 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(wlandevice_t *priv, const wlan_fr_disassoc_t *req)
-+{
-+      FN_ENTER;
-+
-+      if (!priv->ap_client) {
-+              /* Hrm, we aren't assoc'ed yet anyhow... */
-+              goto end;
-+      }
-+      if (mac_is_equal(priv->dev_addr, req->hdr->a1)) {
-+              acx_l_transmit_deauthen(priv, priv->bssid,
-+                              WLAN_MGMT_REASON_DEAUTH_LEAVING);
-+              /* Start scan anew */
-+              SET_BIT(priv->set_mask, GETSET_RESCAN);
-+              acx_schedule_after_interrupt_task(priv, ACX_AFTER_IRQ_UPDATE_CARD_CFG);
-+      }
-+end:
-+      FN_EXIT0;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_l_process_deauth_from_ap
-+*----------------------------------------------------------------*/
-+static void
-+acx_l_process_deauth_from_ap(wlandevice_t *priv, const wlan_fr_deauthen_t *req)
-+{
-+      FN_ENTER;
-+
-+      if (!priv->ap_client) {
-+              /* Hrm, we aren't assoc'ed yet anyhow... */
-+              goto end;
-+      }
-+      /* Chk: is ta is verified to be from our AP? */
-+      if (mac_is_equal(priv->dev_addr, req->hdr->a1)) {
-+              acxlog(L_DEBUG, "AP sent us deauth packet\n");
-+              /* not needed: acx_set_status(priv, ACX_STATUS_1_SCANNING) */
-+              SET_BIT(priv->set_mask, GETSET_RESCAN);
-+              acx_schedule_after_interrupt_task(priv, 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().
-+ *
-+ * Arguments:
-+ *    rxdesc: the rxhostdesc to pull the data from
-+ *    priv:   the acx100 private struct of the interface
-+ *----------------------------------------------------------------------------*/
-+static void
-+acx_l_rx(wlandevice_t *priv, rxbuffer_t *rxbuf)
-+{
-+      FN_ENTER;
-+      if (likely(priv->dev_state_mask & ACX_STATE_IFACE_UP)) {
-+              struct sk_buff *skb;
-+              skb = acx_rxbuf_to_ether(priv, rxbuf);
-+              if (likely(skb)) {
-+                      netif_rx(skb);
-+                      priv->netdev->last_rx = jiffies;
-+                      priv->stats.rx_packets++;
-+                      priv->stats.rx_bytes += skb->len;
-+              }
-+      }
-+      FN_EXIT0;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_l_process_data_frame_master
-+*----------------------------------------------------------------*/
-+static int
-+acx_l_process_data_frame_master(wlandevice_t *priv, 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(priv, rxbuf);
-+
-+      switch (WF_FC_FROMTODSi & hdr->fc) {
-+      case 0:
-+      case WF_FC_FROMDSi:
-+              acxlog(L_DEBUG, "ap->sta or adhoc->adhoc data frame ignored\n");
-+              goto done;
-+      case WF_FC_TODSi:
-+              break;
-+      default: /* WF_FC_FROMTODSi */
-+              acxlog(L_DEBUG, "wds data frame ignored (todo)\n");
-+              goto done;
-+      }
-+
-+      /* check if it is our BSSID, if not, leave */
-+      if (!mac_is_equal(priv->bssid, hdr->a1)) {
-+              goto done;
-+      }
-+
-+      if (mac_is_equal(priv->dev_addr, hdr->a3)) {
-+              /* this one is for us */
-+              acx_l_rx(priv, rxbuf);
-+      } else {
-+              if (mac_is_bcast(hdr->a3)) {
-+                      /* this one is bcast, rx it too */
-+                      acx_l_rx(priv, rxbuf);
-+              }
-+              tx = acx_l_alloc_tx(priv);
-+              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, priv->bssid);
-+              /* To_DS = 0, From_DS = 1 */
-+              hdr->fc = WF_FC_FROMDSi + WF_FTYPE_DATAi;
-+
-+              len = RXBUF_BYTES_RCVD(rxbuf);
-+              txbuf = acx_l_get_txbuf(priv, tx);
-+              if (txbuf) {
-+                      memcpy(txbuf, &rxbuf->hdr_a3, len);
-+                      acx_l_tx_data(priv, tx, len);
-+              }
-+      }
-+done:
-+      result = OK;
-+fail:
-+      FN_EXIT1(result);
-+      return result;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_l_process_data_frame_client
-+*----------------------------------------------------------------*/
-+static int
-+acx_l_process_data_frame_client(wlandevice_t *priv, rxbuffer_t *rxbuf)
-+{
-+      const u8 *da, *bssid;
-+      const wlan_hdr_t *hdr;
-+      netdevice_t *dev = priv->netdev;
-+      int result = NOT_OK;
-+
-+      FN_ENTER;
-+
-+      if (ACX_STATUS_4_ASSOCIATED != priv->status)
-+              goto drop;
-+
-+      hdr = acx_get_wlan_hdr(priv, rxbuf);
-+
-+      switch (WF_FC_FROMTODSi & hdr->fc) {
-+      case 0:
-+              if (priv->mode != ACX_MODE_0_ADHOC) {
-+                      acxlog(L_DEBUG, "adhoc->adhoc data frame ignored\n");
-+                      goto drop;
-+              }
-+              bssid = hdr->a3;
-+              break;
-+      case WF_FC_FROMDSi:
-+              if (priv->mode != ACX_MODE_2_STA) {
-+                      acxlog(L_DEBUG, "ap->sta data frame ignored\n");
-+                      goto drop;
-+              }
-+              bssid = hdr->a2;
-+              break;
-+      case WF_FC_TODSi:
-+              acxlog(L_DEBUG, "sta->ap data frame ignored\n");
-+              goto drop;
-+      default: /* WF_FC_FROMTODSi: wds->wds */
-+              acxlog(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(" priv->bssid=", priv->bssid, "");
-+              acx_print_mac(" priv->addr=", priv->dev_addr, "\n");
-+      }
-+
-+      /* promiscuous mode --> receive all packets */
-+      if (unlikely(dev->flags & IFF_PROMISC))
-+              goto process;
-+
-+      /* FIRST, check if it is our BSSID */
-+      if (!mac_is_equal(priv->bssid, bssid)) {
-+              /* is not our BSSID, so bail out */
-+              goto drop;
-+      }
-+
-+      /* then, check if it is our address */
-+      if (mac_is_equal(priv->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 (dev->flags & IFF_ALLMULTI)
-+                      goto process;
-+
-+              /* FIXME: check against the list of
-+               * multicast addresses that are configured
-+               * for the interface (ifconfig) */
-+              acxlog(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;
-+      }
-+
-+      acxlog(L_DEBUG, "rx: foreign packet, dropping\n");
-+      goto drop;
-+process:
-+      /* receive packet */
-+      acx_l_rx(priv, 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.
-+* NB: wlan_mgmt_decode_XXX are dev-independent (shoudnt have been named acx_XXX)
-+*----------------------------------------------------------------*/
-+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(wlandevice_t *priv, 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(priv, rxbuf);
-+
-+      /* Management frames never have these set */
-+      if (WF_FC_FROMTODSi & hdr->fc) {
-+              FN_EXIT1(NOT_OK);
-+              return NOT_OK;
-+      }
-+
-+      len = RXBUF_BYTES_RCVD(rxbuf);
-+      if (WF_FC_ISWEPi & hdr->fc)
-+              len -= 0x10;
-+
-+      adhoc = (priv->mode == ACX_MODE_0_ADHOC);
-+      sta_scan = ((priv->mode == ACX_MODE_2_STA)
-+               && (priv->status != ACX_STATUS_4_ASSOCIATED));
-+      sta = ((priv->mode == ACX_MODE_2_STA)
-+          && (priv->status == ACX_STATUS_4_ASSOCIATED));
-+      ap = (priv->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(priv, &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, priv->bssid)
-+               && mac_is_equal(hdr->a3, priv->bssid)) {
-+                      acx_l_transmit_assocresp(priv, &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(priv, &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(priv, &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(priv, &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(priv, &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(priv, &parsed.disassoc);
-+              else
-+                      acx_l_process_disassoc_from_sta(priv, &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(priv, &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(priv, &parsed.deauthen);
-+              else
-+                      acx_l_process_deauth_from_sta(priv, &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(wlandevice_t *priv, 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(wlandevice_t *priv, 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(priv, 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(priv, ebx);
-+      if (client)
-+              result = NOT_OK;
-+      else {
-+#ifdef IS_IT_BROKEN
-+              acxlog(L_DEBUG|L_XFER, "<transmit_deauth 7>\n");
-+              acx_l_transmit_deauthen(priv, ebx,
-+                      WLAN_MGMT_REASON_CLASS2_NONAUTH);
-+#else
-+              acxlog(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(wlandevice_t *priv, 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, priv->dev_addr)) {
-+              acxlog(L_ASSOC, "huh, scan found our own MAC!?\n");
-+              goto ok; /* just skip this one silently */
-+      }
-+
-+      bss = acx_l_sta_list_get_or_add(priv, hdr->a2);
-+
-+      /* NB: be careful modifying bss data! It may be one
-+      ** of already known clients (like our AP is 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_after_interrupt_task(priv, ACX_AFTER_IRQ_CMD_STOP_SCAN);
-+              /* TODO: a nice comment what below call achieves --vda */
-+              acx_set_status(priv, 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",
-+                                                  priv->netdev->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 = priv->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 */
-+      acxlog(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(wlandevice_t *priv, const wlan_fr_assocresp_t *req)
-+{
-+      const wlan_hdr_t *hdr;
-+      int res = OK;
-+
-+      FN_ENTER;
-+      hdr = req->hdr;
-+
-+      if ((ACX_MODE_2_STA == priv->mode)
-+       && mac_is_equal(priv->dev_addr, hdr->a1)) {
-+              u16 st = ieee2host16(*(req->status));
-+              if (WLAN_MGMT_STATUS_SUCCESS == st) {
-+                      priv->aid = ieee2host16(*(req->aid));
-+                      /* tell the card we are associated when we are out of interrupt context */
-+                      acx_schedule_after_interrupt_task(priv, ACX_AFTER_IRQ_CMD_ASSOCIATE);
-+              } else {
-+
-+                      /* TODO: we shall delete peer from sta_list, and try other candidates... */
-+
-+                      printk("%s: association FAILED: peer sent "
-+                              "response code %d (%s)\n",
-+                              priv->netdev->name, st, get_status_string(st));
-+                      res = NOT_OK;
-+              }
-+      }
-+
-+      FN_EXIT1(res);
-+      return res;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_l_process_reassocresp
-+*----------------------------------------------------------------*/
-+static int
-+acx_l_process_reassocresp(wlandevice_t *priv, 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(priv->dev_addr, hdr->a1)) {
-+              goto end;
-+      }
-+      st = ieee2host16(*(req->status));
-+      if (st == WLAN_MGMT_STATUS_SUCCESS) {
-+              acx_set_status(priv, ACX_STATUS_4_ASSOCIATED);
-+              result = OK;
-+      } else {
-+              printk("%s: reassociation FAILED: peer sent "
-+                      "response code %d (%s)\n",
-+                      priv->netdev->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(wlandevice_t *priv, 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 priv->addr=", priv->dev_addr, " ");
-+              acx_print_mac("a1=", hdr->a1, " ");
-+              acx_print_mac("a2=", hdr->a2, " ");
-+              acx_print_mac("a3=", hdr->a3, " ");
-+              acx_print_mac("priv->bssid=", priv->bssid, "\n");
-+      }
-+
-+      if (!mac_is_equal(priv->dev_addr, hdr->a1)
-+       || !mac_is_equal(priv->bssid, hdr->a3)) {
-+              result = OK;
-+              goto end;
-+      }
-+
-+      alg = ieee2host16(*(req->auth_alg));
-+      seq = ieee2host16(*(req->auth_seq));
-+      status = ieee2host16(*(req->status));
-+
-+      ap = (priv->mode == ACX_MODE_3_AP);
-+
-+      if (priv->auth_alg <= 1) {
-+              if (priv->auth_alg != alg) {
-+                      acxlog(L_ASSOC, "authentication algorithm mismatch: "
-+                              "want: %d, req: %d\n", priv->auth_alg, alg);
-+                      result = NOT_OK;
-+                      goto end;
-+              }
-+      }
-+      acxlog(L_ASSOC, "algorithm is ok\n");
-+
-+      if (ap) {
-+              clt = acx_l_sta_list_get_or_add(priv, hdr->a2);
-+              if (STA_LIST_ADD_CAN_FAIL && !clt) {
-+                      acxlog(L_ASSOC, "could not allocate room for client\n");
-+                      result = NOT_OK;
-+                      goto end;
-+              }
-+      } else {
-+              clt = priv->ap_client;
-+              if (!mac_is_equal(clt->address, hdr->a2)) {
-+                      printk("%s: malformed auth frame from AP?!\n",
-+                                      priv->netdev->name);
-+                      result = NOT_OK;
-+                      goto end;
-+              }
-+      }
-+
-+      /* now check which step in the authentication sequence we are
-+       * currently in, and act accordingly */
-+      acxlog(L_ASSOC, "acx_process_authen auth seq step %d\n", seq);
-+      switch (seq) {
-+      case 1:
-+              if (!ap)
-+                      break;
-+              acx_l_transmit_authen2(priv, req, clt);
-+              break;
-+      case 2:
-+              if (ap)
-+                      break;
-+              if (status == WLAN_MGMT_STATUS_SUCCESS) {
-+                      if (alg == WLAN_AUTH_ALG_OPENSYSTEM) {
-+                              acx_set_status(priv, ACX_STATUS_3_AUTHENTICATED);
-+                              acx_l_transmit_assoc_req(priv);
-+                      } else
-+                      if (alg == WLAN_AUTH_ALG_SHAREDKEY) {
-+                              acx_l_transmit_authen3(priv, req);
-+                      }
-+              } else {
-+                      printk("%s: auth FAILED: peer sent "
-+                              "response code %d (%s), "
-+                              "still waiting for authentication\n",
-+                              priv->netdev->name,
-+                              status, get_status_string(status));
-+                      acx_set_status(priv, 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(priv, 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(priv, ACX_STATUS_3_AUTHENTICATED);
-+              acxlog(L_ASSOC, "Authenticated!\n");
-+              /* now that we're authenticated, request association */
-+              acx_l_transmit_assoc_req(priv);
-+              break;
-+      }
-+      result = NOT_OK;
-+end:
-+      FN_EXIT1(result);
-+      return result;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_gen_challenge
-+*----------------------------------------------------------------*/
-+static 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(wlandevice_t *priv, 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(priv);
-+      if (!tx)
-+              goto bad;
-+      head = acx_l_get_txbuf(priv, tx);
-+      if (!head)
-+              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, priv->dev_addr);
-+      MAC_COPY(head->bssid, priv->bssid);
-+      head->seq = 0;
-+
-+      acxlog(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(priv, 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(wlandevice_t *priv)
-+{
-+      struct tx *tx;
-+      struct wlan_hdr_mgmt *head;
-+      struct auth_frame_body *body;
-+
-+      FN_ENTER;
-+
-+      acxlog(L_ASSOC, "Sending authentication1 request, "
-+              "awaiting response!\n");
-+
-+      tx = acx_l_alloc_tx(priv);
-+      if (!tx)
-+              goto bad;
-+      head = acx_l_get_txbuf(priv, tx);
-+      if (!head)
-+              goto bad;
-+      body = (void*)(head + 1);
-+
-+      head->fc = WF_FSTYPE_AUTHENi;
-+      head->dur = host2ieee16(0x8000);
-+      MAC_COPY(head->da, priv->bssid);
-+      MAC_COPY(head->sa, priv->dev_addr);
-+      MAC_COPY(head->bssid, priv->bssid);
-+      head->seq = 0;
-+
-+      body->auth_alg = host2ieee16(priv->auth_alg);
-+      body->auth_seq = host2ieee16(1);
-+      body->status = host2ieee16(0);
-+
-+      acx_l_tx_data(priv, 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(wlandevice_t *priv, 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(priv);
-+      if (!tx)
-+              goto bad;
-+      head = acx_l_get_txbuf(priv, tx);
-+      if (!head)
-+              goto bad;
-+      body = (void*)(head + 1);
-+
-+      head->fc = WF_FSTYPE_AUTHENi; /* 0xb0 */
-+      head->dur = req->hdr->dur;
-+      MAC_COPY(head->da, req->hdr->a2);
-+      /* MAC_COPY(head->sa, req->hdr->a1); */
-+      MAC_COPY(head->sa, priv->dev_addr);
-+      MAC_COPY(head->bssid, req->hdr->a3);
-+      head->seq = 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(priv, 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(wlandevice_t *priv, 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(priv);
-+      if (!tx)
-+              goto ok;
-+      head = acx_l_get_txbuf(priv, tx);
-+      if (!head)
-+              goto ok;
-+      body = (void*)(head + 1);
-+
-+      head->fc = WF_FC_ISWEPi + WF_FSTYPE_AUTHENi;
-+      /* FIXME: is this needed?? authen4 does it...
-+      head->dur = req->hdr->dur;
-+      head->seq = req->hdr->seq;
-+      */
-+      MAC_COPY(head->da, priv->bssid);
-+      MAC_COPY(head->sa, priv->dev_addr);
-+      MAC_COPY(head->bssid, priv->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;
-+
-+      acxlog(L_ASSOC|L_XFER, "transmit_authen3!\n");
-+
-+      acx_l_tx_data(priv, tx, packet_len);
-+ok:
-+      FN_EXIT1(OK);
-+      return OK;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_l_transmit_authen4
-+*----------------------------------------------------------------*/
-+static int
-+acx_l_transmit_authen4(wlandevice_t *priv, 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(priv);
-+      if (!tx)
-+              goto ok;
-+      head = acx_l_get_txbuf(priv, tx);
-+      if (!head)
-+              goto ok;
-+      body = (void*)(head + 1);
-+
-+      head->fc = WF_FSTYPE_AUTHENi; /* 0xb0 */
-+      head->dur = req->hdr->dur;
-+      MAC_COPY(head->da, req->hdr->a2);
-+      /* MAC_COPY(head->sa, req->hdr->a1); */
-+      MAC_COPY(head->sa, priv->dev_addr);
-+      MAC_COPY(head->bssid, req->hdr->a3);
-+      head->seq = 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(priv, tx, WLAN_HDR_A3_LEN + 2 + 2 + 2);
-+ok:
-+      FN_EXIT1(OK);
-+      return OK;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_l_transmit_assoc_req
-+*
-+* priv->ap_client is a current candidate AP here
-+*----------------------------------------------------------------*/
-+static int
-+acx_l_transmit_assoc_req(wlandevice_t *priv)
-+{
-+      struct tx *tx;
-+      struct wlan_hdr_mgmt *head;
-+      u8 *body, *p, *prate;
-+      unsigned int packet_len;
-+      u16 cap;
-+
-+      FN_ENTER;
-+
-+      acxlog(L_ASSOC, "sending association request, "
-+                      "awaiting response. NOT ASSOCIATED YET\n");
-+      tx = acx_l_alloc_tx(priv);
-+      if (!tx)
-+              goto bad;
-+      head = acx_l_get_txbuf(priv, tx);
-+      if (!head)
-+              goto bad;
-+      body = (void*)(head + 1);
-+
-+      head->fc = WF_FSTYPE_ASSOCREQi;
-+      head->dur = host2ieee16(0x8000);
-+      MAC_COPY(head->da, priv->bssid);
-+      MAC_COPY(head->sa, priv->dev_addr);
-+      MAC_COPY(head->bssid, priv->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 (priv->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 (priv->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 (priv->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(priv->listen_interval); p += 2;
-+      /* 3. ESSID */
-+      p = wlan_fill_ie_ssid(p,
-+                      strlen(priv->essid_for_assoc), priv->essid_for_assoc);
-+      /* 4. supp rates */
-+      prate = p;
-+      p = wlan_fill_ie_rates(p,
-+                      priv->rate_supported_len, priv->rate_supported);
-+      /* 5. ext supp rates */
-+      p = wlan_fill_ie_rates_ext(p,
-+                      priv->rate_supported_len, priv->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);
-+
-+      acxlog(L_ASSOC, "association: requesting caps 0x%04X, ESSID '%s'\n",
-+              cap, priv->essid_for_assoc);
-+
-+      acx_l_tx_data(priv, 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(priv, clt) - kick this client (we're an AP)
-+* acx_l_transmit_disassoc(priv, NULL) - leave BSSID (we're a STA)
-+*----------------------------------------------------------------*/
-+#ifdef BROKEN
-+int
-+acx_l_transmit_disassoc(wlandevice_t *priv, 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(priv);
-+              if (!tx)
-+                      goto bad;
-+              head = acx_l_get_txbuf(priv, tx);
-+              if (!head)
-+                      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, priv->bssid);
-+              MAC_COPY(head->sa, priv->dev_addr);
-+              MAC_COPY(head->bssid, priv->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(priv, 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 priv->sta_list:
-+*     if priv->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 priv->ap_client to the chosen struct client
-+*     sets priv->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(wlandevice_t *priv)
-+{
-+      struct client *bss;
-+      unsigned long flags;
-+      u16 needed_cap;
-+      int i;
-+      int idx_found = -1;
-+      int result = OK;
-+
-+      FN_ENTER;
-+
-+      switch (priv->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", priv->mode);
-+              dump_stack();
-+              goto end;
-+      }
-+
-+      acx_lock(priv, flags);
-+
-+      /* TODO: sta_iterator hiding implementation would be nice here... */
-+
-+      for (i = 0; i < VEC_SIZE(priv->sta_list); i++) {
-+              bss = &priv->sta_list[i];
-+              if (!bss->used) continue;
-+
-+              acxlog(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(priv->ap))
-+                      if (!mac_is_equal(bss->bssid, priv->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",
-+                              priv->netdev->name, MAC(bss->address));
-+                      continue;
-+              }
-+              acxlog(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",
-+                              priv->netdev->name, MAC(bss->address));
-+                      continue;
-+              }
-+
-+              /* do we support all basic rates of this peer? */
-+              if ((bss->rate_bas & priv->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",
-+                              priv->netdev->name, MAC(bss->address),
-+                              bss->rate_bas, priv->rate_oper);
-+                      continue;
-+#else
-+                      printk("%s: peer "MACSTR": incompatible basic rates "
-+                              "(AP requests 0x%04X, we have 0x%04X). "
-+                              "Considering anyway...\n",
-+                              priv->netdev->name, MAC(bss->address),
-+                              bss->rate_bas, priv->rate_oper);
-+#endif
-+              }
-+
-+              if ( !(priv->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",
-+                              priv->netdev->name, MAC(bss->address),
-+                              bss->channel);
-+                      continue; /* keep looking */
-+              }
-+
-+              if (!priv->essid_active || !strcmp(bss->essid, priv->essid)) {
-+                      acxlog(L_ASSOC,
-+                             "found station with matching ESSID! ('%s' "
-+                             "station, '%s' config)\n",
-+                             bss->essid,
-+                             (priv->essid_active) ? priv->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 == priv->channel)
-+                              break;
-+              } else
-+              if (!bss->essid[0]
-+               || ((' ' == bss->essid[0]) && !bss->essid[1])
-+              ) {
-+                      /* 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;
-+                      acxlog(L_ASSOC, "found station with empty or "
-+                              "single-space (hidden) SSID, considering "
-+                              "for assoc attempt\n");
-+                      /* ...and keep looking for better matches */
-+              } else {
-+                      acxlog(L_ASSOC, "ESSID doesn't match! ('%s' "
-+                              "station, '%s' config)\n",
-+                              bss->essid,
-+                              (priv->essid_active) ? priv->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 = &priv->sta_list[idx_found];
-+              priv->ap_client = bss;
-+
-+              if (bss->essid[0] == '\0') {
-+                      /* if the ESSID of the station we found is empty
-+                       * (no broadcast), then use user configured ESSID
-+                       * instead */
-+                      essid_src = priv->essid;
-+                      essid_len = priv->essid_len;
-+              } else {
-+                      essid_src = bss->essid;
-+                      essid_len = strlen(bss->essid);
-+              }
-+
-+              acx_update_capabilities(priv);
-+
-+              memcpy(priv->essid_for_assoc, essid_src, essid_len);
-+              priv->essid_for_assoc[essid_len] = '\0';
-+              priv->channel = bss->channel;
-+              MAC_COPY(priv->bssid, bss->bssid);
-+
-+              bss->rate_cfg = (bss->rate_cap & priv->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: ", priv->bssid, ", joining\n");
-+
-+              /* TODO: do we need to switch to the peer's channel first? */
-+
-+              if (ACX_MODE_0_ADHOC == priv->mode) {
-+                      acx_set_status(priv, ACX_STATUS_4_ASSOCIATED);
-+              } else {
-+                      acx_l_transmit_authen1(priv);
-+                      acx_set_status(priv, ACX_STATUS_2_WAIT_AUTH);
-+              }
-+      } else { /* idx_found == -1 */
-+              /* uh oh, no station found in range */
-+              if (ACX_MODE_0_ADHOC == priv->mode) {
-+                      printk("%s: no matching station found in range, "
-+                              "generating our own IBSS instead\n",
-+                              priv->netdev->name);
-+                      /* we do it hostap way: */
-+                      MAC_COPY(priv->bssid, priv->dev_addr);
-+                      priv->bssid[0] |= 0x02; /* 'local assigned addr' bit */
-+                      /* add IBSS bit to our caps... */
-+                      acx_update_capabilities(priv);
-+                      acx_set_status(priv, 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 */
-+                      acxlog(L_ASSOC,
-+                              "no matching station found in range yet\n");
-+                      acx_set_status(priv, ACX_STATUS_1_SCANNING);
-+                      result = NOT_OK;
-+              }
-+      }
-+
-+      acx_unlock(priv, flags);
-+
-+      if (idx_found != -1) {
-+              if (ACX_MODE_0_ADHOC == priv->mode) {
-+                      /* need to update channel in beacon template */
-+                      SET_BIT(priv->set_mask, SET_TEMPLATES);
-+                      if (ACX_STATE_IFACE_UP & priv->dev_state_mask)
-+                              acx_s_update_card_settings(priv, 0, 0);
-+              }
-+              /* Inform firmware on our decision to start or join BSS */
-+              acx_s_cmd_join_bssid(priv, priv->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
-+*/
-+#if USE_FW_LOADER_26
-+firmware_image_t*
-+acx_s_read_fw(struct device *dev, const char *file, u32 *size)
-+#else
-+#undef acx_s_read_fw
-+firmware_image_t*
-+acx_s_read_fw(const char *file, u32 *size)
-+#endif
-+{
-+      firmware_image_t *res;
-+
-+#if USE_FW_LOADER_LEGACY
-+      mm_segment_t orgfs;
-+      unsigned long page;
-+      char *buffer;
-+      struct file *inf;
-+      int retval;
-+      int offset;
-+      char *filename;
-+#endif
-+
-+#if USE_FW_LOADER_26
-+      const struct firmware *fw_entry;
-+
-+      res = NULL;
-+      acxlog(L_DEBUG, "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);
-+#endif
-+
-+#if USE_FW_LOADER_LEGACY
-+      printk("acx: firmware upload via firmware_dir module parameter "
-+              "is deprecated. Switch to using hotplug\n");
-+
-+      res = NULL;
-+      orgfs = get_fs(); /* store original fs */
-+      set_fs(KERNEL_DS);
-+
-+      /* Read in whole file then check the size */
-+      page = __get_free_page(GFP_KERNEL);
-+      if (unlikely(0 == page)) {
-+              printk("acx: no memory for firmware upload\n");
-+              goto fail;
-+      }
-+
-+      filename = kmalloc(PATH_MAX, GFP_KERNEL);
-+      if (unlikely(!filename)) {
-+              printk("acx: no memory for firmware upload\n");
-+              goto fail;
-+      }
-+      if (!firmware_dir) {
-+              firmware_dir = "/usr/share/acx";
-+              acxlog(L_DEBUG, "no firmware directory specified "
-+                      "via module parameter firmware_dir, "
-+                      "using default %s\n", firmware_dir);
-+      }
-+      snprintf(filename, PATH_MAX, "%s/%s", firmware_dir, file);
-+      acxlog(L_DEBUG, "reading firmware image '%s'\n", filename);
-+
-+      buffer = (char*)page;
-+
-+      /* Note that file must be given as absolute path:
-+       * a relative path works on first loading,
-+       * but any subsequent firmware loading during card
-+       * eject/insert will fail, most likely since the first
-+       * module loading happens in user space (and thus
-+       * filp_open can figure out the absolute path from a
-+       * relative path) whereas the card reinsert processing
-+       * probably happens in kernel space where you don't have
-+       * a current directory to be able to figure out an
-+       * absolute path from a relative path... */
-+      inf = filp_open(filename, O_RDONLY, 0);
-+      kfree(filename);
-+      if (OK != IS_ERR(inf)) {
-+              const char *err;
-+
-+              switch (-PTR_ERR(inf)) {
-+                      case 2: err = "file not found";
-+                              break;
-+                      default:
-+                              err = "unknown error";
-+                              break;
-+              }
-+              printk("acx: error %ld trying to open file '%s': %s\n",
-+                                      -PTR_ERR(inf), file, err);
-+              goto fail;
-+      }
-+
-+      if (unlikely((NULL == inf->f_op) || (NULL == inf->f_op->read))) {
-+              printk("acx: %s does not have a read method?!\n", file);
-+              goto fail_close;
-+      }
-+
-+      offset = 0;
-+      do {
-+              retval = inf->f_op->read(inf, buffer, PAGE_SIZE, &inf->f_pos);
-+
-+              if (unlikely(0 > retval)) {
-+                      printk("acx: error %d reading file '%s'\n",
-+                                                      -retval, file);
-+                      vfree(res);
-+                      res = NULL;
-+              } else if (0 == retval) {
-+                      if (0 == offset) {
-+                              printk("acx: firmware image file "
-+                                      "'%s' is empty?!\n", file);
-+                      }
-+              } else if (0 < retval) {
-+                      /* allocate result buffer here if needed,
-+                       * since we don't want to waste resources/time
-+                       * (in case file opening/reading fails)
-+                       * by doing allocation in front of the loop instead. */
-+                      if (NULL == res) {
-+                              *size = 8 + le32_to_cpu(*(u32 *)(4 + buffer));
-+
-+                              res = vmalloc(*size);
-+                              if (NULL == res) {
-+                                      printk("acx: unable to "
-+                                              "allocate %u bytes for "
-+                                              "firmware module upload\n",
-+                                              *size);
-+                                      goto fail_close;
-+                              }
-+                              acxlog(L_DEBUG, "allocated %u bytes "
-+                                      "for firmware module loading\n",
-+                                      *size);
-+                      }
-+                      if ((unlikely(offset + retval > *size))) {
-+                              printk("acx: ERROR: allocation "
-+                                      "was less than firmware image size?!\n");
-+                              goto fail_close;
-+                      }
-+                      memcpy((u8*)res + offset, buffer, retval);
-+                      offset += retval;
-+              }
-+      } while (0 < retval);
-+
-+fail_close:
-+      retval = filp_close(inf, NULL);
-+
-+      if (unlikely(retval)) {
-+              printk("acx: error %d closing file '%s'\n", -retval, file);
-+      }
-+
-+      if (unlikely((NULL != res) && (offset != le32_to_cpu(res->size) + 8))) {
-+              printk("acx: firmware is reporting a different size "
-+                      "(0x%08X; 0x%08X was read)\n",
-+                      le32_to_cpu(res->size) + 8, offset);
-+              vfree(res);
-+              res = NULL;
-+      }
-+
-+fail:
-+      if (page)
-+              free_page(page);
-+      set_fs(orgfs);
-+#endif
-+
-+      /* checksum will be verified in write_fw, so don't bother here */
-+      return res;
-+}
-+
-+
-+#ifdef POWER_SAVE_80211
-+/*----------------------------------------------------------------
-+* acx_s_activate_power_save_mode
-+*----------------------------------------------------------------*/
-+static void
-+acx_s_activate_power_save_mode(wlandevice_t *priv)
-+{
-+      acx100_ie_powermgmt_t pm;
-+
-+      FN_ENTER;
-+
-+      acx_s_interrogate(priv, &pm, ACX1xx_IE_POWER_MGMT);
-+      if (pm.wakeup_cfg != 0x81)
-+              goto end;
-+
-+      pm.wakeup_cfg = 0;
-+      pm.options = 0;
-+      pm.hangover_period = 0;
-+      acx_s_configure(priv, &pm, ACX1xx_IE_POWER_MGMT);
-+end:
-+      FN_EXIT0;
-+}
-+#endif
-+
-+
-+/***********************************************************************
-+** acx_s_set_wepkey
-+*/
-+static void
-+acx100_s_set_wepkey(wlandevice_t *priv)
-+{
-+      ie_dot11WEPDefaultKey_t dk;
-+      int i;
-+
-+      for (i = 0; i < DOT11_MAX_DEFAULT_WEP_KEYS; i++) {
-+              if (priv->wep_keys[i].size != 0) {
-+                      acxlog(L_INIT, "setting WEP key: %d with "
-+                              "total size: %d\n", i, (int) priv->wep_keys[i].size);
-+                      dk.action = 1;
-+                      dk.keySize = priv->wep_keys[i].size;
-+                      dk.defaultKeyNum = i;
-+                      memcpy(dk.key, priv->wep_keys[i].key, dk.keySize);
-+                      acx_s_configure(priv, &dk, ACX100_IE_DOT11_WEP_DEFAULT_KEY_WRITE);
-+              }
-+      }
-+}
-+
-+static void
-+acx111_s_set_wepkey(wlandevice_t *priv)
-+{
-+      acx111WEPDefaultKey_t dk;
-+      int i;
-+
-+      for (i = 0; i < DOT11_MAX_DEFAULT_WEP_KEYS; i++) {
-+              if (priv->wep_keys[i].size != 0) {
-+                      acxlog(L_INIT, "setting WEP key: %d with "
-+                              "total size: %d\n", i, (int) priv->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 = priv->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, priv->wep_keys[i].key, dk.keySize);
-+                      acx_s_issue_cmd(priv, ACX1xx_CMD_WEP_MGMT, &dk, sizeof(dk));
-+              }
-+      }
-+}
-+
-+static void
-+acx_s_set_wepkey(wlandevice_t *priv)
-+{
-+      if (IS_ACX111(priv))
-+              acx111_s_set_wepkey(priv);
-+      else
-+              acx100_s_set_wepkey(priv);
-+}
-+
-+
-+/***********************************************************************
-+** 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...
-+*/
-+int
-+acx100_s_init_wep(wlandevice_t *priv)
-+{
-+/*    int i;
-+      acx100_cmd_wep_mgmt_t wep_mgmt;           size = 37 bytes */
-+      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(priv, &pt, ACX1xx_IE_MEMORY_MAP)) {
-+              goto fail;
-+      }
-+
-+      acxlog(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(priv, &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;
-+
-+      acxlog(L_ASSOC, "%s: writing WEP options\n", __func__);
-+      acx_s_configure(priv, &options, ACX100_IE_WEP_OPTIONS);
-+
-+      acx100_s_set_wepkey(priv);
-+
-+      if (priv->wep_keys[priv->wep_current_index].size != 0) {
-+              acxlog(L_ASSOC, "setting active default WEP key number: %d\n",
-+                              priv->wep_current_index);
-+              dk.KeyID = priv->wep_current_index;
-+              acx_s_configure(priv, &dk, ACX1xx_IE_DOT11_WEP_DEFAULT_KEY_SET); /* 0x1010 */
-+      }
-+      /* FIXME!!! wep_key_struct is filled nowhere! But priv
-+       * is initialized to 0, and we don't REALLY need those keys either */
-+/*            for (i = 0; i < 10; i++) {
-+              if (priv->wep_key_struct[i].len != 0) {
-+                      MAC_COPY(wep_mgmt.MacAddr, priv->wep_key_struct[i].addr);
-+                      wep_mgmt.KeySize = cpu_to_le16(priv->wep_key_struct[i].len);
-+                      memcpy(&wep_mgmt.Key, priv->wep_key_struct[i].key, le16_to_cpu(wep_mgmt.KeySize));
-+                      wep_mgmt.Action = cpu_to_le16(1);
-+                      acxlog(L_ASSOC, "writing WEP key %d (len %d)\n", i, le16_to_cpu(wep_mgmt.KeySize));
-+                      if (OK == acx_s_issue_cmd(priv, ACX1xx_CMD_WEP_MGMT, &wep_mgmt, sizeof(wep_mgmt))) {
-+                              priv->wep_key_struct[i].index = i;
-+                      }
-+              }
-+      } */
-+
-+      /* now retrieve the updated WEPCacheEnd pointer... */
-+      if (OK != acx_s_interrogate(priv, &pt, ACX1xx_IE_MEMORY_MAP)) {
-+              printk("%s: ACX1xx_IE_MEMORY_MAP read #2 FAILED\n",
-+                              priv->netdev->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(priv, &pt, ACX1xx_IE_MEMORY_MAP)) {
-+              printk("%s: ACX1xx_IE_MEMORY_MAP write #2 FAILED\n",
-+                              priv->netdev->name);
-+              goto fail;
-+      }
-+      res = OK;
-+
-+fail:
-+      FN_EXIT1(res);
-+      return res;
-+}
-+
-+
-+/***********************************************************************
-+*/
-+static int
-+acx_s_init_max_null_data_template(wlandevice_t *priv)
-+{
-+      struct acx_template_nullframe b;
-+      int result;
-+
-+      FN_ENTER;
-+      memset(&b, 0, sizeof(b));
-+      b.size = cpu_to_le16(sizeof(b) - 2);
-+      result = acx_s_issue_cmd(priv, ACX1xx_CMD_CONFIG_NULL_DATA, &b, sizeof(b));
-+      FN_EXIT1(result);
-+      return result;
-+}
-+
-+
-+/***********************************************************************
-+** acx_s_init_max_beacon_template
-+*/
-+static int
-+acx_s_init_max_beacon_template(wlandevice_t *priv)
-+{
-+      struct acx_template_beacon b;
-+      int result;
-+
-+      FN_ENTER;
-+      memset(&b, 0, sizeof(b));
-+      b.size = cpu_to_le16(sizeof(b) - 2);
-+      result = acx_s_issue_cmd(priv, ACX1xx_CMD_CONFIG_BEACON, &b, sizeof(b));
-+
-+      FN_EXIT1(result);
-+      return result;
-+}
-+
-+/***********************************************************************
-+** acx_s_init_max_tim_template
-+*/
-+static int
-+acx_s_init_max_tim_template(wlandevice_t *priv)
-+{
-+      acx_template_tim_t t;
-+
-+      memset(&t, 0, sizeof(t));
-+      t.size = cpu_to_le16(sizeof(t) - 2);
-+      return acx_s_issue_cmd(priv, ACX1xx_CMD_CONFIG_TIM, &t, sizeof(t));
-+}
-+
-+
-+/***********************************************************************
-+** acx_s_init_max_probe_response_template
-+*/
-+static int
-+acx_s_init_max_probe_response_template(wlandevice_t *priv)
-+{
-+      struct acx_template_proberesp pr;
-+
-+      memset(&pr, 0, sizeof(pr));
-+      pr.size = cpu_to_le16(sizeof(pr) - 2);
-+
-+      return acx_s_issue_cmd(priv, ACX1xx_CMD_CONFIG_PROBE_RESPONSE, &pr, sizeof(pr));
-+}
-+
-+
-+/***********************************************************************
-+** acx_s_init_max_probe_request_template
-+*/
-+static int
-+acx_s_init_max_probe_request_template(wlandevice_t *priv)
-+{
-+      union {
-+              acx100_template_probereq_t p100;
-+              acx111_template_probereq_t p111;
-+      } pr;
-+      int res;
-+
-+      FN_ENTER;
-+      memset(&pr, 0, sizeof(pr));
-+      pr.p100.size = cpu_to_le16(sizeof(pr) - 2);
-+      res = acx_s_issue_cmd(priv, ACX1xx_CMD_CONFIG_PROBE_REQUEST, &pr, sizeof(pr));
-+      FN_EXIT1(res);
-+      return res;
-+}
-+
-+
-+/***********************************************************************
-+** acx_s_set_tim_template
-+**
-+** 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(wlandevice_t *priv)
-+{
-+/* 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(priv, 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(wlandevice_t *priv,
-+                                      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, priv->dev_addr);
-+      MAC_COPY(templ->bssid, priv->bssid);
-+
-+      templ->beacon_interval = cpu_to_le16(priv->beacon_interval);
-+      acx_update_capabilities(priv);
-+      templ->cap = cpu_to_le16(priv->capabilities);
-+
-+      p = templ->variable;
-+      p = wlan_fill_ie_ssid(p, priv->essid_len, priv->essid);
-+      p = wlan_fill_ie_rates(p, priv->rate_supported_len, priv->rate_supported);
-+      p = wlan_fill_ie_ds_parms(p, priv->channel);
-+      /* NB: should go AFTER tim, but acx seem to keep tim last always */
-+      p = wlan_fill_ie_rates_ext(p, priv->rate_supported_len, priv->rate_supported);
-+
-+      switch (priv->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;
-+}
-+
-+
-+/***********************************************************************
-+** acx_s_set_beacon_template
-+*/
-+static int
-+acx_s_set_beacon_template(wlandevice_t *priv)
-+{
-+      struct acx_template_beacon bcn;
-+      int len, result;
-+
-+      FN_ENTER;
-+
-+      len = acx_fill_beacon_or_proberesp_template(priv, &bcn, WF_FSTYPE_BEACON);
-+      result = acx_s_issue_cmd(priv, 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(wlandevice_t *priv)
-+{
-+      struct acx_template_proberesp pr;
-+      int len, result;
-+
-+      FN_ENTER;
-+
-+      len = acx_fill_beacon_or_proberesp_template(priv, &pr, WF_FSTYPE_PROBERESP);
-+      result = acx_s_issue_cmd(priv, ACX1xx_CMD_CONFIG_PROBE_RESPONSE, &pr, len);
-+
-+      FN_EXIT1(result);
-+      return result;
-+}
-+
-+
-+/***********************************************************************
-+** acx100_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.
-+*/
-+int
-+acx100_s_init_packet_templates(wlandevice_t *priv)
-+{
-+      acx_ie_memmap_t mm;
-+      int result = NOT_OK;
-+
-+      FN_ENTER;
-+
-+      acxlog(L_DEBUG, "sizeof(memmap)=%d bytes\n", (int)sizeof(mm));
-+
-+      /* acx100 still do not emit probe requests, thus this call
-+      ** is sourt of not needed. But we want it to work someday */
-+      if (OK != acx_s_init_max_probe_request_template(priv))
-+              goto failed;
-+
-+#ifdef NOT_WORKING_YET
-+      /* FIXME: creating the NULL data template breaks
-+       * communication right now, needs further testing.
-+       * Also, need to set the template once we're joining a network. */
-+      if (OK != acx_s_init_max_null_data_template(priv))
-+              goto failed;
-+#endif
-+
-+      if (OK != acx_s_init_max_beacon_template(priv))
-+              goto failed;
-+
-+      if (OK != acx_s_init_max_tim_template(priv))
-+              goto failed;
-+
-+      if (OK != acx_s_init_max_probe_response_template(priv))
-+              goto failed;
-+
-+      if (OK != acx_s_set_tim_template(priv))
-+              goto failed;
-+
-+      if (OK != acx_s_interrogate(priv, &mm, ACX1xx_IE_MEMORY_MAP)) {
-+              goto failed;
-+      }
-+
-+      mm.QueueStart = cpu_to_le32(le32_to_cpu(mm.PacketTemplateEnd) + 4);
-+      if (OK != acx_s_configure(priv, &mm, ACX1xx_IE_MEMORY_MAP)) {
-+              goto failed;
-+      }
-+
-+      result = OK;
-+      goto success;
-+
-+failed:
-+      acxlog(L_DEBUG|L_INIT,
-+              /* "cb=0x%X\n" */
-+              "pACXMemoryMap:\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));
-+
-+success:
-+      FN_EXIT1(result);
-+      return result;
-+}
-+
-+int
-+acx111_s_init_packet_templates(wlandevice_t *priv)
-+{
-+      int result = NOT_OK;
-+
-+      FN_ENTER;
-+
-+      acxlog(L_DEBUG|L_INIT, "initializing max packet templates\n");
-+
-+      if (OK != acx_s_init_max_probe_request_template(priv))
-+              goto failed;
-+
-+      if (OK != acx_s_init_max_null_data_template(priv))
-+              goto failed;
-+
-+      if (OK != acx_s_init_max_beacon_template(priv))
-+              goto failed;
-+
-+      if (OK != acx_s_init_max_tim_template(priv))
-+              goto failed;
-+
-+      if (OK != acx_s_init_max_probe_response_template(priv))
-+              goto failed;
-+
-+      /* the other templates will be set later (acx_start) */
-+      /*
-+      if (OK != acx_s_set_tim_template(priv))
-+              goto failed;*/
-+
-+      result = OK;
-+      goto success;
-+
-+failed:
-+      printk("%s: acx111_init_packet_templates() FAILED\n", priv->netdev->name);
-+
-+success:
-+      FN_EXIT1(result);
-+      return result;
-+}
-+
-+
-+/***********************************************************************
-+*/
-+static int
-+acx100_s_set_probe_request_template(wlandevice_t *priv)
-+{
-+      struct acx100_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, priv->dev_addr);
-+      MAC_BCAST(probereq.bssid);
-+
-+      probereq.beacon_interval = cpu_to_le16(priv->beacon_interval);
-+      acx_update_capabilities(priv);
-+      probereq.cap = cpu_to_le16(priv->capabilities);
-+
-+      p = probereq.variable;
-+      acxlog(L_ASSOC, "SSID='%s' len=%d\n", priv->essid, priv->essid_len);
-+      p = wlan_fill_ie_ssid(p, priv->essid_len, priv->essid);
-+      p = wlan_fill_ie_rates(p, priv->rate_supported_len, priv->rate_supported);
-+      /* FIXME: should these be here or AFTER ds_parms? */
-+      p = wlan_fill_ie_rates_ext(p, priv->rate_supported_len, priv->rate_supported);
-+      /* HUH?? who said it must be here? I've found nothing in 802.11! --vda*/
-+      /* p = wlan_fill_ie_ds_parms(p, priv->channel); */
-+      frame_len = p - (char*)&probereq;
-+      probereq.size = frame_len - 2;
-+
-+      res = acx_s_issue_cmd(priv, ACX1xx_CMD_CONFIG_PROBE_REQUEST, &probereq, frame_len);
-+      FN_EXIT0;
-+      return res;
-+}
-+
-+static int
-+acx111_s_set_probe_request_template(wlandevice_t *priv)
-+{
-+      struct acx111_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, priv->dev_addr);
-+      MAC_BCAST(probereq.bssid);
-+
-+      p = probereq.variable;
-+      p = wlan_fill_ie_ssid(p, priv->essid_len, priv->essid);
-+      p = wlan_fill_ie_rates(p, priv->rate_supported_len, priv->rate_supported);
-+      p = wlan_fill_ie_rates_ext(p, priv->rate_supported_len, priv->rate_supported);
-+      frame_len = p - (char*)&probereq;
-+      probereq.size = frame_len - 2;
-+
-+      res = acx_s_issue_cmd(priv, ACX1xx_CMD_CONFIG_PROBE_REQUEST, &probereq, frame_len);
-+      FN_EXIT0;
-+      return res;
-+}
-+
-+static int
-+acx_s_set_probe_request_template(wlandevice_t *priv)
-+{
-+      if (IS_ACX111(priv)) {
-+              return acx111_s_set_probe_request_template(priv);
-+      } else {
-+              return acx100_s_set_probe_request_template(priv);
-+      }
-+}
-+
-+
-+/***********************************************************************
-+** acx_s_update_card_settings
-+**
-+** Applies accumulated changes in various priv->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(wlandevice_t *priv)
-+{
-+      u32 feature1, feature2;
-+
-+      if ((priv->sensitivity < 1) || (priv->sensitivity > 3)) {
-+              printk("%s: invalid sensitivity setting (1..3), "
-+                      "setting to 1\n", priv->netdev->name);
-+              priv->sensitivity = 1;
-+      }
-+      acx111_s_get_feature_config(priv, &feature1, &feature2);
-+      CLEAR_BIT(feature1, FEATURE1_LOW_RX|FEATURE1_EXTRA_LOW_RX);
-+      if (priv->sensitivity > 1)
-+              SET_BIT(feature1, FEATURE1_LOW_RX);
-+      if (priv->sensitivity > 2)
-+              SET_BIT(feature1, FEATURE1_EXTRA_LOW_RX);
-+      acx111_s_feature_set(priv, feature1, feature2);
-+}
-+
-+void
-+acx_s_update_card_settings(wlandevice_t *priv, int get_all, int set_all)
-+{
-+      unsigned long flags;
-+      unsigned int start_scan = 0;
-+      int i;
-+
-+      FN_ENTER;
-+
-+      if (get_all)
-+              SET_BIT(priv->get_mask, GETSET_ALL);
-+      if (set_all)
-+              SET_BIT(priv->set_mask, GETSET_ALL);
-+      /* Why not just set masks to 0xffffffff? We can get rid of GETSET_ALL */
-+
-+      acxlog(L_INIT, "get_mask 0x%08X, set_mask 0x%08X\n",
-+                      priv->get_mask, priv->set_mask);
-+
-+      /* Track dependencies betweed various settings */
-+
-+      if (priv->set_mask & (GETSET_MODE|GETSET_RESCAN|GETSET_WEP)) {
-+              acxlog(L_INIT, "important setting has been changed. "
-+                      "Need to update packet templates, too\n");
-+              SET_BIT(priv->set_mask, SET_TEMPLATES);
-+      }
-+      if (priv->set_mask & (GETSET_CHANNEL|GETSET_ALL)) {
-+              /* This will actually tune RX/TX to the channel */
-+              SET_BIT(priv->set_mask, GETSET_RX|GETSET_TX);
-+              switch (priv->mode) {
-+              case ACX_MODE_0_ADHOC:
-+              case ACX_MODE_3_AP:
-+                      /* Beacons contain channel# - update them */
-+                      SET_BIT(priv->set_mask, SET_TEMPLATES);
-+              }
-+              switch (priv->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 (priv->set_mask & (GETSET_MODE|GETSET_RESCAN|GETSET_CHANNEL|GETSET_WEP|GETSET_ALL)) {
-+              if (ACX_MODE_2_STA == priv->mode) {
-+                      if (ACX_STATUS_4_ASSOCIATED == priv->status) {
-+                              acxlog(L_ASSOC, "we were ASSOCIATED - "
-+                                      "sending disassoc request\n");
-+                              acx_lock(priv, flags);
-+                              acx_l_transmit_disassoc(priv, NULL);
-+                              /* FIXME: deauth? */
-+                              acx_unlock(priv, flags);
-+                      }
-+                      /* need to reset some other stuff as well */
-+                      acxlog(L_DEBUG, "resetting bssid\n");
-+                      MAC_ZERO(priv->bssid);
-+                      SET_BIT(priv->set_mask, SET_TEMPLATES|SET_STA_LIST);
-+                      /* FIXME: should start scanning */
-+                      start_scan = 1;
-+              }
-+      }
-+#endif
-+
-+      if (priv->get_mask & (GETSET_STATION_ID|GETSET_ALL)) {
-+              u8 stationID[4 + ACX1xx_IE_DOT11_STATION_ID_LEN];
-+              const u8 *paddr;
-+
-+              acx_s_interrogate(priv, 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 iwpriv->dev_addr */
-+                      priv->netdev->dev_addr[ETH_ALEN - 1 - i] = paddr[i];
-+              }
-+              CLEAR_BIT(priv->get_mask, GETSET_STATION_ID);
-+      }
-+
-+      if (priv->get_mask & (GETSET_SENSITIVITY|GETSET_ALL)) {
-+              if ((RADIO_RFMD_11 == priv->radio_type)
-+              || (RADIO_MAXIM_0D == priv->radio_type)
-+              || (RADIO_RALINK_15 == priv->radio_type)) {
-+                      acx_s_read_phy_reg(priv, 0x30, &priv->sensitivity);
-+              } else {
-+                      acxlog(L_INIT, "don't know how to get sensitivity "
-+                              "for radio type 0x%02X\n", priv->radio_type);
-+                      priv->sensitivity = 0;
-+              }
-+              acxlog(L_INIT, "got sensitivity value %u\n", priv->sensitivity);
-+
-+              CLEAR_BIT(priv->get_mask, GETSET_SENSITIVITY);
-+      }
-+
-+      if (priv->get_mask & (GETSET_ANTENNA|GETSET_ALL)) {
-+              u8 antenna[4 + ACX1xx_IE_DOT11_CURRENT_ANTENNA_LEN];
-+
-+              memset(antenna, 0, sizeof(antenna));
-+              acx_s_interrogate(priv, antenna, ACX1xx_IE_DOT11_CURRENT_ANTENNA);
-+              priv->antenna = antenna[4];
-+              acxlog(L_INIT, "got antenna value 0x%02X\n", priv->antenna);
-+              CLEAR_BIT(priv->get_mask, GETSET_ANTENNA);
-+      }
-+
-+      if (priv->get_mask & (GETSET_ED_THRESH|GETSET_ALL)) {
-+              if (IS_ACX100(priv))    {
-+                      u8 ed_threshold[4 + ACX100_IE_DOT11_ED_THRESHOLD_LEN];
-+
-+                      memset(ed_threshold, 0, sizeof(ed_threshold));
-+                      acx_s_interrogate(priv, ed_threshold, ACX100_IE_DOT11_ED_THRESHOLD);
-+                      priv->ed_threshold = ed_threshold[4];
-+              } else {
-+                      acxlog(L_INIT, "acx111 doesn't support ED\n");
-+                      priv->ed_threshold = 0;
-+              }
-+              acxlog(L_INIT, "got Energy Detect (ED) threshold %u\n", priv->ed_threshold);
-+              CLEAR_BIT(priv->get_mask, GETSET_ED_THRESH);
-+      }
-+
-+      if (priv->get_mask & (GETSET_CCA|GETSET_ALL)) {
-+              if (IS_ACX100(priv))    {
-+                      u8 cca[4 + ACX1xx_IE_DOT11_CURRENT_CCA_MODE_LEN];
-+
-+                      memset(cca, 0, sizeof(priv->cca));
-+                      acx_s_interrogate(priv, cca, ACX1xx_IE_DOT11_CURRENT_CCA_MODE);
-+                      priv->cca = cca[4];
-+              } else {
-+                      acxlog(L_INIT, "acx111 doesn't support CCA\n");
-+                      priv->cca = 0;
-+              }
-+              acxlog(L_INIT, "got Channel Clear Assessment (CCA) value %u\n", priv->cca);
-+              CLEAR_BIT(priv->get_mask, GETSET_CCA);
-+      }
-+
-+      if (priv->get_mask & (GETSET_REG_DOMAIN|GETSET_ALL)) {
-+              acx_ie_generic_t dom;
-+
-+              acx_s_interrogate(priv, &dom, ACX1xx_IE_DOT11_CURRENT_REG_DOMAIN);
-+              priv->reg_dom_id = dom.m.bytes[0];
-+              /* FIXME: should also set chanmask somehow */
-+              acxlog(L_INIT, "got regulatory domain 0x%02X\n", priv->reg_dom_id);
-+              CLEAR_BIT(priv->get_mask, GETSET_REG_DOMAIN);
-+      }
-+
-+      if (priv->set_mask & (GETSET_STATION_ID|GETSET_ALL)) {
-+              u8 stationID[4 + ACX1xx_IE_DOT11_STATION_ID_LEN];
-+              u8 *paddr;
-+
-+              paddr = &stationID[4];
-+              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] = priv->dev_addr[ETH_ALEN - 1 - i];
-+              }
-+              acx_s_configure(priv, &stationID, ACX1xx_IE_DOT11_STATION_ID);
-+              CLEAR_BIT(priv->set_mask, GETSET_STATION_ID);
-+      }
-+
-+      if (priv->set_mask & (SET_TEMPLATES|GETSET_ALL)) {
-+              acxlog(L_INIT, "updating packet templates\n");
-+              /* Doesn't work for acx100, do it only for acx111 for now */
-+              if (IS_ACX111(priv)) {
-+                      switch (priv->mode) {
-+                      case ACX_MODE_0_ADHOC:
-+                      case ACX_MODE_2_STA:
-+                              acx_s_set_probe_request_template(priv);
-+                      }
-+              }
-+              switch (priv->mode) {
-+              case ACX_MODE_0_ADHOC:
-+              case ACX_MODE_3_AP:
-+                      /* FIXME: why only for AP? STA need probe req templates... */
-+                      acx_s_set_beacon_template(priv);
-+                      acx_s_set_tim_template(priv);
-+                      /* 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(priv);
-+              }
-+              /* Needed if generated frames are to be emitted at different tx rate now */
-+              acxlog(L_IRQ, "redoing cmd_join_bssid() after template cfg\n");
-+              acx_s_cmd_join_bssid(priv, priv->bssid);
-+              CLEAR_BIT(priv->set_mask, SET_TEMPLATES);
-+      }
-+      if (priv->set_mask & (SET_STA_LIST|GETSET_ALL)) {
-+              acx_lock(priv, flags);
-+              acx_l_sta_list_init(priv);
-+              CLEAR_BIT(priv->set_mask, SET_STA_LIST);
-+              acx_unlock(priv, flags);
-+      }
-+      if (priv->set_mask & (SET_RATE_FALLBACK|GETSET_ALL)) {
-+              u8 rate[4 + ACX1xx_IE_RATE_FALLBACK_LEN];
-+
-+              /* configure to not do fallbacks when not in auto rate mode */
-+              rate[4] = (priv->rate_auto) ? /* priv->txrate_fallback_retries */ 1 : 0;
-+              acxlog(L_INIT, "updating Tx fallback to %u retries\n", rate[4]);
-+              acx_s_configure(priv, &rate, ACX1xx_IE_RATE_FALLBACK);
-+              CLEAR_BIT(priv->set_mask, SET_RATE_FALLBACK);
-+      }
-+      if (priv->set_mask & (GETSET_TXPOWER|GETSET_ALL)) {
-+              acxlog(L_INIT, "updating transmit power: %u dBm\n",
-+                                      priv->tx_level_dbm);
-+              acx_s_set_tx_level(priv, priv->tx_level_dbm);
-+              CLEAR_BIT(priv->set_mask, GETSET_TXPOWER);
-+      }
-+
-+      if (priv->set_mask & (GETSET_SENSITIVITY|GETSET_ALL)) {
-+              acxlog(L_INIT, "updating sensitivity value: %u\n",
-+                                      priv->sensitivity);
-+              switch (priv->radio_type) {
-+              case RADIO_RFMD_11:
-+              case RADIO_MAXIM_0D:
-+              case RADIO_RALINK_15:
-+                      acx_s_write_phy_reg(priv, 0x30, priv->sensitivity);
-+                      break;
-+              case RADIO_RADIA_16:
-+              case RADIO_UNKNOWN_17:
-+                      acx111_s_sens_radio_16_17(priv);
-+                      break;
-+              default:
-+                      acxlog(L_INIT, "don't know how to modify sensitivity "
-+                              "for radio type 0x%02X\n", priv->radio_type);
-+              }
-+              CLEAR_BIT(priv->set_mask, GETSET_SENSITIVITY);
-+      }
-+
-+      if (priv->set_mask & (GETSET_ANTENNA|GETSET_ALL)) {
-+              /* antenna */
-+              u8 antenna[4 + ACX1xx_IE_DOT11_CURRENT_ANTENNA_LEN];
-+
-+              memset(antenna, 0, sizeof(antenna));
-+              antenna[4] = priv->antenna;
-+              acxlog(L_INIT, "updating antenna value: 0x%02X\n",
-+                                      priv->antenna);
-+              acx_s_configure(priv, &antenna, ACX1xx_IE_DOT11_CURRENT_ANTENNA);
-+              CLEAR_BIT(priv->set_mask, GETSET_ANTENNA);
-+      }
-+
-+      if (priv->set_mask & (GETSET_ED_THRESH|GETSET_ALL)) {
-+              /* ed_threshold */
-+              acxlog(L_INIT, "updating Energy Detect (ED) threshold: %u\n",
-+                                      priv->ed_threshold);
-+              if (IS_ACX100(priv)) {
-+                      u8 ed_threshold[4 + ACX100_IE_DOT11_ED_THRESHOLD_LEN];
-+
-+                      memset(ed_threshold, 0, sizeof(ed_threshold));
-+                      ed_threshold[4] = priv->ed_threshold;
-+                      acx_s_configure(priv, &ed_threshold, ACX100_IE_DOT11_ED_THRESHOLD);
-+              }
-+              else
-+                      acxlog(L_INIT, "acx111 doesn't support ED!\n");
-+              CLEAR_BIT(priv->set_mask, GETSET_ED_THRESH);
-+      }
-+
-+      if (priv->set_mask & (GETSET_CCA|GETSET_ALL)) {
-+              /* CCA value */
-+              acxlog(L_INIT, "updating Channel Clear Assessment "
-+                              "(CCA) value: 0x%02X\n", priv->cca);
-+              if (IS_ACX100(priv))    {
-+                      u8 cca[4 + ACX1xx_IE_DOT11_CURRENT_CCA_MODE_LEN];
-+
-+                      memset(cca, 0, sizeof(cca));
-+                      cca[4] = priv->cca;
-+                      acx_s_configure(priv, &cca, ACX1xx_IE_DOT11_CURRENT_CCA_MODE);
-+              }
-+              else
-+                      acxlog(L_INIT, "acx111 doesn't support CCA!\n");
-+              CLEAR_BIT(priv->set_mask, GETSET_CCA);
-+      }
-+
-+      if (priv->set_mask & (GETSET_LED_POWER|GETSET_ALL)) {
-+              /* Enable Tx */
-+              acxlog(L_INIT, "updating power LED status: %u\n", priv->led_power);
-+
-+              acx_lock(priv, flags);
-+              if (IS_PCI(priv))
-+                      acx_l_power_led(priv, priv->led_power);
-+              CLEAR_BIT(priv->set_mask, GETSET_LED_POWER);
-+              acx_unlock(priv, flags);
-+      }
-+
-+/* this seems to cause Tx lockup after some random time (Tx error 0x20),
-+ * so let's disable it for now until further investigation */
-+/* Maybe fixed now after locking is fixed. Need to retest */
-+#ifdef POWER_SAVE_80211
-+      if (priv->set_mask & (GETSET_POWER_80211|GETSET_ALL)) {
-+              acx100_ie_powermgmt_t pm;
-+
-+              /* change 802.11 power save mode settings */
-+              acxlog(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 %d\n",
-+                      priv->ps_wakeup_cfg, priv->ps_listen_interval,
-+                      priv->ps_options, priv->ps_hangover_period,
-+                      priv->ps_enhanced_transition_time);
-+              acx_s_interrogate(priv, &pm, ACX100_IE_POWER_MGMT);
-+              acxlog(L_INIT, "Previous PS mode settings: wakeup_cfg 0x%02X, "
-+                      "listen interval %u, options 0x%02X, "
-+                      "hangover period %u, "
-+                      "enhanced_ps_transition_time %d\n",
-+                      pm.wakeup_cfg, pm.listen_interval, pm.options,
-+                      pm.hangover_period, pm.enhanced_ps_transition_time);
-+              pm.wakeup_cfg = priv->ps_wakeup_cfg;
-+              pm.listen_interval = priv->ps_listen_interval;
-+              pm.options = priv->ps_options;
-+              pm.hangover_period = priv->ps_hangover_period;
-+              pm.enhanced_ps_transition_time = cpu_to_le16(priv->ps_enhanced_transition_time);
-+              acx_s_configure(priv, &pm, ACX100_IE_POWER_MGMT);
-+              acx_s_interrogate(priv, &pm, ACX100_IE_POWER_MGMT);
-+              acxlog(L_INIT, "wakeup_cfg: 0x%02X\n", pm.wakeup_cfg);
-+              acx_s_msleep(40);
-+              acx_s_interrogate(priv, &pm, ACX100_IE_POWER_MGMT);
-+              acxlog(L_INIT, "power save mode change %s\n",
-+                      (pm.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). Does this need locking?? */
-+              CLEAR_BIT(priv->set_mask, GETSET_POWER_80211);
-+      }
-+#endif
-+
-+      if (priv->set_mask & (GETSET_CHANNEL|GETSET_ALL)) {
-+              /* channel */
-+              acxlog(L_INIT, "updating channel to: %u\n", priv->channel);
-+              CLEAR_BIT(priv->set_mask, GETSET_CHANNEL);
-+      }
-+
-+      if (priv->set_mask & (GETSET_TX|GETSET_ALL)) {
-+              /* set Tx */
-+              acxlog(L_INIT, "updating: %s Tx\n",
-+                              priv->tx_disabled ? "disable" : "enable");
-+              if (priv->tx_disabled)
-+                      acx_s_issue_cmd(priv, ACX1xx_CMD_DISABLE_TX, NULL, 0);
-+                      /*                                                 ^ */
-+                      /* FIXME: this used to be 1, but since we don't transfer a parameter... */
-+              else
-+                      acx_s_issue_cmd(priv, ACX1xx_CMD_ENABLE_TX, &(priv->channel), 1);
-+              CLEAR_BIT(priv->set_mask, GETSET_TX);
-+      }
-+
-+      if (priv->set_mask & (GETSET_RX|GETSET_ALL)) {
-+              /* Enable Rx */
-+              acxlog(L_INIT, "updating: enable Rx on channel: %u\n",
-+                              priv->channel);
-+              acx_s_issue_cmd(priv, ACX1xx_CMD_ENABLE_RX, &(priv->channel), 1);
-+              CLEAR_BIT(priv->set_mask, GETSET_RX);
-+      }
-+
-+      if (priv->set_mask & (GETSET_RETRY|GETSET_ALL)) {
-+              u8 short_retry[4 + ACX1xx_IE_DOT11_SHORT_RETRY_LIMIT_LEN];
-+              u8 long_retry[4 + ACX1xx_IE_DOT11_LONG_RETRY_LIMIT_LEN];
-+
-+              acxlog(L_INIT, "updating short retry limit: %u, long retry limit: %u\n",
-+                                      priv->short_retry, priv->long_retry);
-+              short_retry[0x4] = priv->short_retry;
-+              long_retry[0x4] = priv->long_retry;
-+              acx_s_configure(priv, &short_retry, ACX1xx_IE_DOT11_SHORT_RETRY_LIMIT);
-+              acx_s_configure(priv, &long_retry, ACX1xx_IE_DOT11_LONG_RETRY_LIMIT);
-+              CLEAR_BIT(priv->set_mask, GETSET_RETRY);
-+      }
-+
-+      if (priv->set_mask & (SET_MSDU_LIFETIME|GETSET_ALL)) {
-+              u8 xmt_msdu_lifetime[4 + ACX1xx_IE_DOT11_MAX_XMIT_MSDU_LIFETIME_LEN];
-+
-+              acxlog(L_INIT, "updating tx MSDU lifetime: %u\n",
-+                                      priv->msdu_lifetime);
-+              *(u32 *)&xmt_msdu_lifetime[4] = cpu_to_le32((u32)priv->msdu_lifetime);
-+              acx_s_configure(priv, &xmt_msdu_lifetime, ACX1xx_IE_DOT11_MAX_XMIT_MSDU_LIFETIME);
-+              CLEAR_BIT(priv->set_mask, SET_MSDU_LIFETIME);
-+      }
-+
-+      if (priv->set_mask & (GETSET_REG_DOMAIN|GETSET_ALL)) {
-+              /* reg_domain */
-+              acx_ie_generic_t dom;
-+              unsigned mask;
-+
-+              acxlog(L_INIT, "updating regulatory domain: 0x%02X\n",
-+                                      priv->reg_dom_id);
-+              for (i = 0; i < sizeof(reg_domain_ids); i++)
-+                      if (reg_domain_ids[i] == priv->reg_dom_id)
-+                              break;
-+
-+              if (sizeof(reg_domain_ids) == i) {
-+                      acxlog(L_INIT, "Invalid or unsupported regulatory "
-+                              "domain 0x%02X specified, falling back to "
-+                              "FCC (USA)! Please report if this sounds "
-+                              "fishy!\n", priv->reg_dom_id);
-+                      i = 0;
-+                      priv->reg_dom_id = reg_domain_ids[i];
-+              }
-+
-+              priv->reg_dom_chanmask = reg_domain_channel_masks[i];
-+              dom.m.bytes[0] = priv->reg_dom_id;
-+              acx_s_configure(priv, &dom, ACX1xx_IE_DOT11_CURRENT_REG_DOMAIN);
-+
-+              mask = (1 << (priv->channel - 1));
-+              if (!(priv->reg_dom_chanmask & mask)) {
-+              /* hmm, need to adjust our channel to reside within domain */
-+                      mask = 1;
-+                      for (i = 1; i <= 14; i++) {
-+                              if (priv->reg_dom_chanmask & mask) {
-+                                      printk("%s: adjusting "
-+                                              "selected channel from %d "
-+                                              "to %d due to new regulatory "
-+                                              "domain\n", priv->netdev->name,
-+                                              priv->channel, i);
-+                                      priv->channel = i;
-+                                      break;
-+                              }
-+                              mask <<= 1;
-+                      }
-+              }
-+              CLEAR_BIT(priv->set_mask, GETSET_REG_DOMAIN);
-+      }
-+
-+      if (priv->set_mask & (GETSET_MODE|GETSET_ALL)) {
-+              priv->netdev->type = ARPHRD_ETHER;
-+
-+              switch (priv->mode) {
-+              case ACX_MODE_3_AP:
-+
-+                      acx_lock(priv, flags);
-+                      acx_l_sta_list_init(priv);
-+                      priv->aid = 0;
-+                      priv->ap_client = NULL;
-+                      MAC_COPY(priv->bssid, priv->dev_addr);
-+                      /* this basically says "we're connected" */
-+                      acx_set_status(priv, ACX_STATUS_4_ASSOCIATED);
-+                      acx_unlock(priv, flags);
-+
-+                      acx111_s_feature_off(priv, 0, FEATURE2_NO_TXCRYPT|FEATURE2_SNIFFER);
-+                      /* start sending beacons */
-+                      acx_s_cmd_join_bssid(priv, priv->bssid);
-+                      break;
-+              case ACX_MODE_MONITOR:
-+                      /* priv->netdev->type = ARPHRD_ETHER; */
-+                      /* priv->netdev->type = ARPHRD_IEEE80211; */
-+                      priv->netdev->type = ARPHRD_IEEE80211_PRISM;
-+                      acx111_s_feature_on(priv, 0, FEATURE2_NO_TXCRYPT|FEATURE2_SNIFFER);
-+                      /* this stops beacons */
-+                      acx_s_cmd_join_bssid(priv, priv->bssid);
-+                      /* this basically says "we're connected" */
-+                      acx_set_status(priv, ACX_STATUS_4_ASSOCIATED);
-+                      SET_BIT(priv->set_mask, SET_RXCONFIG|SET_WEP_OPTIONS);
-+                      break;
-+              case ACX_MODE_0_ADHOC:
-+              case ACX_MODE_2_STA:
-+                      acx111_s_feature_off(priv, 0, FEATURE2_NO_TXCRYPT|FEATURE2_SNIFFER);
-+                      priv->aid = 0;
-+                      priv->ap_client = NULL;
-+                      /* 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: */
-+                      /* priv->tx_disabled = 1; */
-+                      /* SET_BIT(priv->set_mask, GETSET_RX|GETSET_TX); */
-+
-+                      /* This stops beacons (invalid macmode...) */
-+                      acx_s_cmd_join_bssid(priv, priv->bssid);
-+                      acx_set_status(priv, ACX_STATUS_0_STOPPED);
-+                      break;
-+              }
-+              CLEAR_BIT(priv->set_mask, GETSET_MODE);
-+      }
-+
-+      if (priv->set_mask & (SET_RXCONFIG|GETSET_ALL)) {
-+              acx_s_initialize_rx_config(priv);
-+              CLEAR_BIT(priv->set_mask, SET_RXCONFIG);
-+      }
-+
-+      if (priv->set_mask & (GETSET_RESCAN|GETSET_ALL)) {
-+              switch (priv->mode) {
-+              case ACX_MODE_0_ADHOC:
-+              case ACX_MODE_2_STA:
-+                      start_scan = 1;
-+                      break;
-+              }
-+              CLEAR_BIT(priv->set_mask, GETSET_RESCAN);
-+      }
-+
-+      if (priv->set_mask & (GETSET_WEP|GETSET_ALL)) {
-+              /* encode */
-+
-+              ie_dot11WEPDefaultKeyID_t dkey;
-+#ifdef DEBUG_WEP
-+              struct {
-+                      u16 type ACX_PACKED;
-+                      u16 len ACX_PACKED;
-+                      u8  val ACX_PACKED;
-+              } keyindic;
-+#endif
-+              acxlog(L_INIT, "updating WEP key settings\n");
-+
-+              acx_s_set_wepkey(priv);
-+
-+              dkey.KeyID = priv->wep_current_index;
-+              acxlog(L_INIT, "setting WEP key %u as default\n", dkey.KeyID);
-+              acx_s_configure(priv, &dkey, ACX1xx_IE_DOT11_WEP_DEFAULT_KEY_SET);
-+#ifdef DEBUG_WEP
-+              keyindic.val = 3;
-+              acx_s_configure(priv, &keyindic, ACX111_IE_KEY_CHOOSE);
-+#endif
-+              start_scan = 1;
-+              CLEAR_BIT(priv->set_mask, GETSET_WEP);
-+      }
-+
-+      if (priv->set_mask & (SET_WEP_OPTIONS|GETSET_ALL)) {
-+              acx100_ie_wep_options_t options;
-+
-+              if (IS_ACX111(priv)) {
-+                      acxlog(L_DEBUG, "setting WEP Options for acx111 is not supported\n");
-+              } else {
-+                      acxlog(L_INIT, "setting WEP Options\n");
-+
-+                      /* 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 (priv->mode == ACX_MODE_MONITOR) {
-+                              /* don't decrypt default key only,
-+                               * override decryption mechanism: */
-+                              options.WEPOption = 2;
-+                      }
-+
-+                      acx_s_configure(priv, &options, ACX100_IE_WEP_OPTIONS);
-+              }
-+              CLEAR_BIT(priv->set_mask, SET_WEP_OPTIONS);
-+      }
-+
-+      /* Rescan was requested */
-+      if (start_scan) {
-+              switch (priv->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(priv, flags);
-+                      priv->ap_client = NULL;
-+                      acx_l_sta_list_init(priv);
-+                      acx_set_status(priv, ACX_STATUS_1_SCANNING);
-+                      acx_unlock(priv, flags);
-+
-+                      acx_s_cmd_start_scan(priv);
-+              }
-+      }
-+
-+      /* debug, rate, and nick don't need any handling */
-+      /* what about sniffing mode?? */
-+
-+      acxlog(L_INIT, "get_mask 0x%08X, set_mask 0x%08X - after update\n",
-+                      priv->get_mask, priv->set_mask);
-+
-+/* end: */
-+      FN_EXIT0;
-+}
-+
-+
-+/***********************************************************************
-+*/
-+void
-+acx_s_initialize_rx_config(wlandevice_t *priv)
-+{
-+      struct {
-+              u16     id ACX_PACKED;
-+              u16     len ACX_PACKED;
-+              u16     rx_cfg1 ACX_PACKED;
-+              u16     rx_cfg2 ACX_PACKED;
-+      } cfg;
-+
-+      switch (priv->mode) {
-+      case ACX_MODE_OFF:
-+              priv->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    */
-+                      );
-+              priv->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:
-+              priv->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    */
-+                      );
-+              priv->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:
-+              priv->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    */
-+                      );
-+              priv->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;
-+      }
-+#ifdef DEBUG_WEP
-+      if (IS_ACX100(priv))
-+              /* only ACX100 supports that */
-+#endif
-+              priv->rx_config_1 |= RX_CFG1_INCLUDE_RXBUF_HDR;
-+
-+      acxlog(L_INIT, "setting RXconfig to %04X:%04X\n",
-+                      priv->rx_config_1, priv->rx_config_2);
-+      cfg.rx_cfg1 = cpu_to_le16(priv->rx_config_1);
-+      cfg.rx_cfg2 = cpu_to_le16(priv->rx_config_2);
-+      acx_s_configure(priv, &cfg, ACX1xx_IE_RXCONFIG);
-+}
-+
-+
-+/***********************************************************************
-+** acx_e_after_interrupt_task
-+*/
-+static int
-+acx_s_recalib_radio(wlandevice_t *priv)
-+{
-+      if (IS_ACX111(priv)) {
-+              acx111_cmd_radiocalib_t cal;
-+
-+              printk("%s: recalibrating radio\n", priv->netdev->name);
-+              /* automatic recalibration, choose all methods: */
-+              cal.methods = cpu_to_le32(0x8000000f);
-+              /* automatic recalibration every 60 seconds (value in TUs)
-+               * FIXME: what is the firmware default here?? */
-+              cal.interval = cpu_to_le32(58594);
-+              return acx_s_issue_cmd_timeo(priv, ACX111_CMD_RADIOCALIB,
-+                      &cal, sizeof(cal), CMD_TIMEOUT_MS(100));
-+      } else {
-+              if (/* (OK == acx_s_issue_cmd(priv, ACX1xx_CMD_DISABLE_TX, NULL, 0)) &&
-+                  (OK == acx_s_issue_cmd(priv, ACX1xx_CMD_DISABLE_RX, NULL, 0)) && */
-+                  (OK == acx_s_issue_cmd(priv, ACX1xx_CMD_ENABLE_TX, &(priv->channel), 1)) &&
-+                  (OK == acx_s_issue_cmd(priv, ACX1xx_CMD_ENABLE_RX, &(priv->channel), 1)) )
-+                      return OK;
-+              return NOT_OK;
-+      }
-+}
-+
-+static void
-+acx_s_after_interrupt_recalib(wlandevice_t *priv)
-+{
-+      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(priv->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 (priv->recalib_time_last_success
-+       && time_before(jiffies, priv->recalib_time_last_success
-+                                      + RECALIB_PAUSE * 60 * HZ)) {
-+              priv->recalib_msg_ratelimit++;
-+              if (priv->recalib_msg_ratelimit <= 5)
-+                      printk("%s: less than " STRING(RECALIB_PAUSE)
-+                              " minutes since last radio recalibration, "
-+                              "not recalibrating (maybe card is too hot?)\n",
-+                              priv->netdev->name);
-+              if (priv->recalib_msg_ratelimit == 5)
-+                      printk("disabling above message\n");
-+              return;
-+      }
-+
-+      priv->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(priv);
-+      if (res == OK) {
-+              printk("%s: successfully recalibrated radio\n",
-+                                              priv->netdev->name);
-+              priv->recalib_time_last_success = jiffies;
-+              priv->recalib_failure_count = 0;
-+      } else {
-+              /* failed: resubmit, but only limited
-+               * amount of times within some time range
-+               * to prevent endless loop */
-+
-+              priv->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, priv->recalib_time_last_attempt + HZ))
-+                      priv->recalib_failure_count = 0;
-+
-+              if (++priv->recalib_failure_count <= 5) {
-+                      priv->recalib_time_last_attempt = jiffies;
-+                      acx_schedule_after_interrupt_task(priv, ACX_AFTER_IRQ_CMD_RADIO_RECALIB);
-+              }
-+      }
-+}
-+
-+static void
-+acx_e_after_interrupt_task(void *data)
-+{
-+      netdevice_t *dev = (netdevice_t *) data;
-+      wlandevice_t *priv = netdev_priv(dev);
-+
-+      FN_ENTER;
-+
-+      acx_sem_lock(priv);
-+
-+      if (!priv->after_interrupt_jobs)
-+              goto end; /* no jobs to do */
-+
-+#if TX_CLEANUP_IN_SOFTIRQ
-+      if (priv->after_interrupt_jobs & ACX_AFTER_IRQ_TX_CLEANUP) {
-+              acx_lock(priv, flags);
-+              acx_l_clean_tx_desc(priv);
-+              CLEAR_BIT(priv->after_interrupt_jobs, ACX_AFTER_IRQ_TX_CLEANUP);
-+              acx_unlock(priv, flags);
-+      }
-+#endif
-+      /* we see lotsa tx errors */
-+      if (priv->after_interrupt_jobs & ACX_AFTER_IRQ_CMD_RADIO_RECALIB) {
-+              acx_s_after_interrupt_recalib(priv);
-+      }
-+
-+      /* a poor interrupt code wanted to do update_card_settings() */
-+      if (priv->after_interrupt_jobs & ACX_AFTER_IRQ_UPDATE_CARD_CFG) {
-+              if (ACX_STATE_IFACE_UP & priv->dev_state_mask)
-+                      acx_s_update_card_settings(priv, 0, 0);
-+              CLEAR_BIT(priv->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 (priv->after_interrupt_jobs & ACX_AFTER_IRQ_CMD_STOP_SCAN) {
-+              acxlog(L_IRQ, "sending a stop scan cmd...\n");
-+              acx_s_issue_cmd(priv, 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(priv->irq_status, HOST_INT_SCAN_COMPLETE);
-+              CLEAR_BIT(priv->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 (priv->after_interrupt_jobs & ACX_AFTER_IRQ_COMPLETE_SCAN) {
-+              if (priv->status == ACX_STATUS_1_SCANNING) {
-+                      if (OK != acx_s_complete_scan(priv)) {
-+                              SET_BIT(priv->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 (priv->mode) {
-+                      case ACX_MODE_0_ADHOC:
-+                      case ACX_MODE_3_AP:
-+                              acxlog(L_IRQ, "redoing cmd_join_bssid() after scan\n");
-+                              acx_s_cmd_join_bssid(priv, priv->bssid);
-+                      }
-+              }
-+              CLEAR_BIT(priv->after_interrupt_jobs, ACX_AFTER_IRQ_COMPLETE_SCAN);
-+      }
-+
-+      /* STA auth or assoc timed out, start over again */
-+      if (priv->after_interrupt_jobs & ACX_AFTER_IRQ_RESTART_SCAN) {
-+              acxlog(L_IRQ, "sending a start_scan cmd...\n");
-+              acx_s_cmd_start_scan(priv);
-+              CLEAR_BIT(priv->after_interrupt_jobs, ACX_AFTER_IRQ_RESTART_SCAN);
-+      }
-+
-+      /* whee, we got positive assoc response! 8) */
-+      if (priv->after_interrupt_jobs & ACX_AFTER_IRQ_CMD_ASSOCIATE) {
-+              acx_ie_generic_t pdr;
-+              /* tiny race window exists, checking that we still a STA */
-+              switch (priv->mode) {
-+              case ACX_MODE_2_STA:
-+                      pdr.m.aid = cpu_to_le16(priv->aid);
-+                      acx_s_configure(priv, &pdr, ACX1xx_IE_ASSOC_ID);
-+                      acx_set_status(priv, ACX_STATUS_4_ASSOCIATED);
-+                      acxlog(L_ASSOC|L_DEBUG, "ASSOCIATED!\n");
-+                      CLEAR_BIT(priv->after_interrupt_jobs, ACX_AFTER_IRQ_CMD_ASSOCIATE);
-+              }
-+      }
-+end:
-+      acx_sem_unlock(priv);
-+      FN_EXIT0;
-+}
-+
-+
-+/***********************************************************************
-+** acx_schedule_after_interrupt_task
-+**
-+** Schedule the call of the after_interrupt method after leaving
-+** the interrupt context.
-+*/
-+void
-+acx_schedule_after_interrupt_task(wlandevice_t *priv, unsigned int set_flag)
-+{
-+      SET_BIT(priv->after_interrupt_jobs, set_flag);
-+      SCHEDULE_WORK(&priv->after_interrupt_task);
-+}
-+
-+
-+/***********************************************************************
-+*/
-+void
-+acx_init_task_scheduler(wlandevice_t *priv)
-+{
-+      /* configure task scheduler */
-+      INIT_WORK(&priv->after_interrupt_task, acx_e_after_interrupt_task,
-+                      priv->netdev);
-+}
-+
-+
-+/***********************************************************************
-+** acx_s_start
-+*/
-+void
-+acx_s_start(wlandevice_t *priv)
-+{
-+      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(priv->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);
-+
-+      acxlog(L_INIT, "updating initial settings on iface activation...\n");
-+      acx_s_update_card_settings(priv, 0, 0);
-+
-+      FN_EXIT0;
-+}
-+
-+
-+/***********************************************************************
-+** acx_update_capabilities
-+*/
-+void
-+acx_update_capabilities(wlandevice_t *priv)
-+{
-+      u16 cap = 0;
-+
-+      switch (priv->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 (priv->wep_restricted) {
-+              SET_BIT(cap, WF_MGMT_CAP_PRIVACY);
-+      }
-+      if (priv->capab_short) {
-+              SET_BIT(cap, WF_MGMT_CAP_SHORT);
-+      }
-+      if (priv->capab_pbcc) {
-+              SET_BIT(cap, WF_MGMT_CAP_PBCC);
-+      }
-+      if (priv->capab_agility) {
-+              SET_BIT(cap, WF_MGMT_CAP_AGILITY);
-+      }
-+      acxlog(L_DEBUG, "caps updated from 0x%04X to 0x%04X\n",
-+                              priv->capabilities, cap);
-+      priv->capabilities = cap;
-+}
-+
-+#ifdef UNUSED
-+/***********************************************************************
-+** FIXME: check whether this function is indeed acx111 only,
-+** rename ALL relevant definitions to indicate actual card scope!
-+*/
-+void
-+acx111_s_read_configoption(wlandevice_t *priv)
-+{
-+      acx111_ie_configoption_t co, co2;
-+      int i;
-+      const u8 *pEle;
-+
-+      if (OK != acx_s_interrogate(priv, &co, ACX111_IE_CONFIG_OPTIONS) ) {
-+              return;
-+      };
-+      if (!(acx_debug & L_DEBUG))
-+              return;
-+
-+      memcpy(&co2.configoption_fixed, &co.configoption_fixed,
-+                      sizeof(co.configoption_fixed));
-+
-+      pEle = (u8 *)&co.configoption_fixed + sizeof(co.configoption_fixed) - 4;
-+
-+      co2.antennas.type = pEle[0];
-+      co2.antennas.len = pEle[1];
-+      printk("AntennaID:%02X Len:%02X Data:",
-+                      co2.antennas.type, co2.antennas.len);
-+      for (i = 0; i < pEle[1]; i++) {
-+              co2.antennas.list[i] = pEle[i+2];
-+              printk("%02X ", pEle[i+2]);
-+      }
-+      printk("\n");
-+
-+      pEle += pEle[1] + 2;
-+      co2.power_levels.type = pEle[0];
-+      co2.power_levels.len = pEle[1];
-+      printk("PowerLevelID:%02X Len:%02X Data:",
-+                      co2.power_levels.type, co2.power_levels.len);
-+      for (i = 0; i < pEle[1]*2; i++) {
-+              co2.power_levels.list[i] = pEle[i+2];
-+              printk("%02X ", pEle[i+2]);
-+      }
-+      printk("\n");
-+
-+      pEle += pEle[1]*2 + 2;
-+      co2.data_rates.type = pEle[0];
-+      co2.data_rates.len = pEle[1];
-+      printk("DataRatesID:%02X Len:%02X Data:",
-+                      co2.data_rates.type, co2.data_rates.len);
-+      for (i = 0; i < pEle[1]; i++) {
-+              co2.data_rates.list[i] = pEle[i+2];
-+              printk("%02X ", pEle[i+2]);
-+      }
-+      printk("\n");
-+
-+      pEle += pEle[1] + 2;
-+      co2.domains.type = pEle[0];
-+      co2.domains.len = pEle[1];
-+      printk("DomainID:%02X Len:%02X Data:",
-+                      co2.domains.type, co2.domains.len);
-+      for (i = 0; i < pEle[1]; i++) {
-+              co2.domains.list[i] = pEle[i+2];
-+              printk("%02X ", pEle[i+2]);
-+      }
-+      printk("\n");
-+
-+      pEle += pEle[1] + 2;
-+      co2.product_id.type = pEle[0];
-+      co2.product_id.len = pEle[1];
-+      for (i = 0; i < pEle[1]; i++) {
-+              co2.product_id.list[i] = pEle[i+2];
-+      }
-+      printk("ProductID:%02X Len:%02X Data:%.*s\n",
-+                      co2.product_id.type, co2.product_id.len,
-+                      co2.product_id.len, (char *)co2.product_id.list);
-+
-+      pEle += pEle[1] + 2;
-+      co2.manufacturer.type = pEle[0];
-+      co2.manufacturer.len = pEle[1];
-+      for (i = 0; i < pEle[1]; i++) {
-+              co2.manufacturer.list[i] = pEle[i+2];
-+      }
-+      printk("ManufacturerID:%02X Len:%02X Data:%.*s\n",
-+                      co2.manufacturer.type, co2.manufacturer.len,
-+                      co2.manufacturer.len, (char *)co2.manufacturer.list);
-+/*
-+      printk("EEPROM part:\n");
-+      for (i=0; i<58; i++) {
-+              printk("%02X =======>  0x%02X\n",
-+                          i, (u8 *)co.configoption_fixed.NVSv[i-2]);
-+      }
-+*/
-+}
-+#endif
-+
-+
-+/***********************************************************************
-+*/
-+static int __init
-+acx_e_init_module(void)
-+{
-+      int r1;
-+
-+      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_CFI)
-+      r1 = acxcfi_e_init_module();
-+#elif defined(CONFIG_ACX_PCI)
-+      r1 = acxpci_e_init_module();
-+#elif defined(CONFIG_ACX_USB)
-+      r1 = acxusb_e_init_module();
-+#else
-+      r1 = -EINVAL;
-+#endif
-+      if (r1) /* both failed! */
-+              return r1;
-+      /* return success if at least one succeeded */
-+      return 0;
-+}
-+
-+static void __exit
-+acx_e_cleanup_module(void)
-+{
-+#if defined(CONFIG_ACX_PCI)
-+      acxcfi_e_cleanup_module();
-+#elif defined(CONFIG_ACX_PCI)
-+      acxpci_e_cleanup_module();
-+#elif defined(CONFIG_ACX_USB)
-+      acxusb_e_cleanup_module();
-+#endif
-+}
-+
-+module_init(acx_e_init_module)
-+module_exit(acx_e_cleanup_module)
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/net/wireless/tiacx/conv.c bt_kernel/drivers/net/wireless/tiacx/conv.c
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/net/wireless/tiacx/conv.c   1970-01-01 02:00:00.000000000 +0200
-+++ bt_kernel/drivers/net/wireless/tiacx/conv.c        2005-09-28 23:54:23.938287000 +0300
-@@ -0,0 +1,508 @@
-+/***********************************************************************
-+** 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/config.h>
-+#include <linux/version.h>
-+#include <linux/skbuff.h>
-+#include <linux/if_arp.h>
-+#include <linux/etherdevice.h>
-+#include <linux/wireless.h>
-+#if WIRELESS_EXT >= 13
-+#include <net/iw_handler.h>
-+#endif
-+
-+#include "acx.h"
-+
-+
-+/*----------------------------------------------------------------
-+* proto_is_stt
-+*
-+* Searches the 802.1h Selective Translation Table for a given
-+* protocol.
-+*
-+* Arguments:
-+*     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.
-+*
-+* Comment:
-+*     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_l_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.
-+*
-+* Comment:
-+*     Based largely on p80211conv.c of the linux-wlan-ng project
-+*----------------------------------------------------------------*/
-+int
-+acx_l_ether_to_txbuf(wlandevice_t *priv, 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;
-+      int result = -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)) {
-+              acxlog(L_DEBUG, "zero-length skb!\n");
-+              goto end;
-+      }
-+
-+      w_hdr = (struct wlan_hdr_a3*)txbuf;
-+
-+      switch (priv->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 (skb->len >= WLAN_A4FR_MAXLEN_WEP_FCS - WLAN_FCS_LEN) {
-+                      printk("%s: can't tx oversized frame (%d bytes)\n",
-+                              priv->netdev->name, skb->len);
-+                      goto end;
-+              }
-+              memcpy(w_hdr, skb->data, skb->len);
-+              result = 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) {
-+              acxlog(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. */
-+
-+              acxlog(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;
-+      result = payload_len;
-+
-+      /* Set up the 802.11 header */
-+      switch (priv->mode) {
-+      case ACX_MODE_0_ADHOC:
-+              fc = (WF_FTYPE_DATAi | WF_FSTYPE_DATAONLYi);
-+              a1 = e_hdr->daddr;
-+              a3 = priv->bssid;
-+              break;
-+      case ACX_MODE_2_STA:
-+              fc = (WF_FTYPE_DATAi | WF_FSTYPE_DATAONLYi | WF_FC_TODSi);
-+              a1 = priv->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",
-+                              priv->netdev->name);
-+              result = -1;
-+              goto end;
-+      }
-+      if (priv->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, priv->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(result);
-+      return result;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* 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(wlandevice_t *priv, 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(priv, 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(priv)) {
-+              /* chop off the IV+ICV WEP header and footer */
-+              acxlog(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", priv->netdev->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);
-+      e_payload = (u8*) (e_snap + 1);
-+      mtu = priv->netdev->mtu;
-+
-+      acxlog(L_DATA, "rx: payload_offset %d, payload_length %d\n",
-+              payload_offset, payload_length);
-+      acxlog(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) */
-+              acxlog(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",
-+                              priv->netdev->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) */)) {
-+                      acxlog(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",
-+                                      priv->netdev->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 */
-+                      acxlog(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",
-+                                      priv->netdev->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 {
-+              acxlog(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",
-+                              priv->netdev->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 = priv->netdev;
-+      skb->protocol = eth_type_trans(skb, priv->netdev);
-+
-+#ifdef DEBUG_CONVERT
-+      if (acx_debug & L_DATA) {
-+              printk("p802.11 frame [%d]: ", RXBUF_BYTES_RCVD(rxbuf));
-+              acx_dump_bytes(w_hdr, RXBUF_BYTES_RCVD(rxbuf));
-+              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",
-+                      priv->netdev->name, buflen + 2);
-+ret_null:
-+      FN_EXIT1((int)NULL);
-+      return NULL;
-+}
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/net/wireless/tiacx/ioctl.c bt_kernel/drivers/net/wireless/tiacx/ioctl.c
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/net/wireless/tiacx/ioctl.c  1970-01-01 02:00:00.000000000 +0200
-+++ bt_kernel/drivers/net/wireless/tiacx/ioctl.c       2005-09-28 23:54:23.938287000 +0300
-@@ -0,0 +1,3060 @@
-+/***********************************************************************
-+** 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/config.h>
-+#include <linux/version.h>
-+#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>
-+#if WIRELESS_EXT >= 13
-+#include <net/iw_handler.h>
-+#endif /* WE >= 13 */
-+
-+#include "acx.h"
-+
-+
-+/*================================================================*/
-+
-+/* if you plan to reorder something, make sure to reorder all other places
-+ * accordingly! */
-+/* someone broke 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
-+};
-+
-+/* 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,
-+};
-+
-+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" },
-+};
-+
-+
-+/*------------------------------------------------------------------------------
-+ * acx_ioctl_commit
-+ *----------------------------------------------------------------------------*/
-+static int
-+acx_ioctl_commit(struct net_device *dev,
-+                                    struct iw_request_info *info,
-+                                    void *zwrq, char *extra)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+
-+      FN_ENTER;
-+
-+      acx_sem_lock(priv);
-+      if (ACX_STATE_IFACE_UP & priv->dev_state_mask)
-+              acx_s_update_card_settings(priv, 0, 0);
-+      acx_sem_unlock(priv);
-+
-+      FN_EXIT0;
-+      return OK;
-+}
-+
-+
-+/***********************************************************************
-+*/
-+static int
-+acx_ioctl_get_name(
-+      struct net_device *dev,
-+      struct iw_request_info *info,
-+      char *cwrq,
-+      char *extra)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+      static const char * const names[] = { "IEEE 802.11b+/g+", "IEEE 802.11b+" };
-+
-+      strcpy(cwrq, names[IS_ACX111(priv) ? 0 : 1]);
-+
-+      return OK;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_ioctl_set_freq
-+*----------------------------------------------------------------*/
-+static int
-+acx_ioctl_set_freq(
-+      struct net_device *dev,
-+      struct iw_request_info *info,
-+      struct iw_freq *fwrq,
-+      char *extra)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+      int channel = -1;
-+      unsigned int mult = 1;
-+      int result;
-+
-+      FN_ENTER;
-+
-+      if (fwrq->e == 0 && fwrq->m <= 1000) {
-+              /* Setting by channel number */
-+              channel = fwrq->m;
-+      } else {
-+              /* If setting by frequency, convert to a channel */
-+              int i;
-+
-+              for (i = 0; i < (6 - fwrq->e); i++)
-+                      mult *= 10;
-+
-+              for (i = 1; i <= 14; i++)
-+                      if (fwrq->m == acx_channel_freq[i - 1] * mult)
-+                              channel = i;
-+      }
-+
-+      if (channel > 14) {
-+              result = -EINVAL;
-+              goto end;
-+      }
-+
-+      acx_sem_lock(priv);
-+
-+      priv->channel = channel;
-+      /* hmm, the following code part is strange, but this is how
-+       * it was being done before... */
-+      acxlog(L_IOCTL, "Changing to channel %d\n", channel);
-+      SET_BIT(priv->set_mask, GETSET_CHANNEL);
-+
-+      result = -EINPROGRESS; /* need to call commit handler */
-+
-+      acx_sem_unlock(priv);
-+end:
-+      FN_EXIT1(result);
-+      return result;
-+}
-+
-+
-+/***********************************************************************
-+*/
-+static inline int
-+acx_ioctl_get_freq(
-+      struct net_device *dev,
-+      struct iw_request_info *info,
-+      struct iw_freq *fwrq,
-+      char *extra)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+      fwrq->e = 0;
-+      fwrq->m = priv->channel;
-+      return OK;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_ioctl_set_mode
-+*----------------------------------------------------------------*/
-+static int
-+acx_ioctl_set_mode(
-+      struct net_device *dev,
-+      struct iw_request_info *info,
-+      u32 *uwrq,
-+      char *extra)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+      int result;
-+
-+      FN_ENTER;
-+
-+      acx_sem_lock(priv);
-+
-+      switch (*uwrq) {
-+      case IW_MODE_AUTO:
-+              priv->mode = ACX_MODE_OFF;
-+              break;
-+#if WIRELESS_EXT > 14
-+      case IW_MODE_MONITOR:
-+              priv->mode = ACX_MODE_MONITOR;
-+              break;
-+#endif /* WIRELESS_EXT > 14 */
-+      case IW_MODE_ADHOC:
-+              priv->mode = ACX_MODE_0_ADHOC;
-+              break;
-+      case IW_MODE_INFRA:
-+              priv->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");
-+              priv->mode = ACX_MODE_3_AP;
-+              break;
-+      case IW_MODE_REPEAT:
-+      case IW_MODE_SECOND:
-+      default:
-+              result = -EOPNOTSUPP;
-+              goto end_unlock;
-+      }
-+
-+      acxlog(L_ASSOC, "new priv->mode=%d\n", priv->mode);
-+      SET_BIT(priv->set_mask, GETSET_MODE);
-+      result = -EINPROGRESS;
-+
-+end_unlock:
-+      acx_sem_unlock(priv);
-+
-+      FN_EXIT1(result);
-+      return result;
-+}
-+
-+
-+/***********************************************************************
-+*/
-+static int
-+acx_ioctl_get_mode(
-+      struct net_device *dev,
-+      struct iw_request_info *info,
-+      u32 *uwrq,
-+      char *extra)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+      int result = 0;
-+
-+      switch (priv->mode) {
-+      case ACX_MODE_OFF:
-+              *uwrq = IW_MODE_AUTO; break;
-+#if WIRELESS_EXT > 14
-+      case ACX_MODE_MONITOR:
-+              *uwrq = IW_MODE_MONITOR; break;
-+#endif /* WIRELESS_EXT > 14 */
-+      case ACX_MODE_0_ADHOC:
-+              *uwrq = IW_MODE_ADHOC; break;
-+      case ACX_MODE_2_STA:
-+              *uwrq = IW_MODE_INFRA; break;
-+      case ACX_MODE_3_AP:
-+              *uwrq = IW_MODE_MASTER; break;
-+      default:
-+              result = -EOPNOTSUPP;
-+      }
-+      return result;
-+}
-+
-+
-+/***********************************************************************
-+*/
-+static int
-+acx_ioctl_set_sens(
-+      struct net_device *dev,
-+      struct iw_request_info *info,
-+      struct iw_param *vwrq,
-+      char *extra)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+
-+      acx_sem_lock(priv);
-+
-+      priv->sensitivity = (1 == vwrq->disabled) ? 0 : vwrq->value;
-+      SET_BIT(priv->set_mask, GETSET_SENSITIVITY);
-+
-+      acx_sem_unlock(priv);
-+
-+      return -EINPROGRESS;
-+}
-+
-+
-+/***********************************************************************
-+*/
-+static int
-+acx_ioctl_get_sens(
-+      struct net_device *dev,
-+      struct iw_request_info *info,
-+      struct iw_param *vwrq,
-+      char *extra)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+
-+      /* acx_sem_lock(priv); */
-+
-+      vwrq->value = priv->sensitivity;
-+      vwrq->disabled = (vwrq->value == 0);
-+      vwrq->fixed = 1;
-+
-+      /* acx_sem_unlock(priv); */
-+
-+      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 *dev,
-+      struct iw_request_info *info,
-+      struct sockaddr *awrq,
-+      char *extra)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+      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(priv->ap, ap);
-+
-+      /* We want to start rescan in managed or ad-hoc mode,
-+      ** otherwise just set priv->ap.
-+      ** "iwconfig <if> ap <mac> mode managed": we must be able
-+      ** to set ap _first_ and _then_ set mode */
-+      switch (priv->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(priv->ap);
-+                      acxlog(L_IOCTL, "Not reassociating\n");
-+              } else {
-+                      acxlog(L_IOCTL, "Forcing reassociation\n");
-+                      SET_BIT(priv->set_mask, GETSET_RESCAN);
-+              }
-+              break;
-+      }
-+      result = -EINPROGRESS;
-+end:
-+      FN_EXIT1(result);
-+      return result;
-+}
-+
-+
-+/***********************************************************************
-+*/
-+static int
-+acx_ioctl_get_ap(
-+      struct net_device *dev,
-+      struct iw_request_info *info,
-+      struct sockaddr *awrq,
-+      char *extra)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+
-+      if (ACX_STATUS_4_ASSOCIATED == priv->status) {
-+              /* as seen in Aironet driver, airo.c */
-+              MAC_COPY(awrq->sa_data, priv->bssid);
-+      } else {
-+              MAC_ZERO(awrq->sa_data);
-+      }
-+      awrq->sa_family = ARPHRD_ETHER;
-+      return OK;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_ioctl_get_aplist
-+*
-+* Comment: deprecated in favour 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 *dev,
-+      struct iw_request_info *info,
-+      struct iw_point *dwrq,
-+      char *extra)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+      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 != priv->mode) {
-+              result = -EOPNOTSUPP;
-+              goto end;
-+      }
-+
-+      cur = 0;
-+      for (i = 0; i < VEC_SIZE(priv->sta_list); i++) {
-+              struct client *bss = &priv->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 *dev,
-+      struct iw_request_info *info,
-+      struct iw_param *vwrq,
-+      char *extra)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+      int result;
-+
-+      FN_ENTER;
-+
-+      acx_sem_lock(priv);
-+
-+      /* don't start scan if device is not up yet */
-+      if (!(priv->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(priv);
-+      result = OK;
-+
-+end_unlock:
-+      acx_sem_unlock(priv);
-+/* end: */
-+      FN_EXIT1(result);
-+      return result;
-+}
-+
-+
-+#if WIRELESS_EXT > 13
-+/***********************************************************************
-+** acx_s_scan_add_station
-+*/
-+/* helper. not sure wheter it's really a _s_leeping fn */
-+static char*
-+acx_s_scan_add_station(
-+      wlandevice_t *priv,
-+      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;
-+      acxlog(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;
-+              acxlog(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;
-+      acxlog(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;
-+      acxlog(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;
-+      acxlog(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 = bitpos2ratebyte;
-+      while (rate) {
-+              if (rate & 1) {
-+                      iwe.u.bitrate.value = *p * 500000; /* units of 500kb/s */
-+                      acxlog(L_IOCTL, "scan, rate: %d\n", iwe.u.bitrate.value);
-+                      ptr = 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 *dev,
-+      struct iw_request_info *info,
-+      struct iw_point *dwrq,
-+      char *extra)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+      char *ptr = extra;
-+      int i;
-+      int result = OK;
-+
-+      FN_ENTER;
-+
-+      acx_sem_lock(priv);
-+
-+      /* no scan available if device is not up yet */
-+      if (!(priv->dev_state_mask & ACX_STATE_IFACE_UP)) {
-+              acxlog(L_IOCTL, "iface not up yet\n");
-+              result = -EAGAIN;
-+              goto end_unlock;
-+      }
-+#if 0 /* Why is this needed? If needed, add a comment */
-+      if (priv->scan_start && time_before(jiffies, priv->scan_start + 3*HZ)) {
-+              acxlog(L_IOCTL, "scan in progress, no results yet\n");
-+              result = -EAGAIN;
-+              goto end_unlock;
-+      }
-+#endif
-+
-+#ifdef ENODATA_TO_BE_USED_AFTER_SCAN_ERROR_ONLY
-+      if (priv->bss_table_count == 0) {
-+              /* no stations found */
-+              result = -ENODATA;
-+              goto end_unlock;
-+      }
-+#endif
-+
-+      for (i = 0; i < VEC_SIZE(priv->sta_list); i++) {
-+              struct client *bss = &priv->sta_list[i];
-+              if (!bss->used) continue;
-+              ptr = acx_s_scan_add_station(priv, ptr,
-+                      extra + IW_SCAN_MAX_DATA, bss);
-+      }
-+      dwrq->length = ptr - extra;
-+      dwrq->flags = 0;
-+
-+end_unlock:
-+      acx_sem_unlock(priv);
-+/* end: */
-+      FN_EXIT1(result);
-+      return result;
-+}
-+#endif /* WIRELESS_EXT > 13 */
-+
-+
-+/*----------------------------------------------------------------
-+* acx_ioctl_set_essid
-+*----------------------------------------------------------------*/
-+static int
-+acx_ioctl_set_essid(
-+      struct net_device *dev,
-+      struct iw_request_info *info,
-+      struct iw_point *dwrq,
-+      char *extra)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+      int len = dwrq->length;
-+      int result;
-+
-+      FN_ENTER;
-+
-+      acxlog(L_IOCTL, "Set ESSID '%*s', length %d, flags 0x%04X\n",
-+                                      len, extra, len, dwrq->flags);
-+
-+      if (len < 0) {
-+              result = -EINVAL;
-+              goto end;
-+      }
-+
-+      acx_sem_lock(priv);
-+
-+      /* ESSID disabled? */
-+      if (0 == dwrq->flags) {
-+              priv->essid_active = 0;
-+
-+      } else {
-+              if (dwrq->length > IW_ESSID_MAX_SIZE+1) {
-+                      result = -E2BIG;
-+                      goto end_unlock;
-+              }
-+
-+              if (len > sizeof(priv->essid))
-+                      len = sizeof(priv->essid);
-+              memcpy(priv->essid, extra, len-1);
-+              priv->essid[len-1] = '\0';
-+              /* Paranoia: just in case there is a '\0'... */
-+              priv->essid_len = strlen(priv->essid);
-+              priv->essid_active = 1;
-+      }
-+
-+      SET_BIT(priv->set_mask, GETSET_RESCAN);
-+
-+      result = -EINPROGRESS;
-+
-+end_unlock:
-+      acx_sem_unlock(priv);
-+end:
-+      FN_EXIT1(result);
-+      return result;
-+}
-+
-+
-+/***********************************************************************
-+*/
-+static int
-+acx_ioctl_get_essid(
-+      struct net_device *dev,
-+      struct iw_request_info *info,
-+      struct iw_point *dwrq,
-+      char *extra)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+
-+      dwrq->flags = priv->essid_active;
-+      if (priv->essid_active) {
-+              memcpy(extra, priv->essid, priv->essid_len);
-+              extra[priv->essid_len] = '\0';
-+              dwrq->length = priv->essid_len + 1;
-+              dwrq->flags = 1;
-+      }
-+      return OK;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_l_update_client_rates
-+*----------------------------------------------------------------*/
-+static void
-+acx_l_update_client_rates(wlandevice_t *priv, u16 rate)
-+{
-+      int i;
-+      for (i = 0; i < VEC_SIZE(priv->sta_list); i++) {
-+              client_t *clt = &priv->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(priv, 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);
-+              }
-+              clt->fallback_count = clt->stepup_count = 0;
-+              clt->ignore_count = 16;
-+      }
-+      switch (priv->mode) {
-+      case ACX_MODE_2_STA:
-+              if (priv->ap_client && !priv->ap_client->used) {
-+                      /* Owwww... we kicked our AP!! :) */
-+                      SET_BIT(priv->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 *dev,
-+      struct iw_request_info *info,
-+      struct iw_param *vwrq,
-+      char *extra)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+      u16 txrate_cfg = 1;
-+      unsigned long flags;
-+      int autorate;
-+      int result = -EINVAL;
-+
-+      FN_ENTER;
-+      acxlog(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(priv) ? 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(priv)) {
-+              txrate_cfg &= RATE111_ACX100_COMPAT;
-+              if (!txrate_cfg) {
-+                      result = -ENOTSUPP; /* rate is not supported by acx100 */
-+                      goto end;
-+              }
-+      }
-+
-+      acx_sem_lock(priv);
-+      acx_lock(priv, flags);
-+
-+      priv->rate_auto = autorate;
-+      priv->rate_oper = txrate_cfg;
-+      priv->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 */
-+              priv->rate_basic &= RATE111_80211B_COMPAT;
-+      }
-+      priv->rate_bcast = 1 << lowest_bit(txrate_cfg);
-+      if (IS_ACX100(priv))
-+              priv->rate_bcast100 = acx_rate111to100(priv->rate_bcast);
-+      acx_l_update_ratevector(priv);
-+      acx_l_update_client_rates(priv, txrate_cfg);
-+
-+      /* Do/don't do tx rate fallback; beacon contents and rate */
-+      SET_BIT(priv->set_mask, SET_RATE_FALLBACK|SET_TEMPLATES);
-+      result = -EINPROGRESS;
-+
-+      acx_unlock(priv, flags);
-+      acx_sem_unlock(priv);
-+end:
-+      FN_EXIT1(result);
-+      return result;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_ioctl_get_rate
-+*----------------------------------------------------------------*/
-+static int
-+acx_ioctl_get_rate(
-+      struct net_device *dev,
-+      struct iw_request_info *info,
-+      struct iw_param *vwrq,
-+      char *extra)
-+{
-+      /* TODO: remember rate of last tx, show it. think about multiple peers... */
-+      wlandevice_t *priv = netdev_priv(dev);
-+      vwrq->value = acx111_rate_tbl[highest_bit(priv->rate_oper)];
-+      vwrq->fixed = !priv->rate_auto;
-+      vwrq->disabled = 0;
-+      return OK;
-+}
-+
-+static int
-+acx_ioctl_set_rts(
-+      struct net_device *dev,
-+      struct iw_request_info *info,
-+      struct iw_param *vwrq,
-+      char *extra)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+      int val = vwrq->value;
-+
-+      if (vwrq->disabled)
-+              val = 2312;
-+      if ((val < 0) || (val > 2312))
-+              return -EINVAL;
-+
-+      priv->rts_threshold = val;
-+      return OK;
-+}
-+
-+static inline int
-+acx_ioctl_get_rts(
-+      struct net_device *dev,
-+      struct iw_request_info *info,
-+      struct iw_param *vwrq,
-+      char *extra)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+
-+      vwrq->value = priv->rts_threshold;
-+      vwrq->disabled = (vwrq->value >= 2312);
-+      vwrq->fixed = 1;
-+      return OK;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_ioctl_set_encode
-+*----------------------------------------------------------------*/
-+static int
-+acx_ioctl_set_encode(
-+      struct net_device *dev,
-+      struct iw_request_info *info,
-+      struct iw_point *dwrq,
-+      char *extra)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+      int index;
-+      int result;
-+
-+      FN_ENTER;
-+      acxlog(L_IOCTL,
-+             "Set Encoding flags=0x%04X, size=%d, key: %s\n",
-+             dwrq->flags, dwrq->length, extra ? "set" : "No key");
-+
-+      acx_sem_lock(priv);
-+
-+      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)priv->wep_current_index;
-+
-+              if (0 == (dwrq->flags & IW_ENCODE_NOKEY)) {
-+                      if (dwrq->length > 29)
-+                              dwrq->length = 29; /* restrict it */
-+
-+                      if (dwrq->length > 13)
-+                              priv->wep_keys[index].size = 29; /* 29*8 == 232, WEP256 */
-+                      else
-+                      if (dwrq->length > 5)
-+                              priv->wep_keys[index].size = 13; /* 13*8 == 104bit, WEP128 */
-+                      else
-+                      if (dwrq->length > 0)
-+                              priv->wep_keys[index].size = 5; /* 5*8 == 40bit, WEP64 */
-+                      else
-+                              /* disable key */
-+                              priv->wep_keys[index].size = 0;
-+
-+                      memset(priv->wep_keys[index].key, 0, sizeof(priv->wep_keys[index].key));
-+                      memcpy(priv->wep_keys[index].key, extra, dwrq->length);
-+              }
-+
-+      } else {
-+              /* set transmit key */
-+              if ((index >= 0) && (index <= 3))
-+                      priv->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;
-+                      }
-+      }
-+
-+      priv->wep_enabled = !(dwrq->flags & IW_ENCODE_DISABLED);
-+
-+      if (dwrq->flags & IW_ENCODE_OPEN) {
-+              priv->auth_alg = WLAN_AUTH_ALG_OPENSYSTEM;
-+              priv->wep_restricted = 0;
-+
-+      } else if (dwrq->flags & IW_ENCODE_RESTRICTED) {
-+              priv->auth_alg = WLAN_AUTH_ALG_SHAREDKEY;
-+              priv->wep_restricted = 1;
-+      }
-+
-+      /* set flag to make sure the card WEP settings get updated */
-+      SET_BIT(priv->set_mask, GETSET_WEP);
-+
-+      acxlog(L_IOCTL, "len=%d, key at 0x%p, flags=0x%X\n",
-+             dwrq->length, extra,
-+             dwrq->flags);
-+
-+      for (index = 0; index <= 3; index++) {
-+              if (priv->wep_keys[index].size) {
-+                      acxlog(L_IOCTL,
-+                              "index=%d, size=%d, key at 0x%p\n",
-+                              priv->wep_keys[index].index,
-+                              (int) priv->wep_keys[index].size,
-+                              priv->wep_keys[index].key);
-+              }
-+      }
-+      result = -EINPROGRESS;
-+
-+end_unlock:
-+      acx_sem_unlock(priv);
-+
-+      FN_EXIT1(result);
-+      return result;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_ioctl_get_encode
-+*----------------------------------------------------------------*/
-+static int
-+acx_ioctl_get_encode(
-+      struct net_device *dev,
-+      struct iw_request_info *info,
-+      struct iw_point *dwrq,
-+      char *extra)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+      int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
-+
-+      if (priv->wep_enabled == 0) {
-+              dwrq->flags = IW_ENCODE_DISABLED;
-+
-+      } else {
-+              if ((index < 0) || (index > 3))
-+                      index = (int)priv->wep_current_index;
-+
-+              dwrq->flags =
-+                      (priv->wep_restricted == 1) ? IW_ENCODE_RESTRICTED : IW_ENCODE_OPEN;
-+              dwrq->length = priv->wep_keys[index].size;
-+
-+              memcpy(extra,
-+                           priv->wep_keys[index].key,
-+                           priv->wep_keys[index].size);
-+      }
-+
-+      /* set the current index */
-+      SET_BIT(dwrq->flags, index + 1);
-+
-+      acxlog(L_IOCTL, "len=%d, key=%p, flags=0x%X\n",
-+             dwrq->length, dwrq->pointer,
-+             dwrq->flags);
-+
-+      return OK;
-+}
-+
-+
-+/***********************************************************************
-+*/
-+static int
-+acx_ioctl_set_power(
-+      struct net_device *dev,
-+      struct iw_request_info *info,
-+      struct iw_param *vwrq,
-+      char *extra)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+
-+      acxlog(L_IOCTL, "Set 802.11 Power Save flags=0x%04X\n", vwrq->flags);
-+      if (vwrq->disabled) {
-+              CLEAR_BIT(priv->ps_wakeup_cfg, PS_CFG_ENABLE);
-+              SET_BIT(priv->set_mask, GETSET_POWER_80211);
-+              return -EINPROGRESS;
-+      }
-+      if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
-+              u16 ps_timeout = (vwrq->value * 1024) / 1000;
-+
-+              if (ps_timeout > 255)
-+                      ps_timeout = 255;
-+              acxlog(L_IOCTL, "setting PS timeout value to %d time units "
-+                              "due to %dus\n", ps_timeout, vwrq->value);
-+              priv->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;
-+              acxlog(L_IOCTL, "setting PS period value to %d periods "
-+                              "due to %dus\n", ps_periods, vwrq->value);
-+              priv->ps_listen_interval = ps_periods;
-+              CLEAR_BIT(priv->ps_wakeup_cfg, PS_CFG_WAKEUP_MODE_MASK);
-+              SET_BIT(priv->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(priv->ps_options, PS_OPT_STILL_RCV_BCASTS);
-+                      break;
-+              case IW_POWER_MULTICAST_R:
-+                      SET_BIT(priv->ps_options, PS_OPT_STILL_RCV_BCASTS);
-+                      break;
-+              case IW_POWER_ALL_R:
-+                      SET_BIT(priv->ps_options, PS_OPT_STILL_RCV_BCASTS);
-+                      break;
-+              case IW_POWER_ON:
-+                      break;
-+              default:
-+                      acxlog(L_IOCTL, "unknown PS mode\n");
-+                      return -EINVAL;
-+      }
-+
-+      SET_BIT(priv->ps_wakeup_cfg, PS_CFG_ENABLE);
-+      SET_BIT(priv->set_mask, GETSET_POWER_80211);
-+
-+      return -EINPROGRESS;
-+
-+}
-+
-+
-+/***********************************************************************
-+*/
-+static int
-+acx_ioctl_get_power(
-+      struct net_device *dev,
-+      struct iw_request_info *info,
-+      struct iw_param *vwrq,
-+      char *extra)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+
-+      acxlog(L_IOCTL, "Get 802.11 Power Save flags = 0x%04X\n", vwrq->flags);
-+      vwrq->disabled = ((priv->ps_wakeup_cfg & PS_CFG_ENABLE) == 0);
-+      if (vwrq->disabled)
-+              return OK;
-+      if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
-+              vwrq->value = priv->ps_hangover_period * 1000 / 1024;
-+              vwrq->flags = IW_POWER_TIMEOUT;
-+      } else {
-+              vwrq->value = priv->ps_listen_interval * 1000000;
-+              vwrq->flags = IW_POWER_PERIOD|IW_POWER_RELATIVE;
-+      }
-+      if (priv->ps_options & PS_OPT_STILL_RCV_BCASTS)
-+              SET_BIT(vwrq->flags, IW_POWER_ALL_R);
-+      else
-+              SET_BIT(vwrq->flags, IW_POWER_UNICAST_R);
-+
-+      return OK;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_ioctl_get_txpow
-+*----------------------------------------------------------------*/
-+static inline int
-+acx_ioctl_get_txpow(
-+      struct net_device *dev,
-+      struct iw_request_info *info,
-+      struct iw_param *vwrq,
-+      char *extra)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+
-+      vwrq->flags = IW_TXPOW_DBM;
-+      vwrq->disabled = 0;
-+      vwrq->fixed = 1;
-+      vwrq->value = priv->tx_level_dbm;
-+
-+      acxlog(L_IOCTL, "get txpower:%d dBm\n", priv->tx_level_dbm);
-+
-+      return OK;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_ioctl_set_txpow
-+*----------------------------------------------------------------*/
-+static int
-+acx_ioctl_set_txpow(
-+      struct net_device *dev,
-+      struct iw_request_info *info,
-+      struct iw_param *vwrq,
-+      char *extra)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+      int result;
-+
-+      FN_ENTER;
-+      acxlog(L_IOCTL, "set txpower:%d, disabled:%d, flags:0x%04X\n",
-+                      vwrq->value, vwrq->disabled, vwrq->flags);
-+
-+      acx_sem_lock(priv);
-+
-+      if (vwrq->disabled != priv->tx_disabled) {
-+              SET_BIT(priv->set_mask, GETSET_TX); /* Tx status needs update later */
-+      }
-+
-+      priv->tx_disabled = vwrq->disabled;
-+      if (vwrq->value == -1) {
-+              if (vwrq->disabled) {
-+                      priv->tx_level_dbm = 0;
-+                      acxlog(L_IOCTL, "disable radio tx\n");
-+              } else {
-+                      /* priv->tx_level_auto = 1; */
-+                      acxlog(L_IOCTL, "set tx power auto (NIY)\n");
-+              }
-+      } else {
-+              priv->tx_level_dbm = vwrq->value <= 20 ? vwrq->value : 20;
-+              /* priv->tx_level_auto = 0; */
-+              acxlog(L_IOCTL, "set txpower=%d dBm\n", priv->tx_level_dbm);
-+      }
-+      SET_BIT(priv->set_mask, GETSET_TXPOWER);
-+
-+      result = -EINPROGRESS;
-+
-+      acx_sem_unlock(priv);
-+
-+      FN_EXIT1(result);
-+      return result;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_ioctl_get_range
-+*----------------------------------------------------------------*/
-+static int
-+acx_ioctl_get_range(
-+      struct net_device *dev,
-+      struct iw_request_info *info,
-+      struct iw_point *dwrq,
-+      char *extra)
-+{
-+      if (dwrq->pointer != NULL) {
-+              struct iw_range *range = (struct iw_range *)extra;
-+              wlandevice_t *priv = netdev_priv(dev);
-+              unsigned int i;
-+
-+              dwrq->length = sizeof(struct iw_range);
-+              memset(range, 0, sizeof(struct iw_range));
-+              range->num_channels = 0;
-+              for (i = 1; i <= 14; i++) {
-+                      if (priv->reg_dom_chanmask & (1 << (i - 1))) {
-+                              range->freq[range->num_channels].i = i;
-+                              range->freq[range->num_channels].m = acx_channel_freq[i - 1] * 100000;
-+                              range->freq[range->num_channels++].e = 1; /* MHz values */
-+                      }
-+              }
-+              range->num_frequency = range->num_channels;
-+
-+              range->min_rts = 0;
-+              range->max_rts = 2312;
-+              /* range->min_frag = 256;
-+               * range->max_frag = 2312;
-+               */
-+
-+              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;
-+
-+              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;
-+
-+              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(priv))
-+                      range->sensitivity = 0;
-+              else if (IS_ACX111(priv))
-+                      range->sensitivity = 3;
-+              else
-+                      range->sensitivity = 255;
-+
-+              for (i=0; i < priv->rate_supported_len; i++) {
-+                      range->bitrate[i] = (priv->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;
-+      }
-+
-+      return OK;
-+}
-+
-+
-+/*================================================================*/
-+/* Private functions                                            */
-+/*================================================================*/
-+
-+#if WIRELESS_EXT < 13
-+/*----------------------------------------------------------------
-+* acx_ioctl_get_iw_priv
-+*
-+* Comment: I added the monitor mode and changed the stuff below
-+* to look more like the orinoco driver
-+*----------------------------------------------------------------*/
-+static int
-+acx_ioctl_get_iw_priv(struct iwreq *iwr)
-+{
-+      int result = -EINVAL;
-+
-+      if (!iwr->u.data.pointer)
-+              return -EINVAL;
-+      result = verify_area(VERIFY_WRITE, iwr->u.data.pointer,
-+                      sizeof(acx_ioctl_private_args));
-+      if (result)
-+              return result;
-+
-+      iwr->u.data.length = VEC_SIZE(acx_ioctl_private_args);
-+      if (copy_to_user(iwr->u.data.pointer, acx_ioctl_private_args, sizeof(acx_ioctl_private_args)) != 0)
-+              result = -EFAULT;
-+
-+      return result;
-+}
-+#endif
-+
-+
-+/*----------------------------------------------------------------
-+* acx_ioctl_get_nick
-+*----------------------------------------------------------------*/
-+static inline int
-+acx_ioctl_get_nick(
-+      struct net_device *dev,
-+      struct iw_request_info *info,
-+      struct iw_point *dwrq,
-+      char *extra)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+
-+      /* FIXME : consider spinlock here */
-+      strcpy(extra, priv->nick);
-+      /* FIXME : consider spinlock here */
-+
-+      dwrq->length = strlen(extra) + 1;
-+
-+      return OK;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_ioctl_set_nick
-+*----------------------------------------------------------------*/
-+static int
-+acx_ioctl_set_nick(
-+      struct net_device *dev,
-+      struct iw_request_info *info,
-+      struct iw_point *dwrq,
-+      char *extra)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+      int result;
-+
-+      FN_ENTER;
-+
-+      acx_sem_lock(priv);
-+
-+      if (dwrq->length > IW_ESSID_MAX_SIZE + 1) {
-+              result = -E2BIG;
-+              goto end_unlock;
-+      }
-+
-+      /* extra includes trailing \0, so it's ok */
-+      strcpy(priv->nick, extra);
-+      result = OK;
-+
-+end_unlock:
-+      acx_sem_unlock(priv);
-+
-+      FN_EXIT1(result);
-+      return result;
-+}
-+
-+
-+/*------------------------------------------------------------------------------
-+ * acx_ioctl_get_retry
-+ *----------------------------------------------------------------------------*/
-+static int
-+acx_ioctl_get_retry(
-+      struct net_device *dev,
-+      struct iw_request_info *info,
-+      struct iw_param *vwrq,
-+      char *extra)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+      unsigned int type = vwrq->flags & IW_RETRY_TYPE;
-+      unsigned int modifier = vwrq->flags & IW_RETRY_MODIFIER;
-+      int result;
-+
-+      acx_sem_lock(priv);
-+
-+      /* return the short retry number by default */
-+      if (type == IW_RETRY_LIFETIME) {
-+              vwrq->flags = IW_RETRY_LIFETIME;
-+              vwrq->value = priv->msdu_lifetime;
-+      } else if (modifier == IW_RETRY_MAX) {
-+              vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
-+              vwrq->value = priv->long_retry;
-+      } else {
-+              vwrq->flags = IW_RETRY_LIMIT;
-+              if (priv->long_retry != priv->short_retry)
-+                      SET_BIT(vwrq->flags, IW_RETRY_MIN);
-+              vwrq->value = priv->short_retry;
-+      }
-+
-+      /* can't be disabled */
-+      vwrq->disabled = (u8)0;
-+      result = OK;
-+
-+      acx_sem_unlock(priv);
-+
-+      return result;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_ioctl_set_retry
-+*----------------------------------------------------------------*/
-+static int
-+acx_ioctl_set_retry(
-+      struct net_device *dev,
-+      struct iw_request_info *info,
-+      struct iw_param *vwrq,
-+      char *extra)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+      int result;
-+
-+      FN_ENTER;
-+
-+      if (!vwrq) {
-+              result = -EFAULT;
-+              goto end;
-+      }
-+      if (vwrq->disabled) {
-+              result = -EINVAL;
-+              goto end;
-+      }
-+
-+      acx_sem_lock(priv);
-+
-+      result = -EINVAL;
-+      if (IW_RETRY_LIMIT == (vwrq->flags & IW_RETRY_TYPE)) {
-+              printk("old retry limits: short %d long %d\n",
-+                              priv->short_retry, priv->long_retry);
-+              if (vwrq->flags & IW_RETRY_MAX) {
-+                      priv->long_retry = vwrq->value;
-+              } else if (vwrq->flags & IW_RETRY_MIN) {
-+                      priv->short_retry = vwrq->value;
-+              } else {
-+                      /* no modifier: set both */
-+                      priv->long_retry = vwrq->value;
-+                      priv->short_retry = vwrq->value;
-+              }
-+              printk("new retry limits: short %d long %d\n",
-+                              priv->short_retry, priv->long_retry);
-+              SET_BIT(priv->set_mask, GETSET_RETRY);
-+              result = -EINPROGRESS;
-+      }
-+      else if (vwrq->flags & IW_RETRY_LIFETIME) {
-+              priv->msdu_lifetime = vwrq->value;
-+              printk("new MSDU lifetime: %d\n", priv->msdu_lifetime);
-+              SET_BIT(priv->set_mask, SET_MSDU_LIFETIME);
-+              result = -EINPROGRESS;
-+      }
-+
-+      acx_sem_unlock(priv);
-+end:
-+      FN_EXIT1(result);
-+      return result;
-+}
-+
-+
-+/******************************* private ioctls ******************************/
-+
-+
-+/*----------------------------------------------------------------
-+* acx_ioctl_set_debug
-+*----------------------------------------------------------------*/
-+#if ACX_DEBUG
-+static int
-+acx_ioctl_set_debug(
-+      struct net_device *dev,
-+      struct iw_request_info *info,
-+      struct iw_param *vwrq,
-+      char *extra)
-+{
-+      unsigned int debug_new = *((unsigned int *)extra);
-+      int result = -EINVAL;
-+
-+      acxlog(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 const char * const
-+reg_domain_strings[] = {
-+      " 1-11 FCC (USA)",
-+      " 1-11 DOC/IC (Canada)",
-+      /* BTW: WLAN use in ETSI is regulated by
-+       * ETSI standard EN 300 328-2 V1.1.2 */
-+      " 1-13 ETSI (Europe)",
-+      "10-11 Spain",
-+      "10-13 France",
-+      "   14 MKK (Japan)",
-+      " 1-14 MKK1",
-+      "  3-9 Israel (not all firmware versions)",
-+      NULL /* needs to remain as last entry */
-+};
-+
-+static int
-+acx_ioctl_list_reg_domain(
-+      struct net_device *dev,
-+      struct iw_request_info *info,
-+      struct iw_param *vwrq,
-+      char *extra)
-+{
-+
-+      int i = 1;
-+      const char * const *entry = 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 *dev,
-+      struct iw_request_info *info,
-+      struct iw_param *vwrq,
-+      char *extra)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+      int result;
-+
-+      FN_ENTER;
-+
-+      if ((*extra < 1) || ((size_t)*extra > reg_domain_ids_len)) {
-+              result = -EINVAL;
-+              goto end;
-+      }
-+
-+      acx_sem_lock(priv);
-+
-+      priv->reg_dom_id = reg_domain_ids[*extra - 1];
-+      SET_BIT(priv->set_mask, GETSET_REG_DOMAIN);
-+
-+      result = -EINPROGRESS;
-+
-+      acx_sem_unlock(priv);
-+end:
-+      FN_EXIT1(result);
-+      return result;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_ioctl_get_reg_domain
-+*----------------------------------------------------------------*/
-+static int
-+acx_ioctl_get_reg_domain(
-+      struct net_device *dev,
-+      struct iw_request_info *info,
-+      struct iw_param *vwrq,
-+      char *extra)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+      int dom,i;
-+
-+      /* no locking */
-+      dom = priv->reg_dom_id;
-+
-+      for (i=1; i <= 7; i++) {
-+              if (reg_domain_ids[i-1] == dom) {
-+                      acxlog(L_IOCTL, "regulatory domain is currently set "
-+                              "to %d (0x%X): %s\n", i, dom,
-+                              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 *dev,
-+      struct iw_request_info *info,
-+      struct iw_param *vwrq,
-+      char *extra)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+      int i;
-+      int result;
-+
-+      FN_ENTER;
-+
-+      if ((unsigned char)*extra > 2) {
-+              result = -EINVAL;
-+              goto end;
-+      }
-+
-+      acx_sem_lock(priv);
-+
-+      priv->preamble_mode = (u8)*extra;
-+      switch (priv->preamble_mode) {
-+      case 0: /* long */
-+              priv->preamble_cur = 0;
-+              break;
-+      case 1:
-+              /* short, kick incapable peers */
-+              priv->preamble_cur = 1;
-+              for (i = 0; i < VEC_SIZE(priv->sta_list); i++) {
-+                      client_t *clt = &priv->sta_list[i];
-+                      if (!clt->used) continue;
-+                      if (!(clt->cap_info & WF_MGMT_CAP_SHORT)) {
-+                              clt->used = CLIENT_EMPTY_SLOT_0;
-+                      }
-+              }
-+              switch (priv->mode) {
-+              case ACX_MODE_2_STA:
-+                      if (priv->ap_client && !priv->ap_client->used) {
-+                              /* We kicked our AP :) */
-+                              SET_BIT(priv->set_mask, GETSET_RESCAN);
-+                      }
-+              }
-+              break;
-+      case 2: /* auto. short only if all peers are short-capable */
-+              priv->preamble_cur = 1;
-+              for (i = 0; i < VEC_SIZE(priv->sta_list); i++) {
-+                      client_t *clt = &priv->sta_list[i];
-+                      if (!clt->used) continue;
-+                      if (!(clt->cap_info & WF_MGMT_CAP_SHORT)) {
-+                              priv->preamble_cur = 0;
-+                              break;
-+                      }
-+              }
-+              break;
-+      }
-+      printk("new short preamble setting: configured %s, active %s\n",
-+                      preamble_modes[priv->preamble_mode],
-+                      preamble_modes[priv->preamble_cur]);
-+      result = OK;
-+
-+      acx_sem_unlock(priv);
-+end:
-+      FN_EXIT1(result);
-+      return result;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_ioctl_get_short_preamble
-+*----------------------------------------------------------------*/
-+static int
-+acx_ioctl_get_short_preamble(
-+      struct net_device *dev,
-+      struct iw_request_info *info,
-+      struct iw_param *vwrq,
-+      char *extra)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+
-+      acx_sem_lock(priv);
-+
-+      printk("current short preamble setting: configured %s, active %s\n",
-+                      preamble_modes[priv->preamble_mode],
-+                      preamble_modes[priv->preamble_cur]);
-+
-+      *extra = (char)priv->preamble_mode;
-+
-+      acx_sem_unlock(priv);
-+
-+      return OK;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_ioctl_set_antenna
-+*
-+* Comment: 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 *dev,
-+      struct iw_request_info *info,
-+      struct iw_param *vwrq,
-+      char *extra)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+
-+      acx_sem_lock(priv);
-+
-+      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",
-+                   priv->antenna, (u8)*extra);
-+
-+      priv->antenna = (u8)*extra;
-+      SET_BIT(priv->set_mask, GETSET_ANTENNA);
-+
-+      acx_sem_unlock(priv);
-+
-+      return -EINPROGRESS;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_ioctl_get_antenna
-+*----------------------------------------------------------------*/
-+static int
-+acx_ioctl_get_antenna(
-+      struct net_device *dev,
-+      struct iw_request_info *info,
-+      struct iw_param *vwrq,
-+      char *extra)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+
-+      /* 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", priv->antenna);
-+
-+      return 0;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_ioctl_set_rx_antenna
-+*
-+*
-+* Arguments:
-+*     0 = antenna1; 1 = antenna2; 2 = full diversity; 3 = partial diversity
-+* Comment: Could anybody test which antenna is the external one
-+*----------------------------------------------------------------*/
-+static int
-+acx_ioctl_set_rx_antenna(
-+      struct net_device *dev,
-+      struct iw_request_info *info,
-+      struct iw_param *vwrq,
-+      char *extra)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+      int result;
-+
-+      FN_ENTER;
-+
-+      if (*extra > 3) {
-+              result = -EINVAL;
-+              goto end;
-+      }
-+
-+      printk("old antenna value: 0x%02X\n", priv->antenna);
-+
-+      acx_sem_lock(priv);
-+
-+      priv->antenna &= 0x3f;
-+      SET_BIT(priv->antenna, (*extra << 6));
-+      SET_BIT(priv->set_mask, GETSET_ANTENNA);
-+      printk("new antenna value: 0x%02X\n", priv->antenna);
-+      result = -EINPROGRESS;
-+
-+      acx_sem_unlock(priv);
-+end:
-+      FN_EXIT1(result);
-+      return result;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_ioctl_set_tx_antenna
-+*
-+*
-+* Arguments: 0 == antenna2; 1 == antenna1;
-+* Comment: Could anybody test which antenna is the external one
-+*----------------------------------------------------------------*/
-+static int
-+acx_ioctl_set_tx_antenna(
-+      struct net_device *dev,
-+      struct iw_request_info *info,
-+      struct iw_param *vwrq,
-+      char *extra)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+      int result;
-+
-+      FN_ENTER;
-+
-+      if (*extra > 1) {
-+              result = -EINVAL;
-+              goto end;
-+      }
-+
-+      printk("old antenna value: 0x%02X\n", priv->antenna);
-+
-+      acx_sem_lock(priv);
-+
-+      priv->antenna &= ~0x30;
-+      SET_BIT(priv->antenna, ((*extra & 0x01) << 5));
-+      SET_BIT(priv->set_mask, GETSET_ANTENNA);
-+      printk("new antenna value: 0x%02X\n", priv->antenna);
-+      result = -EINPROGRESS;
-+
-+      acx_sem_unlock(priv);
-+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 *dev,
-+      struct iw_request_info *info,
-+      struct iw_param *vwrq,
-+      char *extra)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+      unsigned int *params = (unsigned int*)extra;
-+      unsigned int enable = (unsigned int)(params[0] > 0);
-+      int result;
-+
-+      FN_ENTER;
-+
-+      acx_sem_lock(priv);
-+
-+      /* not using printk() here, since it distorts kismet display
-+       * when printk messages activated */
-+      acxlog(L_IOCTL, "setting monitor to: 0x%02X\n", params[0]);
-+
-+      switch (params[0]) {
-+      case 0:
-+              priv->netdev->type = ARPHRD_ETHER;
-+              break;
-+      case 1:
-+              priv->netdev->type = ARPHRD_IEEE80211_PRISM;
-+              break;
-+      case 2:
-+              priv->netdev->type = ARPHRD_IEEE80211;
-+              break;
-+      }
-+
-+      if (params[0]) {
-+              priv->mode = ACX_MODE_MONITOR;
-+              SET_BIT(priv->set_mask, GETSET_MODE);
-+      }
-+
-+      if (enable) {
-+              priv->channel = params[1];
-+              SET_BIT(priv->set_mask, GETSET_RX);
-+      }
-+      result = -EINPROGRESS;
-+
-+      acx_sem_unlock(priv);
-+
-+      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 *dev,
-+      struct iw_request_info *info,
-+      struct iw_param *vwrq,
-+      char *extra)
-+{
-+#ifdef BROKEN
-+      wlandevice_t *priv = netdev_priv(dev);
-+      unsigned long flags;
-+      client_t client;
-+      int result;
-+
-+      acx_sem_lock(priv);
-+      acx_lock(priv, flags);
-+
-+      acx_l_transmit_disassoc(priv, &client);
-+      result = OK;
-+
-+      acx_unlock(priv, flags);
-+      acx_sem_unlock(priv);
-+
-+      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 *dev,
-+      struct iw_request_info *info,
-+      struct iw_param *vwrq,
-+      char *extra)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+      const unsigned int *params = (unsigned int*)extra;
-+      int result;
-+
-+      acx_sem_lock(priv);
-+
-+      acxlog(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],
-+                      priv->get_mask, priv->set_mask);
-+      SET_BIT(priv->get_mask, params[0]);
-+      SET_BIT(priv->set_mask, params[1]);
-+      acxlog(L_IOCTL, "after: get_mask %08X set_mask %08X\n",
-+                      priv->get_mask, priv->set_mask);
-+      result = -EINPROGRESS; /* immediately call commit handler */
-+
-+      acx_sem_unlock(priv);
-+
-+      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 *dev, struct iw_request_info *info,
-+               struct iw_param *vwrq, char *extra)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+      unsigned long flags;
-+      int result;
-+      u32 brate = 0, orate = 0; /* basic, operational rate set */
-+
-+      FN_ENTER;
-+
-+      acxlog(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);
-+      acxlog(L_IOCTL, "brate %08X orate %08X\n", brate, orate);
-+
-+      result = verify_rate(brate, priv->chip_type);
-+      if (result) goto end;
-+      result = verify_rate(orate, priv->chip_type);
-+      if (result) goto end;
-+
-+      acx_sem_lock(priv);
-+      acx_lock(priv, flags);
-+
-+      priv->rate_basic = brate;
-+      priv->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 */
-+      priv->rate_bcast = 1 << lowest_bit(brate);
-+      if (IS_ACX100(priv))
-+              priv->rate_bcast100 = acx_rate111to100(priv->rate_bcast);
-+      priv->rate_auto = !has_only_one_bit(orate);
-+      acx_l_update_client_rates(priv, orate);
-+      /* TODO: get rid of ratevector, build it only when needed */
-+      acx_l_update_ratevector(priv);
-+
-+      /* Do/don't do tx rate fallback; beacon contents and rate */
-+      SET_BIT(priv->set_mask, SET_RATE_FALLBACK|SET_TEMPLATES);
-+      result = -EINPROGRESS;
-+
-+      acx_unlock(priv, flags);
-+      acx_sem_unlock(priv);
-+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 *dev,
-+      struct iw_request_info *info,
-+      struct iw_param *vwrq,
-+      char *extra)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+      struct { /* added ACX_PACKED, not tested --vda */
-+              u16 type ACX_PACKED;
-+              u16 len ACX_PACKED;
-+              u32 busytime ACX_PACKED;
-+              u32 totaltime ACX_PACKED;
-+      } usage;
-+
-+      acx_sem_lock(priv);
-+
-+      if (OK != acx_s_interrogate(priv, &usage, ACX1xx_IE_MEDIUM_USAGE))
-+              goto bad_unlock;
-+
-+      printk("%s: average busy percentage since last invocation: %d%% "
-+              "(microseconds: %u of %u)\n",
-+              dev->name,
-+              100 * (le32_to_cpu(usage.busytime) / 100) / (le32_to_cpu(usage.totaltime) / 100),
-+              le32_to_cpu(usage.busytime), le32_to_cpu(usage.totaltime));
-+              /* prevent calculation overflow */
-+
-+      acx_sem_unlock(priv);
-+
-+      return OK;
-+
-+bad_unlock:
-+      acx_sem_unlock(priv);
-+
-+      return NOT_OK;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_ioctl_set_ed_threshold
-+*----------------------------------------------------------------*/
-+static inline int
-+acx_ioctl_set_ed_threshold(
-+      struct net_device *dev,
-+      struct iw_request_info *info,
-+      struct iw_param *vwrq,
-+      char *extra)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+
-+      acx_sem_lock(priv);
-+
-+      printk("old ED threshold value: %d\n", priv->ed_threshold);
-+      priv->ed_threshold = (unsigned char)*extra;
-+      printk("new ED threshold value: %d\n", (unsigned char)*extra);
-+      SET_BIT(priv->set_mask, GETSET_ED_THRESH);
-+
-+      acx_sem_unlock(priv);
-+
-+      return -EINPROGRESS;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_ioctl_set_cca
-+*----------------------------------------------------------------*/
-+static inline int
-+acx_ioctl_set_cca(
-+      struct net_device *dev,
-+      struct iw_request_info *info,
-+      struct iw_param *vwrq,
-+      char *extra)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+      int result;
-+
-+      acx_sem_lock(priv);
-+
-+      printk("old CCA value: 0x%02X\n", priv->cca);
-+      priv->cca = (unsigned char)*extra;
-+      printk("new CCA value: 0x%02X\n", (unsigned char)*extra);
-+      SET_BIT(priv->set_mask, GETSET_CCA);
-+      result = -EINPROGRESS;
-+
-+      acx_sem_unlock(priv);
-+
-+      return result;
-+}
-+
-+
-+/***********************************************************************
-+*/
-+static const char * const
-+scan_modes[] = { "active", "passive", "background" };
-+
-+static void
-+acx_print_scan_params(wlandevice_t *priv, const char* head)
-+{
-+      printk("%s: %smode %d (%s), min chan time %dTU, "
-+              "max chan time %dTU, max scan rate byte: %d\n",
-+              priv->netdev->name, head,
-+              priv->scan_mode, scan_modes[priv->scan_mode],
-+              priv->scan_probe_delay, priv->scan_duration, priv->scan_rate);
-+}
-+
-+static int
-+acx_ioctl_set_scan_params(
-+      struct net_device *dev,
-+      struct iw_request_info *info,
-+      struct iw_param *vwrq,
-+      char *extra)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+      int result;
-+      const int *params = (int *)extra;
-+
-+      acx_sem_lock(priv);
-+
-+      acx_print_scan_params(priv, "old scan parameters: ");
-+      if ((params[0] != -1) && (params[0] >= 0) && (params[0] <= 2))
-+              priv->scan_mode = params[0];
-+      if (params[1] != -1)
-+              priv->scan_probe_delay = params[1];
-+      if (params[2] != -1)
-+              priv->scan_duration = params[2];
-+      if ((params[3] != -1) && (params[3] <= 255))
-+              priv->scan_rate = params[3];
-+      acx_print_scan_params(priv, "new scan parameters: ");
-+      SET_BIT(priv->set_mask, GETSET_RESCAN);
-+      result = -EINPROGRESS;
-+
-+      acx_sem_unlock(priv);
-+
-+      return result;
-+}
-+
-+static int
-+acx_ioctl_get_scan_params(
-+      struct net_device *dev,
-+      struct iw_request_info *info,
-+      struct iw_param *vwrq,
-+      char *extra)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+      int result;
-+      int *params = (int *)extra;
-+
-+      acx_sem_lock(priv);
-+
-+      acx_print_scan_params(priv, "current scan parameters: ");
-+      params[0] = priv->scan_mode;
-+      params[1] = priv->scan_probe_delay;
-+      params[2] = priv->scan_duration;
-+      params[3] = priv->scan_rate;
-+      result = OK;
-+
-+      acx_sem_unlock(priv);
-+
-+      return result;
-+}
-+
-+
-+/***********************************************************************
-+*/
-+static int
-+acx100_ioctl_set_led_power(
-+      struct net_device *dev,
-+      struct iw_request_info *info,
-+      struct iw_param *vwrq,
-+      char *extra)
-+{
-+      static const char * const led_modes[] = { "off", "on", "LinkQuality" };
-+
-+      wlandevice_t *priv = netdev_priv(dev);
-+      int result;
-+
-+      acx_sem_lock(priv);
-+
-+      printk("%s: power LED status: old %d (%s), ",
-+                      dev->name,
-+                      priv->led_power,
-+                      led_modes[priv->led_power]);
-+      priv->led_power = extra[0];
-+      if (priv->led_power > 2) priv->led_power = 2;
-+      printk("new %d (%s)\n",
-+                      priv->led_power,
-+                      led_modes[priv->led_power]);
-+
-+      if (priv->led_power == 2) {
-+              printk("%s: max link quality setting: old %d, ",
-+                      dev->name, priv->brange_max_quality);
-+              if (extra[1])
-+                      priv->brange_max_quality = extra[1];
-+              printk("new %d\n", priv->brange_max_quality);
-+      }
-+
-+      SET_BIT(priv->set_mask, GETSET_LED_POWER);
-+
-+      result = -EINPROGRESS;
-+
-+      acx_sem_unlock(priv);
-+
-+      return result;
-+}
-+
-+
-+/***********************************************************************
-+*/
-+static inline int
-+acx100_ioctl_get_led_power(
-+      struct net_device *dev,
-+      struct iw_request_info *info,
-+      struct iw_param *vwrq,
-+      char *extra)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+
-+      acx_sem_lock(priv);
-+
-+      extra[0] = priv->led_power;
-+      if (priv->led_power == 2)
-+              extra[1] = priv->brange_max_quality;
-+      else
-+              extra[1] = -1;
-+
-+      acx_sem_unlock(priv);
-+
-+      return OK;
-+}
-+
-+
-+/***********************************************************************
-+*/
-+static int
-+acx111_ioctl_info(
-+      struct net_device *dev,
-+      struct iw_request_info *info,
-+      struct iw_param *vwrq,
-+      char *extra)
-+{
-+      if (!IS_PCI((wlandevice_t*)netdev_priv(dev)))
-+              return OK;
-+      return acx111pci_ioctl_info(dev, info, vwrq, extra);
-+}
-+
-+
-+/***********************************************************************
-+*/
-+static int
-+acx100_ioctl_set_phy_amp_bias(
-+      struct net_device *dev,
-+      struct iw_request_info *info,
-+      struct iw_param *vwrq,
-+      char *extra)
-+{
-+      if (!IS_PCI((wlandevice_t*)netdev_priv(dev))) {
-+              printk("acx: set_phy_amp_bias() is not supported on USB\n");
-+              return OK;
-+      }
-+      return acx100pci_ioctl_set_phy_amp_bias(dev, info, vwrq, extra);
-+}
-+
-+
-+/***********************************************************************
-+*/
-+#if WIRELESS_EXT >= 13
-+static const iw_handler acx_ioctl_handler[] =
-+{
-+      (iw_handler) acx_ioctl_commit,          /* SIOCSIWCOMMIT */
-+      (iw_handler) acx_ioctl_get_name,        /* SIOCGIWNAME */
-+      (iw_handler) NULL,                      /* SIOCSIWNWID */
-+      (iw_handler) NULL,                      /* SIOCGIWNWID */
-+      (iw_handler) acx_ioctl_set_freq,        /* SIOCSIWFREQ */
-+      (iw_handler) acx_ioctl_get_freq,        /* SIOCGIWFREQ */
-+      (iw_handler) acx_ioctl_set_mode,        /* SIOCSIWMODE */
-+      (iw_handler) acx_ioctl_get_mode,        /* SIOCGIWMODE */
-+      (iw_handler) acx_ioctl_set_sens,        /* SIOCSIWSENS */
-+      (iw_handler) acx_ioctl_get_sens,        /* SIOCGIWSENS */
-+      (iw_handler) NULL,                      /* SIOCSIWRANGE */
-+      (iw_handler) acx_ioctl_get_range,       /* SIOCGIWRANGE */
-+      (iw_handler) NULL,                      /* SIOCSIWPRIV */
-+      (iw_handler) NULL,                      /* SIOCGIWPRIV */
-+      (iw_handler) NULL,                      /* SIOCSIWSTATS */
-+      (iw_handler) 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
-+      (iw_handler) NULL /* acx_ioctl_set_spy FIXME */,        /* SIOCSIWSPY */
-+      (iw_handler) NULL /* acx_ioctl_get_spy FIXME */,        /* SIOCGIWSPY */
-+#else /* WSPY */
-+      (iw_handler) NULL,                      /* SIOCSIWSPY */
-+      (iw_handler) NULL,                      /* SIOCGIWSPY */
-+#endif /* WSPY */
-+      (iw_handler) NULL,                      /* [nothing] */
-+      (iw_handler) NULL,                      /* [nothing] */
-+#endif /* IW_HANDLER_VERSION > 4 */
-+      (iw_handler) acx_ioctl_set_ap,          /* SIOCSIWAP */
-+      (iw_handler) acx_ioctl_get_ap,          /* SIOCGIWAP */
-+      (iw_handler) NULL,                      /* [nothing] */
-+      (iw_handler) acx_ioctl_get_aplist,      /* SIOCGIWAPLIST */
-+#if WIRELESS_EXT > 13
-+      (iw_handler) acx_ioctl_set_scan,        /* SIOCSIWSCAN */
-+      (iw_handler) acx_ioctl_get_scan,        /* SIOCGIWSCAN */
-+#else /* WE > 13 */
-+      (iw_handler) NULL,                      /* SIOCSIWSCAN */
-+      (iw_handler) NULL,                      /* SIOCGIWSCAN */
-+#endif /* WE > 13 */
-+      (iw_handler) acx_ioctl_set_essid,       /* SIOCSIWESSID */
-+      (iw_handler) acx_ioctl_get_essid,       /* SIOCGIWESSID */
-+      (iw_handler) acx_ioctl_set_nick,        /* SIOCSIWNICKN */
-+      (iw_handler) acx_ioctl_get_nick,        /* SIOCGIWNICKN */
-+      (iw_handler) NULL,                      /* [nothing] */
-+      (iw_handler) NULL,                      /* [nothing] */
-+      (iw_handler) acx_ioctl_set_rate,        /* SIOCSIWRATE */
-+      (iw_handler) acx_ioctl_get_rate,        /* SIOCGIWRATE */
-+      (iw_handler) acx_ioctl_set_rts,         /* SIOCSIWRTS */
-+      (iw_handler) acx_ioctl_get_rts,         /* SIOCGIWRTS */
-+      (iw_handler) NULL /* acx_ioctl_set_frag FIXME */,       /* SIOCSIWFRAG */
-+      (iw_handler) NULL /* acx_ioctl_get_frag FIXME */,       /* SIOCGIWFRAG */
-+      (iw_handler) acx_ioctl_set_txpow,       /* SIOCSIWTXPOW */
-+      (iw_handler) acx_ioctl_get_txpow,       /* SIOCGIWTXPOW */
-+      (iw_handler) acx_ioctl_set_retry,       /* SIOCSIWRETRY */
-+      (iw_handler) acx_ioctl_get_retry,       /* SIOCGIWRETRY */
-+      (iw_handler) acx_ioctl_set_encode,      /* SIOCSIWENCODE */
-+      (iw_handler) acx_ioctl_get_encode,      /* SIOCGIWENCODE */
-+      (iw_handler) acx_ioctl_set_power,       /* SIOCSIWPOWER */
-+      (iw_handler) acx_ioctl_get_power,       /* SIOCGIWPOWER */
-+};
-+
-+static const iw_handler acx_ioctl_private_handler[] =
-+{
-+#if ACX_DEBUG
-+[ACX100_IOCTL_DEBUG           - ACX100_IOCTL] = (iw_handler) acx_ioctl_set_debug,
-+#else
-+[ACX100_IOCTL_DEBUG           - ACX100_IOCTL] = (iw_handler) NULL,
-+#endif
-+[ACX100_IOCTL_SET_PLED                - ACX100_IOCTL] = (iw_handler) acx100_ioctl_set_led_power,
-+[ACX100_IOCTL_GET_PLED                - ACX100_IOCTL] = (iw_handler) acx100_ioctl_get_led_power,
-+[ACX100_IOCTL_SET_RATES               - ACX100_IOCTL] = (iw_handler) acx_ioctl_set_rates,
-+[ACX100_IOCTL_LIST_DOM                - ACX100_IOCTL] = (iw_handler) acx_ioctl_list_reg_domain,
-+[ACX100_IOCTL_SET_DOM         - ACX100_IOCTL] = (iw_handler) acx_ioctl_set_reg_domain,
-+[ACX100_IOCTL_GET_DOM         - ACX100_IOCTL] = (iw_handler) acx_ioctl_get_reg_domain,
-+[ACX100_IOCTL_SET_SCAN_PARAMS - ACX100_IOCTL] = (iw_handler) acx_ioctl_set_scan_params,
-+[ACX100_IOCTL_GET_SCAN_PARAMS - ACX100_IOCTL] = (iw_handler) acx_ioctl_get_scan_params,
-+[ACX100_IOCTL_SET_PREAMB      - ACX100_IOCTL] = (iw_handler) acx_ioctl_set_short_preamble,
-+[ACX100_IOCTL_GET_PREAMB      - ACX100_IOCTL] = (iw_handler) acx_ioctl_get_short_preamble,
-+[ACX100_IOCTL_SET_ANT         - ACX100_IOCTL] = (iw_handler) acx_ioctl_set_antenna,
-+[ACX100_IOCTL_GET_ANT         - ACX100_IOCTL] = (iw_handler) acx_ioctl_get_antenna,
-+[ACX100_IOCTL_RX_ANT          - ACX100_IOCTL] = (iw_handler) acx_ioctl_set_rx_antenna,
-+[ACX100_IOCTL_TX_ANT          - ACX100_IOCTL] = (iw_handler) acx_ioctl_set_tx_antenna,
-+[ACX100_IOCTL_SET_PHY_AMP_BIAS        - ACX100_IOCTL] = (iw_handler) acx100_ioctl_set_phy_amp_bias,
-+[ACX100_IOCTL_GET_PHY_CHAN_BUSY       - ACX100_IOCTL] = (iw_handler) acx_ioctl_get_phy_chan_busy_percentage,
-+[ACX100_IOCTL_SET_ED          - ACX100_IOCTL] = (iw_handler) acx_ioctl_set_ed_threshold,
-+[ACX100_IOCTL_SET_CCA         - ACX100_IOCTL] = (iw_handler) acx_ioctl_set_cca,
-+[ACX100_IOCTL_MONITOR         - ACX100_IOCTL] = (iw_handler) acx_ioctl_wlansniff,
-+[ACX100_IOCTL_TEST            - ACX100_IOCTL] = (iw_handler) acx_ioctl_unknown11,
-+[ACX100_IOCTL_DBG_SET_MASKS   - ACX100_IOCTL] = (iw_handler) acx_ioctl_dbg_set_masks,
-+[ACX111_IOCTL_INFO            - ACX100_IOCTL] = (iw_handler) acx111_ioctl_info,
-+};
-+
-+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,
-+};
-+
-+#endif /* WE >= 13 */
-+
-+
-+#if WIRELESS_EXT < 13
-+/*================================================================*/
-+/* Main function                                                */
-+/*================================================================*/
-+/*----------------------------------------------------------------
-+* acx_e_ioctl_old
-+*
-+* Comment:
-+* This is the *OLD* ioctl handler.
-+* Make sure to not only place your additions here, but instead mainly
-+* in the new one (acx_ioctl_handler[])!
-+*----------------------------------------------------------------*/
-+int
-+acx_e_ioctl_old(netdevice_t *dev, struct ifreq *ifr, int cmd)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+      int result = 0;
-+      struct iwreq *iwr = (struct iwreq *)ifr;
-+
-+      acxlog(L_IOCTL, "%s cmd = 0x%04X\n", __func__, cmd);
-+
-+      /* This is the way it is done in the orinoco driver.
-+       * Check to see if device is present.
-+       */
-+      if (0 == netif_device_present(dev)) {
-+              return -ENODEV;
-+      }
-+
-+      switch (cmd) {
-+/* WE 13 and higher will use acx_ioctl_handler_def */
-+      case SIOCGIWNAME:
-+              /* get name == wireless protocol */
-+              result = acx_ioctl_get_name(dev, NULL,
-+                                             (char *)&(iwr->u.name), NULL);
-+              break;
-+
-+      case SIOCSIWNWID: /* pre-802.11, */
-+      case SIOCGIWNWID: /* not supported. */
-+              result = -EOPNOTSUPP;
-+              break;
-+
-+      case SIOCSIWFREQ:
-+              /* set channel/frequency (Hz)
-+                 data can be frequency or channel :
-+                 0-1000 = channel
-+                 > 1000 = frequency in Hz */
-+              result = acx_ioctl_set_freq(dev, NULL, &(iwr->u.freq), NULL);
-+              break;
-+
-+      case SIOCGIWFREQ:
-+              /* get channel/frequency (Hz) */
-+              result = acx_ioctl_get_freq(dev, NULL, &(iwr->u.freq), NULL);
-+              break;
-+
-+      case SIOCSIWMODE:
-+              /* set operation mode */
-+              result = acx_ioctl_set_mode(dev, NULL, &(iwr->u.mode), NULL);
-+              break;
-+
-+      case SIOCGIWMODE:
-+              /* get operation mode */
-+              result = acx_ioctl_get_mode(dev, NULL, &(iwr->u.mode), NULL);
-+              break;
-+
-+      case SIOCSIWSENS:
-+              /* Set sensitivity */
-+              result = acx_ioctl_set_sens(dev, NULL, &(iwr->u.sens), NULL);
-+              break;
-+
-+      case SIOCGIWSENS:
-+              /* Get sensitivity */
-+              result = acx_ioctl_get_sens(dev, NULL, &(iwr->u.sens), NULL);
-+              break;
-+
-+#if WIRELESS_EXT > 10
-+      case SIOCGIWRANGE:
-+              /* Get range of parameters */
-+              {
-+                      struct iw_range range;
-+                      result = acx_ioctl_get_range(dev, NULL,
-+                                      &(iwr->u.data), (char *)&range);
-+                      if (copy_to_user(iwr->u.data.pointer, &range,
-+                                       sizeof(struct iw_range)))
-+                              result = -EFAULT;
-+              }
-+              break;
-+#endif
-+
-+      case SIOCGIWPRIV:
-+              result = acx_ioctl_get_iw_priv(iwr);
-+              break;
-+
-+      /* FIXME: */
-+      /* case SIOCSIWSPY: */
-+      /* case SIOCGIWSPY: */
-+      /* case SIOCSIWTHRSPY: */
-+      /* case SIOCGIWTHRSPY: */
-+
-+      case SIOCSIWAP:
-+              /* set access point by MAC address */
-+              result = acx_ioctl_set_ap(dev, NULL, &(iwr->u.ap_addr),
-+                                           NULL);
-+              break;
-+
-+      case SIOCGIWAP:
-+              /* get access point MAC address */
-+              result = acx_ioctl_get_ap(dev, NULL, &(iwr->u.ap_addr),
-+                                           NULL);
-+              break;
-+
-+      case SIOCGIWAPLIST:
-+              /* get list of access points in range */
-+              result = acx_ioctl_get_aplist(dev, NULL, &(iwr->u.data),
-+                                               NULL);
-+              break;
-+
-+#if NOT_FINISHED_YET
-+      /* FIXME: do proper interfacing to activate that! */
-+      case SIOCSIWSCAN:
-+              /* start a station scan */
-+              result = acx_ioctl_set_scan(iwr, priv);
-+              break;
-+
-+      case SIOCGIWSCAN:
-+              /* get list of stations found during scan */
-+              result = acx_ioctl_get_scan(iwr, priv);
-+              break;
-+#endif
-+
-+      case SIOCSIWESSID:
-+              /* set ESSID (network name) */
-+              {
-+                      char essid[IW_ESSID_MAX_SIZE+1];
-+
-+                      if (iwr->u.essid.length > IW_ESSID_MAX_SIZE)
-+                      {
-+                              result = -E2BIG;
-+                              break;
-+                      }
-+                      if (copy_from_user(essid, iwr->u.essid.pointer,
-+                                              iwr->u.essid.length))
-+                      {
-+                              result = -EFAULT;
-+                              break;
-+                      }
-+                      result = acx_ioctl_set_essid(dev, NULL,
-+                                      &(iwr->u.essid), essid);
-+              }
-+              break;
-+
-+      case SIOCGIWESSID:
-+              /* get ESSID */
-+              {
-+                      char essid[IW_ESSID_MAX_SIZE+1];
-+                      if (iwr->u.essid.pointer)
-+                              result = acx_ioctl_get_essid(dev, NULL,
-+                                      &(iwr->u.essid), essid);
-+                      if (copy_to_user(iwr->u.essid.pointer, essid,
-+                                              iwr->u.essid.length))
-+                              result = -EFAULT;
-+              }
-+              break;
-+
-+      case SIOCSIWNICKN:
-+              /* set nick */
-+              {
-+                      char nick[IW_ESSID_MAX_SIZE+1];
-+
-+                      if (iwr->u.data.length > IW_ESSID_MAX_SIZE)
-+                      {
-+                              result = -E2BIG;
-+                              break;
-+                      }
-+                      if (copy_from_user(nick, iwr->u.data.pointer,
-+                                              iwr->u.data.length))
-+                      {
-+                              result = -EFAULT;
-+                              break;
-+                      }
-+                      result = acx_ioctl_set_nick(dev, NULL,
-+                                      &(iwr->u.data), nick);
-+              }
-+              break;
-+
-+      case SIOCGIWNICKN:
-+              /* get nick */
-+              {
-+                      char nick[IW_ESSID_MAX_SIZE+1];
-+                      if (iwr->u.data.pointer)
-+                              result = acx_ioctl_get_nick(dev, NULL,
-+                                              &(iwr->u.data), nick);
-+                      if (copy_to_user(iwr->u.data.pointer, nick,
-+                                              iwr->u.data.length))
-+                              result = -EFAULT;
-+              }
-+              break;
-+
-+      case SIOCSIWRATE:
-+              /* set default bit rate (bps) */
-+              result = acx_ioctl_set_rate(dev, NULL, &(iwr->u.bitrate),
-+                                             NULL);
-+              break;
-+
-+      case SIOCGIWRATE:
-+              /* get default bit rate (bps) */
-+              result = acx_ioctl_get_rate(dev, NULL, &(iwr->u.bitrate),
-+                                             NULL);
-+              break;
-+
-+      case  SIOCSIWRTS:
-+              /* set RTS threshold value */
-+              result = acx_ioctl_set_rts(dev, NULL, &(iwr->u.rts), NULL);
-+              break;
-+      case  SIOCGIWRTS:
-+              /* get RTS threshold value */
-+              result = acx_ioctl_get_rts(dev, NULL,  &(iwr->u.rts), NULL);
-+              break;
-+
-+      /* FIXME: */
-+      /* case  SIOCSIWFRAG: */
-+      /* case  SIOCGIWFRAG: */
-+
-+#if WIRELESS_EXT > 9
-+      case SIOCGIWTXPOW:
-+              /* get tx power */
-+              result = acx_ioctl_get_txpow(dev, NULL, &(iwr->u.txpower),
-+                                              NULL);
-+              break;
-+
-+      case SIOCSIWTXPOW:
-+              /* set tx power */
-+              result = acx_ioctl_set_txpow(dev, NULL, &(iwr->u.txpower),
-+                                              NULL);
-+              break;
-+#endif
-+
-+      case SIOCSIWRETRY:
-+              result = acx_ioctl_set_retry(dev, NULL, &(iwr->u.retry), NULL);
-+              break;
-+
-+      case SIOCGIWRETRY:
-+              result = acx_ioctl_get_retry(dev, NULL, &(iwr->u.retry), NULL);
-+              break;
-+
-+      case SIOCSIWENCODE:
-+              {
-+                      /* set encoding token & mode */
-+                      u8 key[29];
-+                      if (iwr->u.encoding.pointer) {
-+                              if (iwr->u.encoding.length > 29) {
-+                                      result = -E2BIG;
-+                                      break;
-+                              }
-+                              if (copy_from_user(key, iwr->u.encoding.pointer,
-+                                              iwr->u.encoding.length)) {
-+                                      result = -EFAULT;
-+                                      break;
-+                              }
-+                      }
-+                      else
-+                      if (iwr->u.encoding.length) {
-+                              result = -EINVAL;
-+                              break;
-+                      }
-+                      result = acx_ioctl_set_encode(dev, NULL,
-+                                      &(iwr->u.encoding), key);
-+              }
-+              break;
-+
-+      case SIOCGIWENCODE:
-+              {
-+                      /* get encoding token & mode */
-+                      u8 key[29];
-+
-+                      result = acx_ioctl_get_encode(dev, NULL,
-+                                      &(iwr->u.encoding), key);
-+                      if (iwr->u.encoding.pointer) {
-+                              if (copy_to_user(iwr->u.encoding.pointer,
-+                                              key, iwr->u.encoding.length))
-+                                      result = -EFAULT;
-+                      }
-+              }
-+              break;
-+
-+      /******************** iwpriv ioctls below ********************/
-+#if ACX_DEBUG
-+      case ACX100_IOCTL_DEBUG:
-+              acx_ioctl_set_debug(dev, NULL, NULL, iwr->u.name);
-+              break;
-+#endif
-+
-+      case ACX100_IOCTL_SET_PLED:
-+              acx100_ioctl_set_led_power(dev, NULL, NULL, iwr->u.name);
-+              break;
-+
-+      case ACX100_IOCTL_GET_PLED:
-+              acx100_ioctl_get_led_power(dev, NULL, NULL, iwr->u.name);
-+              break;
-+
-+      case ACX100_IOCTL_LIST_DOM:
-+              acx_ioctl_list_reg_domain(dev, NULL, NULL, NULL);
-+              break;
-+
-+      case ACX100_IOCTL_SET_DOM:
-+              acx_ioctl_set_reg_domain(dev, NULL, NULL, iwr->u.name);
-+              break;
-+
-+      case ACX100_IOCTL_GET_DOM:
-+              acx_ioctl_get_reg_domain(dev, NULL, NULL, iwr->u.name);
-+              break;
-+
-+      case ACX100_IOCTL_SET_SCAN_PARAMS:
-+              acx_ioctl_set_scan_params(dev, NULL, NULL, iwr->u.name);
-+              break;
-+
-+      case ACX100_IOCTL_GET_SCAN_PARAMS:
-+              acx_ioctl_get_scan_params(dev, NULL, NULL, iwr->u.name);
-+              break;
-+
-+      case ACX100_IOCTL_SET_PREAMB:
-+              acx_ioctl_set_short_preamble(dev, NULL, NULL, iwr->u.name);
-+              break;
-+
-+      case ACX100_IOCTL_GET_PREAMB:
-+              acx_ioctl_get_short_preamble(dev, NULL, NULL, iwr->u.name);
-+              break;
-+
-+      case ACX100_IOCTL_SET_ANT:
-+              acx_ioctl_set_antenna(dev, NULL, NULL, iwr->u.name);
-+              break;
-+
-+      case ACX100_IOCTL_GET_ANT:
-+              acx_ioctl_get_antenna(dev, NULL, NULL, NULL);
-+              break;
-+
-+      case ACX100_IOCTL_RX_ANT:
-+              acx_ioctl_set_rx_antenna(dev, NULL, NULL, iwr->u.name);
-+              break;
-+
-+      case ACX100_IOCTL_TX_ANT:
-+              acx_ioctl_set_tx_antenna(dev, NULL, NULL, iwr->u.name);
-+              break;
-+
-+      case ACX100_IOCTL_SET_ED:
-+              acx_ioctl_set_ed_threshold(dev, NULL, NULL, iwr->u.name);
-+              break;
-+
-+      case ACX100_IOCTL_SET_CCA:
-+              acx_ioctl_set_cca(dev, NULL, NULL, iwr->u.name);
-+              break;
-+
-+      case ACX100_IOCTL_MONITOR:      /* set sniff (monitor) mode */
-+              acxlog(L_IOCTL, "%s: IWPRIV monitor\n", dev->name);
-+
-+              /* can only be done by admin */
-+              if (!capable(CAP_NET_ADMIN)) {
-+                      result = -EPERM;
-+                      break;
-+              }
-+              result = acx_ioctl_wlansniff(dev, NULL, NULL, iwr->u.name);
-+              break;
-+
-+      case ACX100_IOCTL_TEST:
-+              acx_ioctl_unknown11(dev, NULL, NULL, NULL);
-+              break;
-+
-+      case ACX111_IOCTL_INFO:
-+              acx111_ioctl_info(dev, NULL, NULL, NULL);
-+              break;
-+
-+      default:
-+              acxlog(L_IOCTL, "wireless ioctl 0x%04X queried "
-+                              "but not implemented yet\n", cmd);
-+              result = -EOPNOTSUPP;
-+              break;
-+      }
-+
-+      if ((priv->dev_state_mask & ACX_STATE_IFACE_UP) && priv->set_mask) {
-+              acx_sem_lock(priv);
-+              acx_s_update_card_settings(priv, 0, 0);
-+              acx_sem_unlock(priv);
-+      }
-+
-+      /* older WEs don't have a commit handler,
-+       * so we need to fix return code in this case */
-+      if (-EINPROGRESS == result)
-+              result = 0;
-+
-+      return result;
-+}
-+#endif /* WE < 13 */
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/net/wireless/tiacx/Kconfig bt_kernel/drivers/net/wireless/tiacx/Kconfig
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/net/wireless/tiacx/Kconfig  1970-01-01 02:00:00.000000000 +0200
-+++ bt_kernel/drivers/net/wireless/tiacx/Kconfig       2005-09-28 23:54:23.938287000 +0300
-@@ -0,0 +1,59 @@
-+config ACX
-+      tristate "TI acx100/acx111 802.11b/g wireless chipsets"
-+      depends on NET_RADIO && EXPERIMENTAL && 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 quite new and experimental.
-+
-+      These 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.
-+
-+      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 PCI && ACX
-+      ---help---
-+      Include PCI and CardBus support in acx.
-+
-+config ACX_USB
-+      bool "TI acx100/acx111 802.11b/g USB"
-+      depends on USB && ACX && BROKEN
-+      ---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.
-+
-+config ACX_CFI
-+      bool "TI acx100 802.11b/g Compact Flash"
-+      depends on  ACX
-+      ---help---
-+      Include Compact Flash support.
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/net/wireless/tiacx/macros.h bt_kernel/drivers/net/wireless/tiacx/macros.h
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/net/wireless/tiacx/macros.h 1970-01-01 02:00:00.000000000 +0200
-+++ bt_kernel/drivers/net/wireless/tiacx/macros.h      2005-09-28 23:54:23.938287000 +0300
-@@ -0,0 +1,33 @@
-+#ifndef _MACROS_H
-+#define _MACROS_H
-+
-+
-+
-+#define HW_SLAVE_REG_ADDR_REG 0x00000004
-+#define HW_SLAVE_REG_DATA_REG 0x00000008
-+#define HW_SLAVE_REG_CTRL_REG 0x0000000c
-+#define HW_SLAVE_MEM_ADDR_REG 0x00000014
-+#define HW_SLAVE_MEM_DATA_REG 0x00000018
-+
-+#define REG_LO(b,r)   ((u8 *) b + r)
-+#define REG_HI(b,r)   ((u8 *) b + r + 2)
-+
-+static inline u32 acx_readl(unsigned char *iobase, unsigned int reg)
-+{
-+      u16 hi,lo;
-+
-+      writew( 0, REG_LO(iobase, HW_SLAVE_REG_CTRL_REG));
-+      writew( 1, REG_HI(iobase,HW_SLAVE_REG_CTRL_REG));
-+
-+      writew( reg, REG_LO(iobase, HW_SLAVE_REG_ADDR_REG));
-+      writew( 0, REG_HI(iobase,HW_SLAVE_REG_ADDR_REG));
-+
-+      lo = readw(REG_LO(iobase,HW_SLAVE_REG_DATA_REG));
-+      hi = readw(REG_HI(iobase,HW_SLAVE_REG_DATA_REG));
-+
-+      printk("hi=%04x,lo=%04x\n",hi,lo);
-+
-+      return ((u32)hi<<16) | lo;
-+}
-+
-+#endif
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/net/wireless/tiacx/Makefile bt_kernel/drivers/net/wireless/tiacx/Makefile
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/net/wireless/tiacx/Makefile 1970-01-01 02:00:00.000000000 +0200
-+++ bt_kernel/drivers/net/wireless/tiacx/Makefile      2005-09-28 23:54:23.938287000 +0300
-@@ -0,0 +1,9 @@
-+#Use this if you have proper Kconfig integration:
-+
-+obj-$(CONFIG_ACX) += acx.o
-+
-+acx-obj-$(CONFIG_ACX_PCI) += pci.o
-+acx-obj-$(CONFIG_ACX_USB) += usb.o
-+acx-obj-$(CONFIG_ACX_CFI) += cfi.o
-+
-+acx-objs := wlan.o conv.o ioctl.o common.o $(acx-obj-y)
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/net/wireless/tiacx/pci.c bt_kernel/drivers/net/wireless/tiacx/pci.c
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/net/wireless/tiacx/pci.c    1970-01-01 02:00:00.000000000 +0200
-+++ bt_kernel/drivers/net/wireless/tiacx/pci.c 2005-09-28 23:54:23.938287000 +0300
-@@ -0,0 +1,4840 @@
-+/***********************************************************************
-+** 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/config.h>
-+#include <linux/version.h>
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
-+#include <linux/moduleparam.h>
-+#endif
-+#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>
-+#if WIRELESS_EXT >= 13
-+#include <net/iw_handler.h>
-+#endif
-+#include <linux/netdevice.h>
-+#include <linux/ioport.h>
-+#include <linux/pci.h>
-+#include <linux/pm.h>
-+
-+#include "acx.h"
-+
-+
-+/*================================================================*/
-+/* Local Constants */
-+#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      0x280
-+
-+#define CARD_EEPROM_ID_SIZE 6
-+#define MAX_IRQLOOPS_PER_JIFFY  (20000/HZ) /* a la orinoco.c */
-+
-+
-+/***********************************************************************
-+*/
-+static void acx_l_disable_irq(wlandevice_t *priv);
-+static void acx_l_enable_irq(wlandevice_t *priv);
-+static int acx_e_probe_pci(struct pci_dev *pdev,
-+                          const struct pci_device_id *id);
-+static void acx_e_remove_pci(struct pci_dev *pdev);
-+
-+#ifdef CONFIG_PM
-+static int acx_e_suspend(struct pci_dev *pdev, pm_message_t state);
-+static int acx_e_resume(struct pci_dev *pdev);
-+#endif
-+
-+static void acx_i_tx_timeout(netdevice_t *dev);
-+static struct net_device_stats *acx_e_get_stats(netdevice_t *dev);
-+static struct iw_statistics *acx_e_get_wireless_stats(netdevice_t *dev);
-+
-+static irqreturn_t acx_i_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-+static void acx_i_set_multicast_list(netdevice_t *dev);
-+
-+static int acx_e_open(netdevice_t *dev);
-+static int acx_e_close(netdevice_t *dev);
-+static void acx_s_up(netdevice_t *dev);
-+static void acx_s_down(netdevice_t *dev);
-+
-+
-+/***********************************************************************
-+** Register access
-+*/
-+
-+/* Pick one */
-+/* #define INLINE_IO static */
-+#define INLINE_IO static inline
-+
-+INLINE_IO u32
-+acx_read_reg32(wlandevice_t *priv, unsigned int offset)
-+{
-+#if ACX_IO_WIDTH == 32
-+      return readl((u8 *)priv->iobase + priv->io[offset]);
-+#else
-+      return readw((u8 *)priv->iobase + priv->io[offset])
-+          + (readw((u8 *)priv->iobase + priv->io[offset] + 2) << 16);
-+#endif
-+}
-+
-+INLINE_IO u16
-+acx_read_reg16(wlandevice_t *priv, unsigned int offset)
-+{
-+      return readw((u8 *)priv->iobase + priv->io[offset]);
-+}
-+
-+INLINE_IO u8
-+acx_read_reg8(wlandevice_t *priv, unsigned int offset)
-+{
-+      return readb((u8 *)priv->iobase + priv->io[offset]);
-+}
-+
-+INLINE_IO void
-+acx_write_reg32(wlandevice_t *priv, unsigned int offset, u32 val)
-+{
-+#if ACX_IO_WIDTH == 32
-+      writel(val, (u8 *)priv->iobase + priv->io[offset]);
-+#else
-+      writew(val & 0xffff, (u8 *)priv->iobase + priv->io[offset]);
-+      writew(val >> 16, (u8 *)priv->iobase + priv->io[offset] + 2);
-+#endif
-+}
-+
-+INLINE_IO void
-+acx_write_reg16(wlandevice_t *priv, unsigned int offset, u16 val)
-+{
-+      writew(val, (u8 *)priv->iobase + priv->io[offset]);
-+}
-+
-+INLINE_IO void
-+acx_write_reg8(wlandevice_t *priv, unsigned int offset, u8 val)
-+{
-+      writeb(val, (u8 *)priv->iobase + priv->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
-+acx_write_flush(wlandevice_t *priv)
-+{
-+      /* readb(priv->iobase + priv->io[IO_ACX_INFO_MAILBOX_OFFS]); */
-+      /* faster version (accesses the first register, IO_ACX_SOFT_RESET,
-+       * which should also be safe): */
-+      readb(priv->iobase);
-+}
-+
-+
-+/***********************************************************************
-+*/
-+static const char name_acx100[] = "ACX100";
-+static const char name_tnetw1100a[] = "TNETW1100A";
-+static const char name_tnetw1100b[] = "TNETW1100B";
-+
-+static const char name_acx111[] = "ACX111";
-+static const char name_tnetw1130[] = "TNETW1130";
-+
-+static const struct pci_device_id
-+acx_pci_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, acx_pci_id_tbl);
-+
-+/* FIXME: checks should be removed once driver is included in the kernel */
-+#ifndef __devexit_p
-+#warning *** your kernel is EXTREMELY old since it does not even know about
-+#warning __devexit_p - this driver could easily FAIL to work, so better
-+#warning upgrade your kernel! ***
-+#define __devexit_p(x) x
-+#endif
-+
-+#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 acx_pci_drv_id = {
-+      .name        = "acx_pci",
-+      .id_table    = acx_pci_id_tbl,
-+      .probe       = acx_e_probe_pci,
-+      .remove      = __devexit_p(acx_e_remove_pci),
-+#ifdef CONFIG_PM
-+      .suspend     = acx_e_suspend,
-+      .resume      = acx_e_resume
-+#endif /* CONFIG_PM */
-+};
-+
-+typedef struct acx_device {
-+      netdevice_t *newest;
-+} acx_device_t;
-+
-+/* if this driver was only about PCI devices, then we probably wouldn't
-+ * need this linked list.
-+ * But if we want to register ALL kinds of devices in one global list,
-+ * then we need it and need to maintain it properly. */
-+static struct acx_device root_acx_dev = {
-+      .newest         = NULL,
-+};
-+DECLARE_MUTEX(root_acx_dev_sem);
-+
-+
-+/***********************************************************************
-+*/
-+static inline txdesc_t*
-+get_txdesc(wlandevice_t* priv, int index)
-+{
-+      return (txdesc_t*) (((u8*)priv->txdesc_start) + index * priv->txdesc_size);
-+}
-+
-+static inline txdesc_t*
-+move_txdesc(wlandevice_t* priv, txdesc_t* txdesc, int inc)
-+{
-+      return (txdesc_t*) (((u8*)txdesc) + inc * priv->txdesc_size);
-+}
-+
-+static txhostdesc_t*
-+acx_get_txhostdesc(wlandevice_t* priv, txdesc_t* txdesc)
-+{
-+      int index = (u8*)txdesc - (u8*)priv->txdesc_start;
-+      if (ACX_DEBUG && (index % priv->txdesc_size)) {
-+              printk("bad txdesc ptr %p\n", txdesc);
-+              return NULL;
-+      }
-+      index /= priv->txdesc_size;
-+      if (ACX_DEBUG && (index >= TX_CNT)) {
-+              printk("bad txdesc ptr %p\n", txdesc);
-+              return NULL;
-+      }
-+      return &priv->txhostdesc_start[index*2];
-+}
-+
-+static client_t*
-+acx_get_txc(wlandevice_t* priv, txdesc_t* txdesc)
-+{
-+      int index = (u8*)txdesc - (u8*)priv->txdesc_start;
-+      if (ACX_DEBUG && (index % priv->txdesc_size)) {
-+              printk("bad txdesc ptr %p\n", txdesc);
-+              return NULL;
-+      }
-+      index /= priv->txdesc_size;
-+      if (ACX_DEBUG && (index >= TX_CNT)) {
-+              printk("bad txdesc ptr %p\n", txdesc);
-+              return NULL;
-+      }
-+      return priv->txc[index];
-+}
-+
-+static void
-+acx_put_txc(wlandevice_t* priv, txdesc_t* txdesc, client_t* c)
-+{
-+      int index = (u8*)txdesc - (u8*)priv->txdesc_start;
-+      if (ACX_DEBUG && (index % priv->txdesc_size)) {
-+              printk("bad txdesc ptr %p\n", txdesc);
-+              return;
-+      }
-+      index /= priv->txdesc_size;
-+      if (ACX_DEBUG && (index >= TX_CNT)) {
-+              printk("bad txdesc ptr %p\n", txdesc);
-+              return;
-+      }
-+      priv->txc[index] = c;
-+}
-+
-+/***********************************************************************
-+** EEPROM and PHY read/write helpers
-+*/
-+/***********************************************************************
-+** acx_read_eeprom_offset
-+**
-+** Function called to read an octet in the EEPROM.
-+**
-+** This function is used by acx_probe_pci to check if the
-+** connected card is a legal one or not.
-+**
-+** Arguments:
-+**    priv            ptr to wlandevice structure
-+**    addr            address to read in the EEPROM
-+**    charbuf         ptr to a char. This is where the read octet
-+**                    will be stored
-+**
-+** Returns:
-+**    zero (0)        - failed
-+**    one (1)         - success
-+**
-+** NOT ADAPTED FOR ACX111!!
-+*/
-+int
-+acx_read_eeprom_offset(wlandevice_t *priv, u32 addr, u8 *charbuf)
-+{
-+      int result = NOT_OK;
-+      int count;
-+
-+      acx_write_reg32(priv, IO_ACX_EEPROM_CFG, 0);
-+      acx_write_reg32(priv, IO_ACX_EEPROM_ADDR, addr);
-+      acx_write_flush(priv);
-+      acx_write_reg32(priv, IO_ACX_EEPROM_CTL, 2);
-+
-+      count = 0xffff;
-+      while (acx_read_reg16(priv, 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",
-+                                                      priv->netdev->name);
-+                      goto fail;
-+              }
-+      }
-+
-+      *charbuf = acx_read_reg8(priv, IO_ACX_EEPROM_DATA);
-+      acxlog(L_DEBUG, "EEPROM at 0x%04X = 0x%02X\n", addr, *charbuf);
-+      result = OK;
-+
-+fail:
-+      return result;
-+}
-+
-+
-+/***********************************************************************
-+** Dummy EEPROM read? why?!
-+*/
-+static int
-+acx_read_eeprom_area(wlandevice_t *priv)
-+{
-+      int offs;
-+      u8 tmp[0x3b];
-+
-+      for (offs = 0x8c; offs < 0xb9; offs++) {
-+              acx_read_eeprom_offset(priv, offs, &tmp[offs - 0x8c]);
-+      }
-+      return OK;
-+}
-+
-+
-+/***********************************************************************
-+** 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
-+acx_s_write_eeprom_offset(wlandevice_t *priv, 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 = acx_read_reg16(priv, IO_ACX_GPIO_OE);
-+      acx_write_reg16(priv, IO_ACX_GPIO_OE, gpio_orig & ~1);
-+      acx_write_flush(priv);
-+
-+      /* ok, now start writing the data out */
-+      for (i = 0; i < len; i++) {
-+              acx_write_reg32(priv, IO_ACX_EEPROM_CFG, 0);
-+              acx_write_reg32(priv, IO_ACX_EEPROM_ADDR, addr + i);
-+              acx_write_reg32(priv, IO_ACX_EEPROM_DATA, *(charbuf + i));
-+              acx_write_flush(priv);
-+              acx_write_reg32(priv, IO_ACX_EEPROM_CTL, 1);
-+
-+              while (acx_read_reg16(priv, IO_ACX_EEPROM_CTL)) {
-+                      if (unlikely(++count > 0xffff)) {
-+                              printk("WARNING, DANGER!!! "
-+                                      "Timeout waiting for EEPROM write\n");
-+                              goto end;
-+                      }
-+              }
-+      }
-+
-+      /* disable EEPROM writing */
-+      acx_write_reg16(priv, IO_ACX_GPIO_OE, gpio_orig);
-+      acx_write_flush(priv);
-+
-+      /* now start a verification run */
-+      count = 0xffff;
-+      for (i = 0; i < len; i++) {
-+              acx_write_reg32(priv, IO_ACX_EEPROM_CFG, 0);
-+              acx_write_reg32(priv, IO_ACX_EEPROM_ADDR, addr + i);
-+              acx_write_flush(priv);
-+              acx_write_reg32(priv, IO_ACX_EEPROM_CTL, 2);
-+
-+              while (acx_read_reg16(priv, IO_ACX_EEPROM_CTL)) {
-+                      if (unlikely(!--count)) {
-+                              printk("timeout waiting for EEPROM read\n");
-+                              goto end;
-+                      }
-+              }
-+
-+              data_verify[i] = acx_read_reg16(priv, 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
-+** (acx_write_reg32(priv, IO_ACX_ENABLE, 0b000000xx)) kills traffic
-+*/
-+int
-+acxpci_s_read_phy_reg(wlandevice_t *priv, u32 reg, u8 *charbuf)
-+{
-+      int result = NOT_OK;
-+      int count;
-+
-+      FN_ENTER;
-+
-+      acx_write_reg32(priv, IO_ACX_PHY_ADDR, reg);
-+      acx_write_flush(priv);
-+      acx_write_reg32(priv, IO_ACX_PHY_CTL, 2);
-+
-+      count = 0xffff;
-+      while (acx_read_reg32(priv, 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",
-+                                                      priv->netdev->name);
-+                      *charbuf = 0;
-+                      goto fail;
-+              }
-+      }
-+
-+      acxlog(L_DEBUG, "count was %u\n", count);
-+      *charbuf = acx_read_reg8(priv, IO_ACX_PHY_DATA);
-+
-+      acxlog(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(wlandevice_t *priv, u32 reg, u8 value)
-+{
-+      FN_ENTER;
-+
-+      /* FIXME: we didn't use 32bit access here since mprusko said that
-+       * it results in distorted sensitivity on his card (huh!?!?
-+       * doesn't happen with my setup...)
-+       * But with the access reordering and flushing it
-+       * shouldn't happen any more...
-+       * FIXME: which radio is in the problematic card? My working one
-+       * is 0x11 */
-+      acx_write_reg32(priv, IO_ACX_PHY_DATA, value);
-+      acx_write_reg32(priv, IO_ACX_PHY_ADDR, reg);
-+      acx_write_flush(priv);
-+      acx_write_reg32(priv, IO_ACX_PHY_CTL, 1);
-+      acx_write_flush(priv);
-+      acxlog(L_DEBUG, "radio PHY write 0x%02X at 0x%04X\n", value, reg);
-+
-+      FN_EXIT1(OK);
-+      return OK;
-+}
-+
-+
-+#define NO_AUTO_INCREMENT     1
-+
-+/***********************************************************************
-+** acx_s_write_fw
-+**
-+** Write the firmware image into the card.
-+**
-+** Arguments:
-+**    priv            wlan device structure
-+**    apfw_image      firmware image.
-+**
-+** Returns:
-+**    1       firmware image corrupted
-+**    0       success
-+*/
-+static int
-+acx_s_write_fw(wlandevice_t *priv, const firmware_image_t *apfw_image, u32 offset)
-+{
-+      int len, size;
-+      u32 sum, v32;
-+      /* we skip the first four bytes which contain the control sum */
-+      const u8 *image = (u8*)apfw_image + 4;
-+
-+      /* start the image checksum by adding the image size value */
-+      sum = image[0]+image[1]+image[2]+image[3];
-+      image += 4;
-+
-+      acx_write_reg32(priv, IO_ACX_SLV_END_CTL, 0);
-+
-+#if NO_AUTO_INCREMENT
-+      acxlog(L_INIT, "not using auto increment for firmware loading\n");
-+      acx_write_reg32(priv, IO_ACX_SLV_MEM_CTL, 0); /* use basic mode */
-+#else
-+      acx_write_reg32(priv, IO_ACX_SLV_MEM_CTL, 1); /* use autoincrement mode */
-+      acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR, offset); /* configure start address */
-+      acx_write_flush(priv);
-+#endif
-+
-+      len = 0;
-+      size = le32_to_cpu(apfw_image->size) & (~3);
-+
-+      while (likely(len < size)) {
-+              v32 = be32_to_cpu(*(u32*)image);
-+              sum += image[0]+image[1]+image[2]+image[3];
-+              image += 4;
-+              len += 4;
-+
-+#if NO_AUTO_INCREMENT
-+              acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR, offset + len - 4);
-+              acx_write_flush(priv);
-+#endif
-+              acx_write_reg32(priv, IO_ACX_SLV_MEM_DATA, v32);
-+      }
-+
-+      acxlog(L_DEBUG, "%s: firmware written\n", __func__);
-+
-+      /* compare our checksum with the stored image checksum */
-+      return (sum != le32_to_cpu(apfw_image->chksum));
-+}
-+
-+
-+/***********************************************************************
-+** acx_s_validate_fw
-+**
-+** Compare the firmware image given with
-+** the firmware image written into the card.
-+**
-+** Arguments:
-+**    priv            wlan device structure
-+**   apfw_image  firmware image.
-+**
-+** Returns:
-+**    NOT_OK  firmware image corrupted or not correctly written
-+**    OK      success
-+*/
-+static int
-+acx_s_validate_fw(wlandevice_t *priv, const firmware_image_t *apfw_image,
-+                              u32 offset)
-+{
-+      u32 v32, w32, sum;
-+      int len, size;
-+      int result = OK;
-+      /* we skip the first four bytes which contain the control sum */
-+      const u8 *image = (u8*)apfw_image + 4;
-+
-+      /* start the image checksum by adding the image size value */
-+      sum = image[0]+image[1]+image[2]+image[3];
-+      image += 4;
-+
-+      acx_write_reg32(priv, IO_ACX_SLV_END_CTL, 0);
-+
-+#if NO_AUTO_INCREMENT
-+      acx_write_reg32(priv, IO_ACX_SLV_MEM_CTL, 0); /* use basic mode */
-+#else
-+      acx_write_reg32(priv, IO_ACX_SLV_MEM_CTL, 1); /* use autoincrement mode */
-+      acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR, offset); /* configure start address */
-+#endif
-+
-+      len = 0;
-+      size = le32_to_cpu(apfw_image->size) & (~3);
-+
-+      while (likely(len < size)) {
-+              v32 = be32_to_cpu(*(u32*)image);
-+              image += 4;
-+              len += 4;
-+
-+#if NO_AUTO_INCREMENT
-+              acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR, offset + len - 4);
-+#endif
-+              w32 = acx_read_reg32(priv, 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(apfw_image->chksum)) {
-+                      printk("acx: FATAL: firmware upload: "
-+                              "checksums don't match!\n");
-+                      result = NOT_OK;
-+              }
-+      }
-+
-+      return result;
-+}
-+
-+
-+/***********************************************************************
-+** acx_s_upload_fw
-+**
-+** Arguments:
-+**    wlandevice: private device that contains card device
-+** Returns:
-+**    NOT_OK: failed
-+**    OK: success
-+** Call context:
-+**    acx_reset_dev
-+*/
-+static int
-+acx_s_upload_fw(wlandevice_t *priv)
-+{
-+      firmware_image_t *apfw_image = NULL;
-+      int res = NOT_OK;
-+      int try;
-+      u32 size;
-+      char filename[sizeof("tiacx1NNcNN")];
-+
-+      FN_ENTER;
-+
-+      /* Try combined, then main image */
-+      priv->need_radio_fw = 0;
-+      sprintf(filename, "tiacx1%02dc%02X",
-+              IS_ACX111(priv)*11, priv->radio_type);
-+
-+      apfw_image = acx_s_read_fw(&priv->pdev->dev, filename, &size);
-+      if (!apfw_image) {
-+              priv->need_radio_fw = 1;
-+              filename[sizeof("tiacx1NN")-1] = '\0';
-+              apfw_image = acx_s_read_fw(&priv->pdev->dev, filename, &size);
-+              if (!apfw_image) {
-+                      FN_EXIT1(NOT_OK);
-+                      return NOT_OK;
-+              }
-+      }
-+
-+      for (try = 1; try <= 5; try++) {
-+              res = acx_s_write_fw(priv, apfw_image, 0);
-+              acxlog(L_DEBUG|L_INIT, "acx_write_fw (main/combined):%d\n", res);
-+              if (OK == res) {
-+                      res = acx_s_validate_fw(priv, apfw_image, 0);
-+                      acxlog(L_DEBUG|L_INIT, "acx_validate_fw "
-+                                      "(main/combined):%d\n", res);
-+              }
-+
-+              if (OK == res) {
-+                      SET_BIT(priv->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(apfw_image);
-+
-+      FN_EXIT1(res);
-+      return res;
-+}
-+
-+
-+/***********************************************************************
-+** acx_s_upload_radio
-+**
-+** Uploads the appropriate radio module firmware
-+** into the card.
-+*/
-+int
-+acx_s_upload_radio(wlandevice_t *priv)
-+{
-+      acx_ie_memmap_t mm;
-+      firmware_image_t *radio_image = NULL;
-+      acx_cmd_radioinit_t radioinit;
-+      int res = NOT_OK;
-+      int try;
-+      u32 offset;
-+      u32 size;
-+      char filename[sizeof("tiacx1NNrNN")];
-+
-+      if (!priv->need_radio_fw) return OK;
-+
-+      FN_ENTER;
-+
-+      acx_s_interrogate(priv, &mm, ACX1xx_IE_MEMORY_MAP);
-+      offset = le32_to_cpu(mm.CodeEnd);
-+
-+      sprintf(filename, "tiacx1%02dr%02X",
-+              IS_ACX111(priv)*11,
-+              priv->radio_type);
-+      radio_image = acx_s_read_fw(&priv->pdev->dev, filename, &size);
-+      if (!radio_image) {
-+              printk("acx: can't load radio module '%s'\n", filename);
-+              goto fail;
-+      }
-+
-+      acx_s_issue_cmd(priv, ACX1xx_CMD_SLEEP, NULL, 0);
-+
-+      for (try = 1; try <= 5; try++) {
-+              res = acx_s_write_fw(priv, radio_image, offset);
-+              acxlog(L_DEBUG|L_INIT, "acx_write_fw (radio): %d\n", res);
-+              if (OK == res) {
-+                      res = acx_s_validate_fw(priv, radio_image, offset);
-+                      acxlog(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(priv, 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(priv, ACX1xx_CMD_RADIOINIT,
-+              &radioinit, sizeof(radioinit), CMD_TIMEOUT_MS(1000));
-+
-+      res = acx_s_interrogate(priv, &mm, ACX1xx_IE_MEMORY_MAP);
-+fail:
-+      FN_EXIT1(res);
-+      return res;
-+}
-+
-+
-+/***********************************************************************
-+** acx_l_reset_mac
-+**
-+** Arguments:
-+**    wlandevice: private device that contains card device
-+** Side effects:
-+**    MAC will be reset
-+** Call context:
-+**    acx_reset_dev
-+** Comment:
-+**    resets onboard acx100 MAC
-+**
-+** Requires lock to be taken
-+*/
-+static void
-+acx_l_reset_mac(wlandevice_t *priv)
-+{
-+      u16 temp;
-+
-+      FN_ENTER;
-+
-+      /* halt eCPU */
-+      temp = acx_read_reg16(priv, IO_ACX_ECPU_CTRL) | 0x1;
-+      acx_write_reg16(priv, IO_ACX_ECPU_CTRL, temp);
-+
-+      /* now do soft reset of eCPU */
-+      temp = acx_read_reg16(priv, IO_ACX_SOFT_RESET) | 0x1;
-+      acxlog(L_DEBUG, "%s: enable soft reset...\n", __func__);
-+      acx_write_reg16(priv, IO_ACX_SOFT_RESET, temp);
-+      acx_write_flush(priv);
-+
-+      /* now reset bit again */
-+      acxlog(L_DEBUG, "%s: disable soft reset and go to init mode...\n", __func__);
-+      /* deassert eCPU reset */
-+      acx_write_reg16(priv, IO_ACX_SOFT_RESET, temp & ~0x1);
-+
-+      /* now start a burst read from initial flash EEPROM */
-+      temp = acx_read_reg16(priv, IO_ACX_EE_START) | 0x1;
-+      acx_write_reg16(priv, IO_ACX_EE_START, temp);
-+      acx_write_flush(priv);
-+
-+      FN_EXIT0;
-+}
-+
-+
-+/***********************************************************************
-+** acx_s_verify_init
-+*/
-+static int
-+acx_s_verify_init(wlandevice_t *priv)
-+{
-+      int result = NOT_OK;
-+      int timer;
-+
-+      FN_ENTER;
-+
-+      for (timer = 40; timer > 0; timer--) {
-+              u16 irqstat = acx_read_reg16(priv, IO_ACX_IRQ_STATUS_NON_DES);
-+              if (irqstat & HOST_INT_FCS_THRESHOLD) {
-+                      result = OK;
-+                      acx_write_reg16(priv, IO_ACX_IRQ_ACK, HOST_INT_FCS_THRESHOLD);
-+                      break;
-+              }
-+              /* HZ / 50 resulted in 24 schedules for ACX100 on my machine,
-+               * so better schedule away longer for greater efficiency,
-+               * decrease loop count */
-+              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
-+*/
-+
-+/***********************************************************************
-+** acx_read_info_status
-+*/
-+/* Info mailbox format:
-+2 bytes: type
-+2 bytes: status
-+more bytes may follow
-+    docs 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 is no message 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
-+acx_read_info_status(wlandevice_t *priv)
-+{
-+      u32 value;
-+
-+      acx_write_reg32(priv, IO_ACX_SLV_END_CTL, 0x0);
-+      acx_write_reg32(priv, IO_ACX_SLV_MEM_CTL, 0x1);
-+
-+      acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR,
-+              acx_read_reg32(priv, IO_ACX_INFO_MAILBOX_OFFS));
-+
-+      /* make sure we only read the data once all cfg registers are written: */
-+      acx_write_flush(priv);
-+      value = acx_read_reg32(priv, IO_ACX_SLV_MEM_DATA);
-+
-+      priv->info_type = (u16)value;
-+      priv->info_status = (value >> 16);
-+
-+      /* inform hw that we have read this info message */
-+      acx_write_reg32(priv, IO_ACX_SLV_MEM_DATA, priv->info_type | 0x00010000);
-+      acx_write_flush(priv);
-+      /* now bother hw to notice it: */
-+      acx_write_reg16(priv, IO_ACX_INT_TRIG, INT_TRIG_INFOACK);
-+      acx_write_flush(priv);
-+
-+      acxlog(L_CTL, "info_type 0x%04X, info_status 0x%04X\n",
-+                      priv->info_type, priv->info_status);
-+}
-+
-+
-+/***********************************************************************
-+** acx_write_cmd_type_or_status
-+*/
-+static void
-+acx_write_cmd_type_or_status(wlandevice_t *priv, u32 val)
-+{
-+      acx_write_reg32(priv, IO_ACX_SLV_END_CTL, 0x0);
-+      acx_write_reg32(priv, IO_ACX_SLV_MEM_CTL, 0x1); /* FIXME: why auto increment?? */
-+
-+      acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR,
-+              acx_read_reg32(priv, IO_ACX_CMD_MAILBOX_OFFS));
-+
-+      /* make sure we only write the data once all config registers are written */
-+      acx_write_flush(priv);
-+      acx_write_reg32(priv, IO_ACX_SLV_MEM_DATA, val);
-+      acx_write_flush(priv);
-+}
-+static inline void
-+acx_write_cmd_type(wlandevice_t *priv, u32 val)
-+{
-+      acx_write_cmd_type_or_status(priv, val);
-+}
-+static inline void
-+acx_write_cmd_status(wlandevice_t *priv, u32 val)
-+{
-+      acx_write_cmd_type_or_status(priv, val<<16);
-+}
-+
-+
-+/***********************************************************************
-+** acx_read_cmd_status
-+*/
-+static void
-+acx_read_cmd_status(wlandevice_t *priv)
-+{
-+      u32 value;
-+
-+      acx_write_reg32(priv, IO_ACX_SLV_END_CTL, 0x0);
-+      acx_write_reg32(priv, IO_ACX_SLV_MEM_CTL, 0x1); /* FIXME: why auto increment?? */
-+
-+      acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR,
-+              acx_read_reg32(priv, IO_ACX_CMD_MAILBOX_OFFS));
-+
-+      /* make sure we only read the data once all config registers are written */
-+      acx_write_flush(priv);
-+      value = acx_read_reg32(priv, IO_ACX_SLV_MEM_DATA);
-+
-+      priv->cmd_type = (u16)value;
-+      priv->cmd_status = (value >> 16);
-+
-+      acxlog(L_CTL, "cmd_type 0x%04X, cmd_status 0x%04X [%s]\n",
-+              priv->cmd_type, priv->cmd_status,
-+              acx_cmd_status_str(priv->cmd_status));
-+}
-+
-+
-+/***********************************************************************
-+** acx_s_reset_dev
-+**
-+** Arguments:
-+**    netdevice that contains the wlandevice priv variable
-+** Returns:
-+**    NOT_OK on fail
-+**    OK on success
-+** Side effects:
-+**    device is hard reset
-+** Call context:
-+**    acx_probe_pci
-+** Comment:
-+**    This resets the acx100 device using low level hardware calls
-+**    as well as uploads and verifies the firmware to the card
-+*/
-+static int
-+acx_s_reset_dev(netdevice_t *dev)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+      const char* msg = "";
-+      unsigned long flags;
-+      int result = NOT_OK;
-+      u16 hardware_info;
-+      u16 ecpu_ctrl;
-+
-+      FN_ENTER;
-+
-+      /* we're doing a reset, so hardware is unavailable */
-+
-+      /* reset the device to make sure the eCPU is stopped
-+       * to upload the firmware correctly */
-+
-+      acx_lock(priv, flags);
-+
-+      acx_l_reset_mac(priv);
-+
-+      ecpu_ctrl = acx_read_reg16(priv, IO_ACX_ECPU_CTRL) & 1;
-+      if (!ecpu_ctrl) {
-+              msg = "eCPU is already running. ";
-+              goto fail_unlock;
-+      }
-+
-+#ifdef WE_DONT_NEED_THAT_DO_WE
-+      if (acx_read_reg16(priv, IO_ACX_SOR_CFG) & 2) {
-+              /* eCPU most likely means "embedded CPU" */
-+              msg = "eCPU did not start after boot from flash. ";
-+              goto fail_unlock;
-+      }
-+
-+      /* check sense on reset flags */
-+      if (acx_read_reg16(priv, IO_ACX_SOR_CFG) & 0x10) {
-+              printk("%s: eCPU did not start after boot (SOR), "
-+                      "is this fatal?\n", dev->name);
-+      }
-+#endif
-+      /* scan, if any, is stopped now, setting corresponding IRQ bit */
-+      priv->irq_status |= HOST_INT_SCAN_COMPLETE;
-+
-+      acx_unlock(priv, flags);
-+
-+      /* without this delay acx100 may fail to report hardware_info
-+      ** (see below). Most probably eCPU runs some init code */
-+      acx_s_msleep(10);
-+
-+      /* Need to know radio type before fw load */
-+      hardware_info = acx_read_reg16(priv, IO_ACX_EEPROM_INFORMATION);
-+      priv->form_factor = hardware_info & 0xff;
-+      priv->radio_type = hardware_info >> 8;
-+
-+      /* load the firmware */
-+      if (OK != acx_s_upload_fw(priv))
-+              goto fail;
-+
-+      acx_s_msleep(10);
-+
-+      /* now start eCPU by clearing bit */
-+      acxlog(L_DEBUG, "booted eCPU up and waiting for completion...\n");
-+      acx_write_reg16(priv, IO_ACX_ECPU_CTRL, ecpu_ctrl & ~0x1);
-+
-+      /* wait for eCPU bootup */
-+      if (OK != acx_s_verify_init(priv)) {
-+              msg = "timeout waiting for eCPU. ";
-+              goto fail;
-+      }
-+
-+      acxlog(L_DEBUG, "eCPU has woken up, card is ready to be configured\n");
-+
-+      if (IS_ACX111(priv)) {
-+              acxlog(L_DEBUG, "cleaning up cmd mailbox access area\n");
-+              acx_write_cmd_status(priv, 0);
-+              acx_read_cmd_status(priv);
-+              if (priv->cmd_status) {
-+                      msg = "error cleaning cmd mailbox area. ";
-+                      goto fail;
-+              }
-+      }
-+
-+      /* TODO what is this one doing ?? adapt for acx111 */
-+      if ((OK != acx_read_eeprom_area(priv)) && IS_ACX100(priv)) {
-+              /* does "CIS" mean "Card Information Structure"?
-+               * If so, then this would be a PCMCIA message...
-+               */
-+              msg = "CIS error. ";
-+              goto fail;
-+      }
-+
-+      result = OK;
-+      FN_EXIT1(result);
-+      return result;
-+
-+/* Finish error message. Indicate which function failed */
-+fail_unlock:
-+      acx_unlock(priv, flags);
-+fail:
-+      printk("acx: %sreset_dev() FAILED\n", msg);
-+      FN_EXIT1(result);
-+      return result;
-+}
-+
-+
-+/***********************************************************************
-+** acx_init_mboxes
-+*/
-+void
-+acx_init_mboxes(wlandevice_t *priv)
-+{
-+      u32 cmd_offs, info_offs;
-+
-+      FN_ENTER;
-+
-+      cmd_offs = acx_read_reg32(priv, IO_ACX_CMD_MAILBOX_OFFS);
-+      info_offs = acx_read_reg32(priv, IO_ACX_INFO_MAILBOX_OFFS);
-+      priv->cmd_area = (u8 *)priv->iobase2 + cmd_offs + 0x4;
-+      priv->info_area = (u8 *)priv->iobase2 + info_offs + 0x4;
-+      acxlog(L_DEBUG, "iobase2=%p\n"
-+              "cmd_mbox_offset=%X cmd_area=%p\n"
-+              "info_mbox_offset=%X info_area=%p\n",
-+              priv->iobase2,
-+              cmd_offs, priv->cmd_area,
-+              info_offs, priv->info_area);
-+
-+      FN_EXIT0;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_s_issue_cmd_timeo
-+* Excecutes a command in the command mailbox
-+*
-+* Arguments:
-+*   *pcmdparam = an pointer to the data. The data mustn't include
-+*                the 4 byte command header!
-+*
-+* 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(
-+      wlandevice_t *priv,
-+      unsigned int cmd,
-+      void *buffer,
-+      unsigned buflen,
-+      unsigned timeout)
-+{
-+#else
-+int
-+acxpci_s_issue_cmd_timeo_debug(
-+      wlandevice_t *priv,
-+      unsigned cmd,
-+      void *buffer,
-+      unsigned buflen,
-+      unsigned timeout,
-+      const char* cmdstr)
-+{
-+      unsigned long start = jiffies;
-+#endif
-+      const char *devname;
-+      unsigned counter;
-+      u16 irqtype;
-+      u16 cmd_status;
-+
-+      FN_ENTER;
-+
-+      devname = priv->netdev->name;
-+      if (!devname || !devname[0])
-+              devname = "acx";
-+
-+      acxlog(L_CTL, FUNC"(cmd:%s,buflen:%u,timeout:%ums,type:0x%04X)\n",
-+              cmdstr, buflen, timeout,
-+              buffer ? le16_to_cpu(((acx_ie_generic_t *)buffer)->type) : -1);
-+
-+      if (!(priv->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 pdr (len=%u):\n", buflen);
-+              acx_dump_bytes(buffer, buflen);
-+      }
-+
-+      /* wait for firmware to become idle for our command submission */
-+      counter = 199; /* in ms */
-+      do {
-+              acx_read_cmd_status(priv);
-+              /* Test for IDLE state */
-+              if (!priv->cmd_status)
-+                      break;
-+              if (counter % 10 == 0) {
-+                      /* we waited 10 iterations, no luck. Sleep 10 ms */
-+                      acx_s_msleep(10);
-+              }
-+      } while (--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, priv->cmd_status);
-+              goto bad;
-+      } else if (counter < 190) { /* if waited >10ms... */
-+              acxlog(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(priv->cmd_area, 0xAA, buflen);
-+#endif
-+              memcpy(priv->cmd_area, buffer,
-+                      (cmd == ACX1xx_CMD_INTERROGATE) ? 4 : buflen);
-+      }
-+      /* now write the actual command type */
-+      priv->cmd_type = cmd;
-+      acx_write_cmd_type(priv, cmd);
-+      /* execute command */
-+      acx_write_reg16(priv, IO_ACX_INT_TRIG, INT_TRIG_CMD);
-+      acx_write_flush(priv);
-+
-+      /* 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 */
-+      timeout = (timeout-1) | 1;
-+      if (unlikely(timeout > 1199))
-+              timeout = 1199;
-+      /* clear CMD_COMPLETE bit. can be set only by IRQ handler: */
-+      priv->irq_status &= ~HOST_INT_CMD_COMPLETE;
-+
-+      /* we schedule away sometimes (timeout can be large) */
-+      counter = timeout;
-+      do {
-+              if (!priv->irqs_active) { /* IRQ disabled: poll */
-+                      irqtype = acx_read_reg16(priv, IO_ACX_IRQ_STATUS_NON_DES);
-+                      if (irqtype & HOST_INT_CMD_COMPLETE) {
-+                              acx_write_reg16(priv, IO_ACX_IRQ_ACK,
-+                                              HOST_INT_CMD_COMPLETE);
-+                              break;
-+                      }
-+              } else { /* Wait when IRQ will set the bit */
-+                      irqtype = priv->irq_status;
-+                      if (irqtype & HOST_INT_CMD_COMPLETE)
-+                              break;
-+              }
-+
-+              if (counter % 10 == 0) {
-+                      /* we waited 10 iterations, no luck. Sleep 10 ms */
-+                      acx_s_msleep(10);
-+              }
-+      } while (--counter);
-+
-+      /* save state for debugging */
-+      acx_read_cmd_status(priv);
-+      cmd_status = priv->cmd_status;
-+
-+      /* put the card in IDLE state */
-+      priv->cmd_status = 0;
-+      acx_write_cmd_status(priv, 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, (priv->irqs_active) ? "waiting" : "polling",
-+                      irqtype, priv->irq_status, timeout,
-+                      cmd_status, acx_cmd_status_str(cmd_status));
-+              goto bad;
-+      } else if (timeout - counter > 30) { /* if waited >30ms... */
-+              acxlog(L_CTL|L_DEBUG, FUNC"(): %s for CMD_COMPLETE %dms. "
-+                      "count:%d. Please report\n",
-+                      (priv->irqs_active) ? "waited" : "polled",
-+                      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),
-+                      timeout - counter, timeout);
-+              /* zero out result buffer */
-+              if (buffer && buflen)
-+                      memset(buffer, 0, buflen);
-+              goto bad;
-+      }
-+
-+      /* read in result parameters if needed */
-+      if (buffer && buflen && (cmd == ACX1xx_CMD_INTERROGATE)) {
-+              memcpy(buffer, priv->cmd_area, buflen);
-+              if (acx_debug & L_DEBUG) {
-+                      printk("output buffer (len=%u): ", buflen);
-+                      acx_dump_bytes(buffer, buflen);
-+              }
-+      }
-+/* ok: */
-+      acxlog(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;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_s_get_firmware_version
-+*----------------------------------------------------------------*/
-+static void
-+acx_s_get_firmware_version(wlandevice_t *priv)
-+{
-+      fw_ver_t fw;
-+      u8 hexarr[4] = { 0, 0, 0, 0 };
-+      int hexidx = 0, val = 0;
-+      const char *num;
-+      char c;
-+
-+      FN_ENTER;
-+
-+      acx_s_interrogate(priv, &fw, ACX1xx_IE_FWREV);
-+      memcpy(priv->firmware_version, fw.fw_id, FW_ID_SIZE);
-+      priv->firmware_version[FW_ID_SIZE] = '\0';
-+      acxlog(L_DEBUG, "fw_ver: fw_id='%s' hw_id=%08X\n",
-+                              priv->firmware_version, fw.hw_id);
-+
-+      if (strncmp(fw.fw_id, "Rev ", 4) != 0) {
-+              printk("acx: strange firmware version string "
-+                      "'%s', please report\n", priv->firmware_version);
-+              priv->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;
-+              }
-+
-+              priv->firmware_numver = (u32)(
-+                              (hexarr[0] << 24) + (hexarr[1] << 16)
-+                              + (hexarr[2] << 8) + hexarr[3]);
-+              acxlog(L_DEBUG, "firmware_numver 0x%08X\n", priv->firmware_numver);
-+      }
-+      if (IS_ACX111(priv)) {
-+              if (priv->firmware_numver == 0x00010011) {
-+                      /* This one does not survive floodpinging */
-+                      printk("acx: firmware '%s' is known to be buggy, "
-+                              "please upgrade\n", priv->firmware_version);
-+              }
-+              if (priv->firmware_numver == 0x02030131) {
-+                      /* With this one, all rx packets look mangled
-+                      ** Most probably we simply do not know how to use it
-+                      ** properly */
-+                      printk("acx: firmware '%s' does not work well "
-+                              "with this driver\n", priv->firmware_version);
-+              }
-+      }
-+
-+      priv->firmware_id = le32_to_cpu(fw.hw_id);
-+
-+      /* we're able to find out more detailed chip names now */
-+      switch (priv->firmware_id & 0xffff0000) {
-+              case 0x01010000:
-+              case 0x01020000:
-+                      priv->chip_name = name_tnetw1100a;
-+                      break;
-+              case 0x01030000:
-+                      priv->chip_name = name_tnetw1100b;
-+                      break;
-+              case 0x03000000:
-+              case 0x03010000:
-+                      priv->chip_name = name_tnetw1130;
-+                      break;
-+              default:
-+                      printk("acx: unknown chip ID 0x%08X, "
-+                              "please report\n", priv->firmware_id);
-+                      break;
-+      }
-+
-+      FN_EXIT0;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_display_hardware_details
-+*
-+* Arguments:
-+*     priv: ptr to wlandevice that contains all the details
-+*       displayed by this function
-+* Call context:
-+*     acx_probe_pci
-+* Comment:
-+*     This function will display strings to the system log according
-+* to device form_factor and radio type. It will needed to be
-+*----------------------------------------------------------------*/
-+static void
-+acx_display_hardware_details(wlandevice_t *priv)
-+{
-+      const char *radio_str, *form_str;
-+
-+      FN_ENTER;
-+
-+      switch (priv->radio_type) {
-+      case RADIO_MAXIM_0D:
-+              /* hmm, the DWL-650+ seems to have two variants,
-+               * according to a windows driver changelog comment:
-+               * RFMD and Maxim. */
-+              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;
-+      default:
-+              radio_str = "UNKNOWN, please report the radio type name!";
-+              break;
-+      }
-+
-+      switch (priv->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: form factor 0x%02X (%s), "
-+              "radio type 0x%02X (%s), EEPROM version 0x%02X, "
-+              "uploaded firmware '%s' (0x%08X)\n",
-+              priv->form_factor, form_str, priv->radio_type, radio_str,
-+              priv->eeprom_version, priv->firmware_version,
-+              priv->firmware_id);
-+
-+      FN_EXIT0;
-+}
-+
-+/***********************************************************************
-+*/
-+#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(wlandevice_t *priv)
-+{
-+      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 != acx_read_eeprom_offset(priv,
-+                                       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 */
-+
-+
-+/***********************************************************************
-+*/
-+static void
-+acx_s_device_chain_add(struct net_device *dev)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+
-+      down(&root_acx_dev_sem);
-+      priv->prev_nd = root_acx_dev.newest;
-+      root_acx_dev.newest = dev;
-+      priv->netdev = dev;
-+      up(&root_acx_dev_sem);
-+}
-+
-+static void
-+acx_s_device_chain_remove(struct net_device *dev)
-+{
-+      struct net_device *querydev;
-+      struct net_device *olderdev;
-+      struct net_device *newerdev;
-+
-+      down(&root_acx_dev_sem);
-+      querydev = root_acx_dev.newest;
-+      newerdev = NULL;
-+      while (querydev) {
-+              olderdev = ((wlandevice_t*)netdev_priv(querydev))->prev_nd;
-+              if (0 == strcmp(querydev->name, dev->name)) {
-+                      if (!newerdev) {
-+                              /* if we were at the beginning of the
-+                               * list, then it's the list head that
-+                               * we need to update to point at the
-+                               * next older device */
-+                              root_acx_dev.newest = olderdev;
-+                      } else {
-+                              /* it's the device that is newer than us
-+                               * that we need to update to point at
-+                               * the device older than us */
-+                              ((wlandevice_t*)netdev_priv(newerdev))->
-+                                      prev_nd = olderdev;
-+                      }
-+                      break;
-+              }
-+              /* "newerdev" is actually the device of the old iteration,
-+               * but since the list starts (root_acx_dev.newest)
-+               * with the newest devices,
-+               * it's newer than the ones following.
-+               * Oh the joys of iterating from newest to oldest :-\ */
-+              newerdev = querydev;
-+
-+              /* keep checking old devices for matches until we hit the end
-+               * of the list */
-+              querydev = olderdev;
-+      }
-+      up(&root_acx_dev_sem);
-+}
-+
-+
-+/***********************************************************************
-+** acx_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
-+acx_free_coherent(struct pci_dev *hwdev, size_t size,
-+                      void *vaddr, dma_addr_t dma_handle)
-+{
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 53)
-+      dma_free_coherent(hwdev == NULL ? NULL : &hwdev->dev,
-+                      size, vaddr, dma_handle);
-+#else
-+      pci_free_consistent(hwdev, size, vaddr, dma_handle);
-+#endif
-+}
-+
-+void
-+acx_free_desc_queues(wlandevice_t *priv)
-+{
-+#define ACX_FREE_QUEUE(size, ptr, phyaddr) \
-+      if (ptr) { \
-+              acx_free_coherent(0, size, ptr, phyaddr); \
-+              ptr = NULL; \
-+              size = 0; \
-+      }
-+
-+      FN_ENTER;
-+
-+      ACX_FREE_QUEUE(priv->txhostdesc_area_size, priv->txhostdesc_start, priv->txhostdesc_startphy);
-+      ACX_FREE_QUEUE(priv->txbuf_area_size, priv->txbuf_start, priv->txbuf_startphy);
-+
-+      priv->txdesc_start = NULL;
-+
-+      ACX_FREE_QUEUE(priv->rxhostdesc_area_size, priv->rxhostdesc_start, priv->rxhostdesc_startphy);
-+      ACX_FREE_QUEUE(priv->rxbuf_area_size, priv->rxbuf_start, priv->rxbuf_startphy);
-+
-+      priv->rxdesc_start = NULL;
-+
-+      FN_EXIT0;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_s_delete_dma_regions
-+*----------------------------------------------------------------*/
-+static void
-+acx_s_delete_dma_regions(wlandevice_t *priv)
-+{
-+      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? */
-+      acx_write_reg16(priv, IO_ACX_ENABLE, 0);
-+
-+      acx_s_msleep(100);
-+
-+      acx_lock(priv, flags);
-+      acx_free_desc_queues(priv);
-+      acx_unlock(priv, flags);
-+
-+      FN_EXIT0;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_e_probe_pci
-+*
-+* 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
-+*
-+* Arguments:
-+*     pdev            ptr to pci device structure containing info about
-+*                     pci configuration.
-+*     id              ptr to the device id entry that matched this device.
-+*
-+* Returns:
-+*     zero            - success
-+*     negative        - failed
-+*
-+* Call context:
-+*     process thread
-+----------------------------------------------------------------*/
-+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 need 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
-+acx_netdev_init(struct net_device *dev) {}
-+
-+//FIXME: do the same for USB
-+static int
-+acx_change_mtu(struct net_device *dev, int mtu)
-+{
-+      enum {
-+              MIN_MTU = 256,
-+              MAX_MTU = WLAN_DATA_MAXLEN - (ETH_HLEN)
-+      };
-+
-+      if (mtu < MIN_MTU || mtu > MAX_MTU)
-+              return -EINVAL;
-+
-+      dev->mtu = mtu;
-+      return 0;
-+}
-+
-+static int __devinit
-+acx_e_probe_pci(struct pci_dev *pdev, const struct pci_device_id *id)
-+{
-+      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;
-+      wlandevice_t *priv = NULL;
-+      struct net_device *dev = NULL;
-+      const char *chip_name;
-+      int result = -EIO;
-+      int err;
-+      u8 chip_type;
-+
-+#if SEPARATE_DRIVER_INSTANCES
-+      struct pci_dev *tdev;
-+      unsigned int inited;
-+      static int turn = 0;
-+#endif /* SEPARATE_DRIVER_INSTANCES */
-+
-+      FN_ENTER;
-+
-+#if SEPARATE_DRIVER_INSTANCES
-+      if (card) {
-+              turn++;
-+              inited = 0;
-+              pci_for_each_dev(tdev) {
-+                      if (tdev->vendor != PCI_VENDOR_ID_TI)
-+                              continue;
-+
-+                      if (tdev == pdev)
-+                              break;
-+                      if (pci_get_drvdata(tdev))
-+                              inited++;
-+              }
-+              if (inited + turn != card) {
-+                      result = -ENODEV;
-+                      goto done;
-+              }
-+      }
-+#endif /* SEPARATE_DRIVER_INSTANCES */
-+
-+      /* 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);
-+
-+      /* 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 = 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 = 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), "ACX1xx_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), "ACX1xx_2")) {
-+              printk("acx: cannot reserve PCI memory region 2\n");
-+              goto fail_request_mem_region2;
-+      }
-+
-+      mem1 = ioremap(phymem1, mem_region1_size);
-+      if (NULL == mem1) {
-+              printk("acx: ioremap() FAILED\n");
-+              goto fail_ioremap1;
-+      }
-+
-+      mem2 = ioremap(phymem2, mem_region2_size);
-+      if (NULL == mem2) {
-+              printk("acx: ioremap() #2 FAILED\n");
-+              goto fail_ioremap2;
-+      }
-+
-+      /* Log the device */
-+      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);
-+      acxlog(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;
-+      }
-+
-+      dev = alloc_netdev(sizeof(wlandevice_t), "wlan%d", acx_netdev_init);
-+      /* (NB: memsets to 0 entire area) */
-+      if (!dev) {
-+              printk("acx: no memory for netdevice structure\n");
-+              goto fail_alloc_netdev;
-+      }
-+
-+      ether_setup(dev);
-+      dev->open = &acx_e_open;
-+      dev->stop = &acx_e_close;
-+      dev->hard_start_xmit = &acx_i_start_xmit;
-+      dev->get_stats = &acx_e_get_stats;
-+      dev->get_wireless_stats = &acx_e_get_wireless_stats;
-+#if WIRELESS_EXT >= 13
-+      dev->wireless_handlers = (struct iw_handler_def *)&acx_ioctl_handler_def;
-+#else
-+      dev->do_ioctl = &acx_e_ioctl_old;
-+#endif
-+      dev->set_multicast_list = &acx_i_set_multicast_list;
-+      dev->tx_timeout = &acx_i_tx_timeout;
-+      dev->change_mtu = &acx_change_mtu;
-+      dev->watchdog_timeo = 4 * HZ;
-+      dev->irq = pdev->irq;
-+      dev->base_addr = pci_resource_start(pdev, 0);
-+
-+      priv = netdev_priv(dev);
-+      spin_lock_init(&priv->lock);    /* initial state: unlocked */
-+      /* We do not start with downed sem: we want PARANOID_LOCKING to work */
-+      sema_init(&priv->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(priv); */
-+      priv->pdev = pdev;
-+      priv->dev_type = DEVTYPE_PCI;
-+      priv->chip_type = chip_type;
-+      priv->chip_name = chip_name;
-+      priv->io = (CHIPTYPE_ACX100 == chip_type) ? IO_ACX100 : IO_ACX111;
-+      priv->membase = phymem1;
-+      priv->iobase = mem1;
-+      priv->membase2 = phymem2;
-+      priv->iobase2 = mem2;
-+      /* to find crashes due to weird driver access
-+       * to unconfigured interface (ifup) */
-+      priv->mgmt_timer.function = (void (*)(unsigned long))0x0000dead;
-+
-+#ifdef NONESSENTIAL_FEATURES
-+      acx_show_card_eeprom_id(priv);
-+#endif /* NONESSENTIAL_FEATURES */
-+
-+      /* 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(dev, "after setup");
-+
-+#ifdef SET_MODULE_OWNER
-+      SET_MODULE_OWNER(dev);
-+#endif
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 70)
-+      /* this define and its netdev member exist since 2.5.70 */
-+      SET_NETDEV_DEV(dev, &pdev->dev);
-+#endif
-+
-+      /* register new dev in linked list */
-+      acx_s_device_chain_add(dev);
-+
-+      acxlog(L_IRQ|L_INIT, "using IRQ %d\n", pdev->irq);
-+
-+      /* need to be able to restore PCI state after a suspend */
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
-+      /* 2.6.9-rc3-mm2 (2.6.9-bk4, too) introduced this shorter version,
-+         then it made its way into 2.6.10 */
-+      pci_save_state(pdev);
-+#else
-+      pci_save_state(pdev, priv->pci_state);
-+#endif
-+
-+      /* NB: acx_read_reg() reads may return bogus data before reset_dev().
-+      ** acx100 seems to be more affected than acx111 */
-+      if (OK != acx_s_reset_dev(dev)) {
-+              goto fail_reset;
-+      }
-+
-+      /* ok, basic setup is finished, now start initialising the card */
-+
-+      if (OK != acx_read_eeprom_offset(priv, 0x05, &priv->eeprom_version)) {
-+              goto fail_read_eeprom_version;
-+      }
-+
-+      if (OK != acx_s_init_mac(dev)) {
-+              printk("acx: init_mac() FAILED\n");
-+              goto fail_init_mac;
-+      }
-+      if (OK != acx_s_set_defaults(priv)) {
-+              printk("acx: set_defaults() FAILED\n");
-+              goto fail_set_defaults;
-+      }
-+
-+      /* needs to be after acx_s_init_mac() due to necessary init stuff */
-+      acx_s_get_firmware_version(priv);
-+
-+      acx_display_hardware_details(priv);
-+
-+      pci_set_drvdata(pdev, dev);
-+
-+      /* ...and 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(dev);
-+      if (OK != err) {
-+              printk("acx: register_netdev() FAILED: %d\n", err);
-+              goto fail_register_netdev;
-+      }
-+
-+      acx_carrier_off(dev, "on probe");
-+
-+#ifdef CONFIG_PROC_FS
-+      if (OK != acx_proc_register_entries(dev)) {
-+              goto fail_proc_register_entries;
-+      }
-+#endif
-+
-+      /* after register_netdev() userspace may start working with dev
-+       * (in particular, on other CPUs), we only need to up the sem */
-+      /* acx_sem_unlock(priv); */
-+
-+      printk("acx "WLAN_RELEASE": net device %s, driver compiled "
-+              "against wireless extensions %d and Linux %s\n",
-+              dev->name, WIRELESS_EXT, UTS_RELEASE);
-+
-+#if CMD_DISCOVERY
-+      great_inquisitor(priv);
-+#endif
-+
-+      result = OK;
-+      goto done;
-+
-+      /* error paths: undo everything in reverse order... */
-+
-+#ifdef CONFIG_PROC_FS
-+fail_proc_register_entries:
-+
-+      if (priv->dev_state_mask & ACX_STATE_IFACE_UP)
-+              acx_s_down(dev);
-+
-+      unregister_netdev(dev);
-+
-+      /* after unregister_netdev() userspace is guaranteed to finish
-+       * working with it. netdev does not exist anymore.
-+       * For paranoid reasons I am taking sem anyway */
-+      acx_sem_lock(priv);
-+#endif
-+
-+fail_register_netdev:
-+
-+      acx_s_delete_dma_regions(priv);
-+      pci_set_drvdata(pdev, NULL);
-+
-+fail_set_defaults:
-+fail_init_mac:
-+fail_read_eeprom_version:
-+fail_reset:
-+
-+      acx_s_device_chain_remove(dev);
-+      free_netdev(dev);
-+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, 3);
-+
-+done:
-+      FN_EXIT1(result);
-+      return result;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_e_remove_pci
-+*
-+* Deallocate PCI resources for the ACX100 chip.
-+*
-+* This should NOT execute any other hardware operations on the card,
-+* since the card might already be ejected. Instead, that should be done
-+* in cleanup_module, since the card is most likely still available there.
-+*
-+* Arguments:
-+*     pdev            ptr to PCI device structure containing info about
-+*                     PCI configuration.
-+*
-+* Call context:
-+*     process thread
-+----------------------------------------------------------------*/
-+static void __devexit
-+acx_e_remove_pci(struct pci_dev *pdev)
-+{
-+      struct net_device *dev;
-+      wlandevice_t *priv;
-+      unsigned long mem_region1, mem_region2;
-+
-+      FN_ENTER;
-+
-+      dev = (struct net_device *) pci_get_drvdata(pdev);
-+      if (!dev) {
-+              acxlog(L_DEBUG, "%s: card is unused. Skipping any release code\n",
-+                      __func__);
-+              goto end;
-+      }
-+
-+      priv = netdev_priv(dev);
-+
-+      /* unregister the device to not let the kernel
-+       * (e.g. ioctls) access a half-deconfigured device
-+       * NB: this will cause acx_e_close() to be called,
-+       * thus we shouldn't call it under sem! */
-+      acxlog(L_INIT, "removing device %s\n", dev->name);
-+      unregister_netdev(dev);
-+
-+      /* unregister_netdev ensures that no references to us left.
-+       * For paranoid reasons we continue to follow the rules */
-+      acx_sem_lock(priv);
-+
-+      if (IS_ACX100(priv)) {
-+              mem_region1 = PCI_ACX100_REGION1;
-+              mem_region2 = PCI_ACX100_REGION2;
-+      } else {
-+              mem_region1 = PCI_ACX111_REGION1;
-+              mem_region2 = PCI_ACX111_REGION2;
-+      }
-+
-+#ifdef CONFIG_PROC_FS
-+      acx_proc_unregister_entries(dev);
-+#endif
-+
-+      /* find our PCI device in the global acx list and remove it */
-+      acx_s_device_chain_remove(dev);
-+
-+      if (priv->dev_state_mask & ACX_STATE_IFACE_UP)
-+              acx_s_down(dev);
-+
-+      CLEAR_BIT(priv->dev_state_mask, ACX_STATE_IFACE_UP);
-+
-+      acx_s_delete_dma_regions(priv);
-+
-+      /* finally, clean up PCI bus state */
-+      if (priv->iobase) iounmap(priv->iobase);
-+      if (priv->iobase2) iounmap(priv->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);
-+
-+      /* Free netdev (quite late,
-+       * since otherwise we might get caught off-guard
-+       * by a netdev timeout handler execution
-+       * expecting to see a working dev...)
-+       * But don't use free_netdev() here,
-+       * it's supported by newer kernels only */
-+      free_netdev(dev);
-+
-+      /* put device into ACPI D3 mode (shutdown) */
-+      pci_set_power_state(pdev, 3);
-+
-+end:
-+      FN_EXIT0;
-+}
-+
-+
-+/***********************************************************************
-+*/
-+#ifdef CONFIG_PM
-+static int if_was_up = 0; /* FIXME: HACK, do it correctly sometime instead */
-+static int
-+acx_e_suspend(struct pci_dev *pdev, pm_message_t state)
-+{
-+      struct net_device *dev = pci_get_drvdata(pdev);
-+      wlandevice_t *priv = netdev_priv(dev);
-+
-+      FN_ENTER;
-+
-+      acx_sem_lock(priv);
-+
-+      printk("acx: experimental suspend handler called for %p\n", priv);
-+      if (netif_device_present(dev)) {
-+              if_was_up = 1;
-+              acx_s_down(dev);
-+      }
-+      else
-+              if_was_up = 0;
-+
-+      netif_device_detach(dev);       /* This one cannot sleep */
-+      acx_s_delete_dma_regions(priv);
-+
-+      acx_sem_unlock(priv);
-+
-+      FN_EXIT0;
-+      return OK;
-+}
-+
-+static int
-+acx_e_resume(struct pci_dev *pdev)
-+{
-+      struct net_device *dev;
-+      wlandevice_t *priv;
-+
-+      printk(KERN_WARNING "rsm: resume\n");
-+      dev = pci_get_drvdata(pdev);
-+      printk(KERN_WARNING "rsm: got dev\n");
-+
-+      if (!netif_running(dev))
-+              return 0;
-+
-+      priv = netdev_priv(dev);
-+
-+      acx_sem_lock(priv);
-+
-+      printk(KERN_WARNING "rsm: got priv\n");
-+      FN_ENTER;
-+      printk("acx: experimental resume handler called for %p!\n", priv);
-+      pci_set_power_state(pdev, 0);
-+      acxlog(L_DEBUG, "rsm: power state set\n");
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
-+      /* 2.6.9-rc3-mm2 (2.6.9-bk4, too) introduced this shorter version,
-+         then it made its way into 2.6.10 */
-+      pci_restore_state(pdev);
-+#else
-+      pci_restore_state(pdev, priv->pci_state);
-+#endif
-+      acxlog(L_DEBUG, "rsm: PCI state restored\n");
-+      acx_s_reset_dev(dev);
-+      acxlog(L_DEBUG, "rsm: device reset done\n");
-+
-+      if (OK != acx_s_init_mac(dev)) {
-+              printk("rsm: init_mac FAILED\n");
-+              goto fail;
-+      }
-+      acxlog(L_DEBUG, "rsm: init MAC done\n");
-+
-+      if (1 == if_was_up)
-+              acx_s_up(dev);
-+      acxlog(L_DEBUG, "rsm: acx up\n");
-+
-+      /* now even reload all card parameters as they were before suspend,
-+       * and possibly be back in the network again already :-)
-+       * FIXME: should this be done in that scheduled task instead?? */
-+      if (ACX_STATE_IFACE_UP & priv->dev_state_mask)
-+              acx_s_update_card_settings(priv, 0, 1);
-+      acxlog(L_DEBUG, "rsm: settings updated\n");
-+      netif_device_attach(dev);
-+      acxlog(L_DEBUG, "rsm: device attached\n");
-+fail: /* we need to return OK here anyway, right? */
-+      acx_sem_unlock(priv);
-+      FN_EXIT0;
-+      return OK;
-+}
-+#endif /* CONFIG_PM */
-+
-+
-+/*----------------------------------------------------------------
-+* acx_s_up
-+*
-+* Side effects:
-+*     - Enables on-card interrupt requests
-+*     - calls acx_start
-+* Call context:
-+*     - process thread
-+* Comment:
-+*     This function is called by acx_open (when ifconfig sets the
-+*     device as up).
-+*----------------------------------------------------------------*/
-+static void
-+acx_s_up(netdevice_t *dev)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+      unsigned long flags;
-+
-+      FN_ENTER;
-+
-+      acx_lock(priv, flags);
-+      acx_l_enable_irq(priv);
-+      acx_unlock(priv, 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(&priv->mgmt_timer);
-+      priv->mgmt_timer.function = acx_i_timer;
-+      priv->mgmt_timer.data = (unsigned long)priv;
-+
-+      /* Need to set ACX_STATE_IFACE_UP first, or else
-+      ** timer won't be started by acx_set_status() */
-+      SET_BIT(priv->dev_state_mask, ACX_STATE_IFACE_UP);
-+      switch (priv->mode) {
-+      case ACX_MODE_0_ADHOC:
-+      case ACX_MODE_2_STA:
-+              /* actual scan cmd will happen in start() */
-+              acx_set_status(priv, ACX_STATUS_1_SCANNING); break;
-+      case ACX_MODE_3_AP:
-+      case ACX_MODE_MONITOR:
-+              acx_set_status(priv, ACX_STATUS_4_ASSOCIATED); break;
-+      }
-+
-+      acx_s_start(priv);
-+
-+      FN_EXIT0;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_s_down
-+*
-+* Side effects:
-+*     - disables on-card interrupt request
-+* Call context:
-+*     process thread
-+* Comment:
-+*     this disables the netdevice
-+*----------------------------------------------------------------*/
-+static void
-+acx_s_down(netdevice_t *dev)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+      unsigned long flags;
-+
-+      FN_ENTER;
-+
-+      /* Disable IRQs first, so that IRQs cannot race with us */
-+      acx_lock(priv, flags);
-+      acx_l_disable_irq(priv);
-+      acx_unlock(priv, 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(priv);
-+      FLUSH_SCHEDULED_WORK();
-+      acx_sem_lock(priv);
-+
-+      /* 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(priv, flags);
-+      acx_stop_queue(dev, "during close");
-+      acx_set_status(priv, ACX_STATUS_0_STOPPED);
-+      acx_unlock(priv, 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(&priv->mgmt_timer);
-+
-+      FN_EXIT0;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_e_open
-+*
-+* WLAN device open method.  Called from p80211netdev when kernel
-+* device open (start) method is called in response to the
-+* SIOCSIFFLAGS ioctl changing the flags bit IFF_UP
-+* from clear to set.
-+*
-+* Returns:
-+*     0       success
-+*     >0      f/w reported error
-+*     <0      driver reported error
-+*
-+* Call context:
-+*     process thread
-+----------------------------------------------------------------*/
-+static int
-+acx_e_open(netdevice_t *dev)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+      int result = OK;
-+
-+      FN_ENTER;
-+
-+      acxlog(L_INIT, "module count++\n");
-+      WLAN_MOD_INC_USE_COUNT;
-+
-+      acx_sem_lock(priv);
-+
-+      acx_init_task_scheduler(priv);
-+
-+      /* request shared IRQ handler */
-+      if (request_irq(dev->irq, acx_i_interrupt, SA_SHIRQ, dev->name, dev)) {
-+              printk("%s: request_irq FAILED\n", dev->name);
-+              result = -EAGAIN;
-+              goto done;
-+      }
-+      acxlog(L_DEBUG|L_IRQ, "request_irq %d successful\n", dev->irq);
-+
-+      /* ifup device */
-+      acx_s_up(dev);
-+
-+      /* 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(priv);
-+
-+      FN_EXIT1(result);
-+      return result;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_e_close
-+*
-+* WLAN device close method.  Called from network core when kernel
-+* device close method is called in response to the
-+* SIOCSIIFFLAGS ioctl changing the flags bit IFF_UP
-+* from set to clear.
-+* (i.e. called for "ifconfig DEV down")
-+*
-+* Returns:
-+*     0       success
-+*     >0      f/w reported error
-+*     <0      driver reported error
-+*
-+* Call context:
-+*     process thread
-+----------------------------------------------------------------*/
-+static int
-+acx_e_close(netdevice_t *dev)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+
-+      FN_ENTER;
-+
-+      acx_sem_lock(priv);
-+
-+      /* ifdown device */
-+      CLEAR_BIT(priv->dev_state_mask, ACX_STATE_IFACE_UP);
-+      if (netif_device_present(dev)) {
-+              acx_s_down(dev);
-+      }
-+
-+      /* disable all IRQs, release shared IRQ handler */
-+      acx_write_reg16(priv, IO_ACX_IRQ_MASK, 0xffff);
-+      acx_write_reg16(priv, IO_ACX_FEMR, 0x0);
-+      free_irq(dev->irq, dev);
-+
-+      /* 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.
-+       */
-+      acxlog(L_INIT, "module count--\n");
-+      WLAN_MOD_DEC_USE_COUNT;
-+
-+      acx_sem_unlock(priv);
-+
-+      acxlog(L_INIT, "closed device\n");
-+      FN_EXIT0;
-+      return OK;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_i_tx_timeout
-+*
-+* Called from network core. Must not sleep!
-+*----------------------------------------------------------------*/
-+static void
-+acx_i_tx_timeout(netdevice_t *dev)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+      unsigned long flags;
-+      unsigned int tx_num_cleaned;
-+
-+      FN_ENTER;
-+
-+      acx_lock(priv, flags);
-+
-+      /* clean processed tx descs, they may have been completely full */
-+      tx_num_cleaned = acx_l_clean_tx_desc(priv);
-+
-+      /* 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 ((priv->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", dev->name);
-+              acx_l_clean_tx_desc_emergency(priv);
-+      }
-+
-+      if (acx_queue_stopped(dev) && (ACX_STATUS_4_ASSOCIATED == priv->status))
-+              acx_wake_queue(dev, "after tx timeout");
-+
-+      /* stall may have happened due to radio drift, so recalib radio */
-+      acx_schedule_after_interrupt_task(priv, ACX_AFTER_IRQ_CMD_RADIO_RECALIB);
-+
-+      /* do unimportant work last */
-+      printk("%s: tx timeout!\n", dev->name);
-+      priv->stats.tx_errors++;
-+
-+      acx_unlock(priv, flags);
-+
-+      FN_EXIT0;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_e_get_stats
-+*----------------------------------------------------------------*/
-+static struct net_device_stats*
-+acx_e_get_stats(netdevice_t *dev)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+      return &priv->stats;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_e_get_wireless_stats
-+*----------------------------------------------------------------*/
-+static struct iw_statistics*
-+acx_e_get_wireless_stats(netdevice_t *dev)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+      return &priv->wstats;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_i_set_multicast_list
-+* FIXME: most likely needs refinement
-+*----------------------------------------------------------------*/
-+static void
-+acx_i_set_multicast_list(netdevice_t *dev)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+      unsigned long flags;
-+
-+      FN_ENTER;
-+
-+      acx_lock(priv, flags);
-+
-+      /* firmwares don't have allmulti capability,
-+       * so just use promiscuous mode instead in this case. */
-+      if (dev->flags & (IFF_PROMISC|IFF_ALLMULTI)) {
-+              SET_BIT(priv->rx_config_1, RX_CFG1_RCV_PROMISCUOUS);
-+              CLEAR_BIT(priv->rx_config_1, RX_CFG1_FILTER_ALL_MULTI);
-+              SET_BIT(priv->set_mask, SET_RXCONFIG);
-+              /* let kernel know in case *we* needed to set promiscuous */
-+              dev->flags |= (IFF_PROMISC|IFF_ALLMULTI);
-+      } else {
-+              CLEAR_BIT(priv->rx_config_1, RX_CFG1_RCV_PROMISCUOUS);
-+              SET_BIT(priv->rx_config_1, RX_CFG1_FILTER_ALL_MULTI);
-+              SET_BIT(priv->set_mask, SET_RXCONFIG);
-+              dev->flags &= ~(IFF_PROMISC|IFF_ALLMULTI);
-+      }
-+
-+      /* cannot update card settings directly here, atomic context */
-+      acx_schedule_after_interrupt_task(priv, ACX_AFTER_IRQ_UPDATE_CARD_CFG);
-+
-+      acx_unlock(priv, flags);
-+
-+      FN_EXIT0;
-+}
-+
-+static void
-+acx_l_update_link_quality_led(wlandevice_t *priv)
-+{
-+      int qual;
-+
-+      qual = acx_signal_determine_quality(priv->wstats.qual.level, priv->wstats.qual.noise);
-+      if (qual > priv->brange_max_quality)
-+              qual = priv->brange_max_quality;
-+
-+      if (time_after(jiffies, priv->brange_time_last_state_change +
-+                              (HZ/2 - HZ/2 * (unsigned long) qual/priv->brange_max_quality ) )) {
-+              acx_l_power_led(priv, (priv->brange_last_state == 0));
-+              priv->brange_last_state ^= 1; /* toggle */
-+              priv->brange_time_last_state_change = jiffies;
-+      }
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_l_enable_irq
-+*----------------------------------------------------------------*/
-+static void
-+acx_l_enable_irq(wlandevice_t *priv)
-+{
-+      FN_ENTER;
-+      acx_write_reg16(priv, IO_ACX_IRQ_MASK, priv->irq_mask);
-+      acx_write_reg16(priv, IO_ACX_FEMR, 0x8000);
-+      priv->irqs_active = 1;
-+      FN_EXIT0;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_l_disable_irq
-+*----------------------------------------------------------------*/
-+static void
-+acx_l_disable_irq(wlandevice_t *priv)
-+{
-+      FN_ENTER;
-+      acx_write_reg16(priv, IO_ACX_IRQ_MASK, priv->irq_mask_off);
-+      acx_write_reg16(priv, IO_ACX_FEMR, 0x0);
-+      priv->irqs_active = 0;
-+      FN_EXIT0;
-+}
-+
-+/* 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
-+
-+static void
-+acx_l_handle_info_irq(wlandevice_t *priv)
-+{
-+#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
-+      acx_read_info_status(priv);
-+      acxlog(L_IRQ, "got Info IRQ: status 0x%04X type 0x%04X: %s\n",
-+              priv->info_status, priv->info_type,
-+              info_type_msg[(priv->info_type >= VEC_SIZE(info_type_msg)) ?
-+                              0 : priv->info_type]
-+      );
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_i_interrupt
-+*
-+* IRQ handler (atomic context, must not sleep, blah, blah)
-+*----------------------------------------------------------------*/
-+static void
-+acx_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) {
-+              acxlog(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");
-+      }
-+              /* 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 irqreturn_t
-+acx_i_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+      wlandevice_t *priv;
-+      unsigned long flags;
-+      unsigned int irqcount = MAX_IRQLOOPS_PER_JIFFY;
-+      u16 irqtype, unmasked;
-+
-+      priv = (wlandevice_t *) (((netdevice_t *) dev_id)->priv);
-+
-+      /* LOCKING: can just spin_lock() since IRQs are disabled anyway.
-+       * I am paranoid */
-+      acx_lock(priv, flags);
-+
-+      unmasked = acx_read_reg16(priv, IO_ACX_IRQ_STATUS_CLEAR);
-+      if (unlikely(0xffff == unmasked)) {
-+              /* 0xffff value hints at missing hardware,
-+               * so don't do anything.
-+               * FIXME: that's not very clean - maybe we are able to
-+               * establish a flag which definitely tells us that some
-+               * hardware is absent and which we could check here?
-+               * Hmm, but other drivers do the very same thing... */
-+              acxlog(L_IRQ, "IRQ type:FFFF - device removed? IRQ_NONE\n");
-+              goto none;
-+      }
-+
-+      /* We will check only "interesting" IRQ types */
-+      irqtype = unmasked & ~priv->irq_mask;
-+      if (!irqtype) {
-+              /* We are on a shared IRQ line and it wasn't our IRQ */
-+              acxlog(L_IRQ, "IRQ type:%04X, mask:%04X - all are masked, IRQ_NONE\n",
-+                      unmasked, priv->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 != priv->irq_last_jiffies) {
-+      priv->irq_loops_this_jiffy = 0;
-+      priv->irq_last_jiffies = jiffies;
-+}
-+
-+/* safety condition; we'll normally abort loop below
-+ * in case no IRQ type occurred */
-+while (--irqcount) {
-+#endif
-+      /* ACK all IRQs asap */
-+      acx_write_reg16(priv, IO_ACX_IRQ_ACK, 0xffff);
-+
-+      acxlog(L_IRQ, "IRQ type:%04X, mask:%04X, type & ~mask:%04X\n",
-+                              unmasked, priv->irq_mask, irqtype);
-+
-+      /* Handle most important IRQ types first */
-+      if (irqtype & HOST_INT_RX_COMPLETE) {
-+              acxlog(L_IRQ, "got Rx_Complete IRQ\n");
-+              acx_l_process_rx_desc(priv);
-+      }
-+      if (irqtype & HOST_INT_TX_COMPLETE) {
-+              acxlog(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
-+               * acx_l_clean_tx_desc() at a time when we won't wakeup
-+               * the net queue in there for some reason...) */
-+              if (priv->tx_free <= TX_START_CLEAN) {
-+#if TX_CLEANUP_IN_SOFTIRQ
-+                      acx_schedule_after_interrupt_task(priv, ACX_AFTER_IRQ_TX_CLEANUP);
-+#else
-+                      acx_l_clean_tx_desc(priv);
-+#endif
-+              }
-+      }
-+
-+      /* Less frequent ones */
-+      if (irqtype & (0
-+              | HOST_INT_CMD_COMPLETE
-+              | HOST_INT_INFO
-+              | HOST_INT_SCAN_COMPLETE
-+      )) {
-+              if (irqtype & HOST_INT_CMD_COMPLETE) {
-+                      acxlog(L_IRQ, "got Command_Complete IRQ\n");
-+                      /* save the state for the running issue_cmd() */
-+                      SET_BIT(priv->irq_status, HOST_INT_CMD_COMPLETE);
-+              }
-+              if (irqtype & HOST_INT_INFO) {
-+                      acx_l_handle_info_irq(priv);
-+              }
-+              if (irqtype & HOST_INT_SCAN_COMPLETE) {
-+                      acxlog(L_IRQ, "got Scan_Complete IRQ\n");
-+                      /* need to do that in process context */
-+                      acx_schedule_after_interrupt_task(priv, ACX_AFTER_IRQ_COMPLETE_SCAN);
-+                      /* remember that fw is not scanning anymore */
-+                      SET_BIT(priv->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
-+      )) {
-+              acx_log_unusual_irq(irqtype);
-+      }
-+
-+#if IRQ_ITERATE
-+      unmasked = acx_read_reg16(priv, IO_ACX_IRQ_STATUS_CLEAR);
-+      irqtype = unmasked & ~priv->irq_mask;
-+      /* Bail out if no new IRQ bits or if all are masked out */
-+      if (!irqtype)
-+              break;
-+
-+      if (unlikely(++priv->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 */
-+              acx_write_reg16(priv, IO_ACX_IRQ_MASK, 0xffff);
-+              /* This will short-circuit all future attempts to handle IRQ.
-+               * We cant do much more... */
-+              priv->irq_mask = 0;
-+              break;
-+      }
-+}
-+#endif
-+      /* Routine to perform blink with range */
-+      if (unlikely(priv->led_power == 2))
-+              acx_l_update_link_quality_led(priv);
-+
-+/* handled: */
-+      /* acx_write_flush(priv); - not needed, last op was read anyway */
-+      acx_unlock(priv, flags);
-+      FN_EXIT0;
-+      return IRQ_HANDLED;
-+
-+none:
-+      acx_unlock(priv, flags);
-+      return IRQ_NONE;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_l_power_led
-+*----------------------------------------------------------------*/
-+void
-+acx_l_power_led(wlandevice_t *priv, int enable)
-+{
-+      u16 gpio_pled = IS_ACX111(priv) ? 0x0040 : 0x0800;
-+
-+      /* A hack. Not moving message rate limiting to priv->xxx
-+       * (it's only a debug message after all) */
-+      static int rate_limit = 0;
-+
-+      if (rate_limit++ < 3)
-+              acxlog(L_IOCTL, "Please report in case toggling the power "
-+                              "LED doesn't work for your card!\n");
-+      if (enable)
-+              acx_write_reg16(priv, IO_ACX_GPIO_OUT,
-+                      acx_read_reg16(priv, IO_ACX_GPIO_OUT) & ~gpio_pled);
-+      else
-+              acx_write_reg16(priv, IO_ACX_GPIO_OUT,
-+                      acx_read_reg16(priv, IO_ACX_GPIO_OUT) | gpio_pled);
-+}
-+
-+
-+/***********************************************************************
-+** Ioctls
-+*/
-+
-+/***********************************************************************
-+*/
-+int
-+acx111pci_ioctl_info(
-+      struct net_device *dev,
-+      struct iw_request_info *info,
-+      struct iw_param *vwrq,
-+      char *extra)
-+{
-+#if ACX_DEBUG
-+      wlandevice_t *priv = netdev_priv(dev);
-+      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(priv);
-+
-+      if (!IS_ACX111(priv)) {
-+              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(priv, &memconf, ACX1xx_IE_QUEUE_CONFIG);
-+
-+      /* get Acx111 Queue Configuration */
-+      memset(&queueconf, 0, sizeof(queueconf));
-+      acx_s_interrogate(priv, &queueconf, ACX1xx_IE_MEMORY_CONFIG_OPTIONS);
-+
-+      /* get Acx111 Memory Map */
-+      memset(memmap, 0, sizeof(memmap));
-+      acx_s_interrogate(priv, &memmap, ACX1xx_IE_MEMORY_MAP);
-+
-+      /* get Acx111 Rx Config */
-+      memset(rxconfig, 0, sizeof(rxconfig));
-+      acx_s_interrogate(priv, &rxconfig, ACX1xx_IE_RXCONFIG);
-+
-+      /* get Acx111 fcs error count */
-+      memset(fcserror, 0, sizeof(fcserror));
-+      acx_s_interrogate(priv, &fcserror, ACX1xx_IE_FCS_ERROR_COUNT);
-+
-+      /* get Acx111 rate fallback */
-+      memset(ratefallback, 0, sizeof(ratefallback));
-+      acx_s_interrogate(priv, &ratefallback, ACX1xx_IE_RATE_FALLBACK);
-+
-+      /* force occurrence of a beacon interrupt */
-+      /* TODO: comment why is this necessary */
-+      acx_write_reg16(priv, 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]),
-+              priv->iobase,
-+              priv->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(priv, flags);
-+
-+      /* dump acx111 internal rx descriptor ring buffer */
-+      rxdesc = priv->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 = priv->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 = priv->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 = move_txdesc(priv, txdesc, 1);
-+      }
-+
-+      /* dump host tx descriptor ring buffer */
-+
-+      txhostdesc = priv->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++;
-+      }
-+
-+      /* acx_write_reg16(priv, 0xb4, 0x4); */
-+
-+      acx_unlock(priv, flags);
-+end_ok:
-+
-+      acx_sem_unlock(priv);
-+#endif /* ACX_DEBUG */
-+      return OK;
-+}
-+
-+
-+/***********************************************************************
-+*/
-+int
-+acx100pci_ioctl_set_phy_amp_bias(
-+      struct net_device *dev,
-+      struct iw_request_info *info,
-+      struct iw_param *vwrq,
-+      char *extra)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+      unsigned long flags;
-+      u16 gpio_old;
-+
-+      if (!IS_ACX100(priv)) {
-+              /* 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(priv);
-+
-+      /* Need to lock accesses to [IO_ACX_GPIO_OUT]:
-+       * IRQ handler uses it to update LED */
-+      acx_lock(priv, flags);
-+      gpio_old = acx_read_reg16(priv, IO_ACX_GPIO_OUT);
-+      acx_write_reg16(priv, IO_ACX_GPIO_OUT, (gpio_old & 0xf8ff) | ((u16)*extra << 8));
-+      acx_unlock(priv, flags);
-+
-+      acxlog(L_DEBUG, "gpio_old: 0x%04X\n", gpio_old);
-+      printk("%s: PHY power amplifier bias: old:%d, new:%d\n",
-+              dev->name,
-+              (gpio_old & 0x0700) >> 8, (unsigned char)*extra);
-+
-+      acx_sem_unlock(priv);
-+
-+      return OK;
-+}
-+
-+
-+/***************************************************************
-+** acxpci_l_alloc_tx
-+** Actually returns a txdesc_t* ptr
-+*/
-+tx_t*
-+acxpci_l_alloc_tx(wlandevice_t* priv)
-+{
-+      struct txdesc *txdesc;
-+      u8 ctl8;
-+
-+      FN_ENTER;
-+
-+      txdesc = get_txdesc(priv, priv->tx_head);
-+      ctl8 = txdesc->Ctl_8;
-+      if (unlikely(DESC_CTL_HOSTOWN != (ctl8 & DESC_CTL_DONE))) {
-+              /* whoops, descr at current index is not free, so probably
-+               * ring buffer already full */
-+              /* FIXME: this causes a deadlock situation (endless
-+               * loop) in case the current descriptor remains busy,
-+               * so handle it a bit better in the future!! */
-+              printk("acx: BUG: tx_head->Ctl8=0x%02X, (0x%02X & "
-+                      "0x"DESC_CTL_DONE_STR") != 0x"DESC_CTL_HOSTOWN_STR
-+                      ": failed to find free tx descr\n",
-+                      ctl8, ctl8);
-+              txdesc = NULL;
-+              goto end;
-+      }
-+
-+      priv->tx_free--;
-+      acxlog(L_BUFT, "tx: got desc %u, %u remain\n",
-+                      priv->tx_head, priv->tx_free);
-+
-+/*
-+ * This comment is probably not entirely correct, needs further discussion
-+ * (restored commented-out code below to fix Tx ring buffer overflow,
-+ * since it's much better to have a slightly less efficiently used ring
-+ * buffer rather than one which easily overflows):
-+ *
-+ * This doesn't do anything other than limit our maximum number of
-+ * buffers used at a single time (we might as well just declare
-+ * TX_STOP_QUEUE less descriptors when we open up.) We should just let it
-+ * slide here, and back off TX_STOP_QUEUE in acx_l_clean_tx_desc, when given the
-+ * opportunity to let the queue start back up.
-+ */
-+      if (priv->tx_free < TX_STOP_QUEUE) {
-+              acxlog(L_BUF, "stop queue (%u tx desc left)\n",
-+                              priv->tx_free);
-+              acx_stop_queue(priv->netdev, NULL);
-+      }
-+
-+      /* returning current descriptor, so advance to next free one */
-+      priv->tx_head = (priv->tx_head + 1) % TX_CNT;
-+end:
-+      FN_EXIT0;
-+
-+      return (tx_t*)txdesc;
-+}
-+
-+
-+/***********************************************************************
-+*/
-+void*
-+acxpci_l_get_txbuf(wlandevice_t *priv, tx_t* tx_opaque)
-+{
-+      return acx_get_txhostdesc(priv, (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).
-+*/
-+void
-+acxpci_l_tx_data(wlandevice_t *priv, tx_t* tx_opaque, int len)
-+{
-+      txdesc_t *txdesc = (txdesc_t*)tx_opaque;
-+      txhostdesc_t *hostdesc1, *hostdesc2;
-+      client_t *clt;
-+      u8 Ctl_8, Ctl2_8;
-+
-+      FN_ENTER;
-+
-+      /* fw doesn't tx such packets anyhow */
-+      if (len < WLAN_HDR_A3_LEN)
-+              goto end;
-+
-+      hostdesc1 = acx_get_txhostdesc(priv, txdesc);
-+      hostdesc2 = hostdesc1 + 1;
-+
-+      /* 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 = txdesc->Ctl2_8;
-+
-+      /* 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...
-+       * FIXME: what about Ctl2? Equally problematic? */
-+
-+      /* let chip do RTS/CTS handshaking before sending
-+       * in case packet size exceeds threshold */
-+      if (len > priv->rts_threshold)
-+              SET_BIT(Ctl2_8, DESC_CTL2_RTS);
-+      else
-+              CLEAR_BIT(Ctl2_8, DESC_CTL2_RTS);
-+
-+#ifdef DEBUG_WEP
-+      if (priv->wep_enabled)
-+              SET_BIT(Ctl2_8, DESC_CTL2_WEP);
-+      else
-+              CLEAR_BIT(Ctl2_8, DESC_CTL2_WEP);
-+#endif
-+
-+      switch (priv->mode) {
-+      case ACX_MODE_0_ADHOC:
-+      case ACX_MODE_3_AP:
-+              clt = acx_l_sta_list_get(priv, ((wlan_hdr_t*)hostdesc1->data)->a1);
-+              break;
-+      case ACX_MODE_2_STA:
-+              clt = priv->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;
-+      }
-+
-+      if (unlikely(clt && !clt->rate_cur)) {
-+              printk("acx: driver bug! bad ratemask\n");
-+              goto end;
-+      }
-+
-+      /* used in tx cleanup routine for auto rate and accounting: */
-+      acx_put_txc(priv, txdesc, clt);
-+
-+      txdesc->total_length = cpu_to_le16(len);
-+      hostdesc2->length = cpu_to_le16(len - WLAN_HDR_A3_LEN);
-+      if (IS_ACX111(priv)) {
-+              u16 rate_cur = clt ? clt->rate_cur : priv->rate_bcast;
-+              /* 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 : priv->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);
-+              hostdesc1->length = cpu_to_le16(WLAN_HDR_A3_LEN);
-+      }
-+      /* don't need to clean ack/rts statistics here, already
-+       * done on descr cleanup */
-+
-+      /* clears Ctl DESC_CTL_HOSTOWN bit, thus telling that the descriptors
-+       * are now owned by the acx100; do this as LAST operation */
-+      CLEAR_BIT(Ctl_8, DESC_CTL_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); */
-+//TODO: should it be a mmiowb() instead? we are protecting against race with write[bwl]()
-+      /* flush writes before we tell the adapter that it's its turn now */
-+      wmb(); 
-+      acx_write_reg16(priv, IO_ACX_INT_TRIG, INT_TRIG_TXPRC);
-+      acx_write_flush(priv);
-+
-+      /* 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(priv))
-+                      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)" : "",
-+                              priv->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)" : "",
-+                              priv->status);
-+
-+              if (acx_debug & L_DATA) {
-+                      printk("tx: 802.11 [%d]: ", len);
-+                      acx_dump_bytes(hostdesc1->data, len);
-+              }
-+      }
-+end:
-+      FN_EXIT0;
-+}
-+
-+
-+/***********************************************************************
-+*/
-+static void
-+acx_l_handle_tx_error(wlandevice_t *priv, 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";
-+              priv->wstats.discard.fragment++;
-+              break;
-+      case 0x02:
-+              err = "Tx aborted";
-+              priv->stats.tx_aborted_errors++;
-+              break;
-+      case 0x04:
-+              err = "Tx desc wrong parameters";
-+              priv->wstats.discard.misc++;
-+              break;
-+      case 0x08:
-+              err = "WEP key not found";
-+              priv->wstats.discard.misc++;
-+              break;
-+      case 0x10:
-+              err = "MSDU lifetime timeout? - try changing "
-+                              "'iwconfig retry lifetime XXX'";
-+              priv->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'";
-+              priv->wstats.discard.retries++;
-+              /* FIXME: set (GETSET_TX|GETSET_RX) here
-+               * (this seems to recalib radio on ACX100)
-+               * after some more jiffies passed??
-+               * But OTOH Tx error 0x20 also seems to occur on
-+               * overheating, so I'm not sure whether we
-+               * actually want that, 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.
-+               * ENABLE_TX|ENABLE_RX helps, so even do
-+               * DISABLE_TX and DISABLE_RX in order to perhaps
-+               * have more impact. */
-+              if (++priv->retry_errors_msg_ratelimit % 4 == 0) {
-+                      if (priv->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",
-+                                      priv->netdev->name);
-+                      if (priv->retry_errors_msg_ratelimit == 20)
-+                              printk("disabling above "
-+                                      "notification message\n");
-+
-+                      acx_schedule_after_interrupt_task(priv, ACX_AFTER_IRQ_CMD_RADIO_RECALIB);
-+              }
-+              break;
-+      case 0x40:
-+              err = "Tx buffer overflow";
-+              priv->stats.tx_fifo_errors++;
-+              break;
-+      case 0x80:
-+              err = "DMA error";
-+              priv->wstats.discard.misc++;
-+              break;
-+      }
-+      priv->stats.tx_errors++;
-+      if (priv->stats.tx_errors <= 20)
-+              printk("%s: tx error 0x%02X, buf %02u! (%s)\n",
-+                              priv->netdev->name, error, finger, err);
-+      else
-+              printk("%s: tx error 0x%02X, buf %02u!\n",
-+                              priv->netdev->name, error, finger);
-+}
-+
-+
-+/***********************************************************************
-+*/
-+/* 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_2;
-+      }
-+}
-+
-+
-+static void
-+acx_l_handle_txrate_auto(wlandevice_t *priv, struct client *txc,
-+                      unsigned int idx, u8 rate100, u16 rate111, u8 error)
-+{
-+      u16 sent_rate;
-+      u16 cur = txc->rate_cur;
-+      int slower_rate_was_used;
-+
-+      /* FIXME: need to implement some kind of rate success memory
-+       * which stores the success percentage per rate, to be taken
-+       * into account when considering allowing a new rate, since it
-+       * doesn't really help to stupidly count fallback/stepup,
-+       * since one invalid rate will spoil the party anyway
-+       * (such as 22M in case of 11M-only peers) */
-+
-+      /* 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 */
-+
-+      /* do some preparations, i.e. calculate the one rate that was
-+       * used to send this packet */
-+      if (IS_ACX111(priv)) {
-+              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 */
-+      acxlog(L_DEBUG, "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, priv->fallback_threshold,
-+              txc->stepup_count, priv->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 here only, in order to have the 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 & 0x30)) {
-+              txc->stepup_count = 0;
-+              if (++txc->fallback_count <= priv->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! */
-+                      acxlog(L_XFER, "tx: falling back to ratemask %04X\n", cur);
-+                      txc->rate_cur = cur;
-+                      txc->ignore_count = TX_CNT - priv->tx_free;
-+              }
-+      } else if (!slower_rate_was_used) {
-+              txc->fallback_count = 0;
-+              if (++txc->stepup_count <= priv->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);
-+              acxlog(L_XFER, "tx: stepping up to ratemask %04X\n", cur);
-+              txc->rate_cur = cur;
-+              /* FIXME: totally bogus - we could be sending to many peers at once... */
-+              txc->ignore_count = TX_CNT - priv->tx_free;
-+      }
-+
-+      /* calculate acx100 style rate byte if needed */
-+      if (IS_ACX100(priv)) {
-+              txc->rate_100 = bitpos2rate100[highest_bit(cur)];
-+      }
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_l_log_txbuffer
-+*----------------------------------------------------------------*/
-+#if !ACX_DEBUG
-+static inline void acx_l_log_txbuffer(const wlandevice_t *priv) {}
-+#else
-+static void
-+acx_l_log_txbuffer(wlandevice_t *priv)
-+{
-+      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 = priv->txdesc_start;
-+      if (!txdesc) return;
-+      for (i = 0; i < TX_CNT; i++) {
-+              if ((txdesc->Ctl_8 & DESC_CTL_DONE) == DESC_CTL_DONE)
-+                      printk("tx: buf %d done\n", i);
-+              txdesc = move_txdesc(priv, txdesc, 1);
-+      }
-+}
-+#endif
-+
-+
-+/*----------------------------------------------------------------
-+* acx_l_clean_tx_desc
-+*
-+* 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.
-+* Oops, now we have our own index, so everytime we get called we know
-+* where the next packet to be cleaned is.
-+* Hmm, still need to loop through the whole ring buffer now,
-+* since we lost sync for some reason when ping flooding or so...
-+* (somehow we don't get the IRQ for acx_l_clean_tx_desc any more when
-+* too many packets are being sent!)
-+* FIXME: currently we only process one packet, but this gets out of
-+* sync for some reason when ping flooding, so we need to loop,
-+* but the previous smart loop implementation causes the ping latency
-+* to rise dramatically (~3000 ms), at least on CardBus PheeNet WL-0022.
-+* Dunno what to do :-\
-+*----------------------------------------------------------------*/
-+unsigned int
-+acx_l_clean_tx_desc(wlandevice_t *priv)
-+{
-+      txdesc_t *txdesc;
-+      struct client *txc;
-+      int finger;
-+      int num_cleaned;
-+      int to_process;
-+      u16 r111;
-+      u8 error, ack_failures, rts_failures, rts_ok, r100;
-+
-+      FN_ENTER;
-+
-+      if (unlikely(acx_debug & L_DEBUG))
-+              acx_l_log_txbuffer(priv);
-+
-+      acxlog(L_BUFT, "tx: cleaning up bufs from %u\n", priv->tx_tail);
-+
-+      finger = priv->tx_tail;
-+      num_cleaned = 0;
-+      to_process = TX_CNT;
-+      do {
-+              txdesc = get_txdesc(priv, finger);
-+
-+              /* abort if txdesc is not marked as "Tx finished" and "owned" */
-+              if ((txdesc->Ctl_8 & DESC_CTL_DONE) != DESC_CTL_DONE) {
-+                      /* we do need to have at least one cleaned,
-+                       * otherwise we wouldn't get called in the first place
-+                       */
-+                      if (num_cleaned)
-+                              break;
-+              }
-+
-+              /* remember descr 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 = txdesc->u.r2.rate111;
-+
-+#if WIRELESS_EXT > 13 /* wireless_send_event() and IWEVTXDROP are WE13 */
-+              /* 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 = acx_get_txhostdesc(priv, txdesc);
-+                      hdr = (wlan_hdr_t *)hostdesc->data;
-+                      MAC_COPY(wrqu.addr.sa_data, hdr->a1);
-+                      wireless_send_event(priv->netdev, IWEVTXDROP, &wrqu, NULL);
-+              }
-+#endif
-+              /* ...and free the descr */
-+              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:
-+               * if _OWN is set at the beginning instead, our own get_tx
-+               * might choose a Tx desc that isn't fully cleared
-+               * (in case of bad locking). */
-+              txdesc->Ctl_8 = DESC_CTL_HOSTOWN;
-+              priv->tx_free++;
-+              num_cleaned++;
-+
-+              if ((priv->tx_free >= TX_START_QUEUE)
-+              && (priv->status == ACX_STATUS_4_ASSOCIATED)
-+              && (acx_queue_stopped(priv->netdev))
-+              ) {
-+                      acxlog(L_BUF, "tx: wake queue (avail. Tx desc %u)\n",
-+                                      priv->tx_free);
-+                      acx_wake_queue(priv->netdev, NULL);
-+              }
-+
-+              /* do error checking, rate handling and logging
-+               * AFTER having done the work, it's faster */
-+
-+              /* do rate handling */
-+              txc = acx_get_txc(priv, txdesc);
-+              if (txc && priv->rate_auto) {
-+                      acx_l_handle_txrate_auto(priv, txc, finger, r100, r111, error);
-+              }
-+
-+              if (unlikely(error))
-+                      acx_l_handle_tx_error(priv, error, finger);
-+
-+              if (IS_ACX111(priv))
-+                      acxlog(L_BUFT, "tx: cleaned %u: !ACK=%u !RTS=%u RTS=%u r111=%04X\n",
-+                              finger, ack_failures, rts_failures, rts_ok, r111);
-+              else
-+                      acxlog(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;
-+      } while (--to_process);
-+
-+      /* remember last position */
-+      priv->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
-+acx_l_clean_tx_desc_emergency(wlandevice_t *priv)
-+{
-+      txdesc_t *txdesc;
-+      unsigned int i;
-+
-+      FN_ENTER;
-+
-+      for (i = 0; i < TX_CNT; i++) {
-+              txdesc = get_txdesc(priv, i);
-+
-+              /* free it */
-+              txdesc->ack_failures = 0;
-+              txdesc->rts_failures = 0;
-+              txdesc->rts_ok = 0;
-+              txdesc->error = 0;
-+              txdesc->Ctl_8 = DESC_CTL_HOSTOWN;
-+      }
-+
-+      priv->tx_free = TX_CNT;
-+
-+      FN_EXIT0;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_l_log_rxbuffer
-+*
-+* Called from IRQ context only
-+*----------------------------------------------------------------*/
-+#if !ACX_DEBUG
-+static inline void acx_l_log_rxbuffer(const wlandevice_t *priv) {}
-+#else
-+static void
-+acx_l_log_rxbuffer(const wlandevice_t *priv)
-+{
-+      const struct rxhostdesc *rxhostdesc;
-+      int i;
-+
-+      /* no FN_ENTER here, we don't want that */
-+
-+      rxhostdesc = priv->rxhostdesc_start;
-+      if (!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
-+
-+
-+/***************************************************************
-+** acx_l_process_rx_desc
-+**
-+** Called directly and only from the IRQ handler
-+*/
-+void
-+acx_l_process_rx_desc(wlandevice_t *priv)
-+{
-+      rxhostdesc_t *hostdesc;
-+      /* unsigned int curr_idx; */
-+      unsigned int count = 0;
-+
-+      FN_ENTER;
-+
-+      if (unlikely(acx_debug & L_BUFR)) {
-+              acx_l_log_rxbuffer(priv);
-+      }
-+
-+      /* 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. */
-+      while (1) {
-+              /* curr_idx = priv->rx_tail; */
-+              hostdesc = &priv->rxhostdesc_start[priv->rx_tail];
-+              priv->rx_tail = (priv->rx_tail + 1) % RX_CNT;
-+              if ((hostdesc->Ctl_16 & cpu_to_le16(DESC_CTL_HOSTOWN))
-+               && (hostdesc->Status & cpu_to_le32(DESC_STATUS_FULL))) {
-+                      /* found it! */
-+                      break;
-+              }
-+              count++;
-+              if (unlikely(count > RX_CNT)) {
-+                      /* hmm, no luck: all descriptors empty, bail out */
-+                      goto end;
-+              }
-+      }
-+
-+      /* now process descriptors, starting with the first we figured out */
-+      while (1) {
-+              acxlog(L_BUFR, "rx: tail=%u Ctl_16=%04X Status=%08X\n",
-+                      priv->rx_tail, hostdesc->Ctl_16, hostdesc->Status);
-+
-+              acx_l_process_rxbuf(priv, 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 */
-+              /* curr_idx = priv->rx_tail; */
-+              hostdesc = &priv->rxhostdesc_start[priv->rx_tail];
-+
-+              /* if next descriptor is empty, then bail out */
-+              /* FIXME: is this check really entirely correct?? */
-+              /*
-+//FIXME: inconsistent with check in prev while() loop
-+              if (!(hostdesc->Ctl & cpu_to_le16(DESC_CTL_HOSTOWN))
-+               && !(hostdesc->Status & cpu_to_le32(DESC_STATUS_FULL))) */
-+              if (!(hostdesc->Status & cpu_to_le32(DESC_STATUS_FULL)))
-+                      break;
-+
-+              priv->rx_tail = (priv->rx_tail + 1) % RX_CNT;
-+      }
-+end:
-+      FN_EXIT0;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_s_create_tx_host_desc_queue
-+*----------------------------------------------------------------*/
-+static inline void*
-+acx_alloc_coherent(struct pci_dev *hwdev, size_t size,
-+                      dma_addr_t *dma_handle, int flag)
-+{
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 53)
-+      return dma_alloc_coherent(hwdev == NULL ? NULL : &hwdev->dev,
-+                      size, dma_handle, flag);
-+#else
-+#warning Using old PCI-specific DMA allocation, may fail with out-of-mem!
-+#warning Upgrade kernel if it does...
-+      return pci_alloc_consistent(hwdev, size, dma_handle);
-+#endif
-+}
-+
-+static void*
-+allocate(wlandevice_t *priv, size_t size, dma_addr_t *phy, const char *msg)
-+{
-+      void *ptr = acx_alloc_coherent(priv->pdev, size, phy, GFP_KERNEL);
-+      if (ptr) {
-+              acxlog(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
-+acx_s_create_tx_host_desc_queue(wlandevice_t *priv)
-+{
-+      txhostdesc_t *hostdesc;
-+      u8 *txbuf;
-+      dma_addr_t hostdesc_phy;
-+      dma_addr_t txbuf_phy;
-+      int i;
-+
-+      FN_ENTER;
-+
-+      /* allocate TX buffer */
-+      priv->txbuf_area_size = TX_CNT * WLAN_A4FR_MAXLEN_WEP_FCS;
-+      priv->txbuf_start = allocate(priv, priv->txbuf_area_size,
-+                      &priv->txbuf_startphy, "txbuf_start");
-+      if (!priv->txbuf_start)
-+              goto fail;
-+
-+      /* allocate the TX host descriptor queue pool */
-+      priv->txhostdesc_area_size = TX_CNT * 2*sizeof(txhostdesc_t);
-+      priv->txhostdesc_start = allocate(priv, priv->txhostdesc_area_size,
-+                      &priv->txhostdesc_startphy, "txhostdesc_start");
-+      if (!priv->txhostdesc_start)
-+              goto fail;
-+      /* check for proper alignment of TX host descriptor pool */
-+      if ((long) priv->txhostdesc_start & 3) {
-+              printk("acx: driver bug: dma alloc returns unaligned address\n");
-+              goto fail;
-+      }
-+
-+/* Each tx frame buffer is accessed by hardware via
-+** txdesc -> txhostdesc(s) -> framebuffer(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 hostdesc.length = 3 (or larger)
-+** Storing NULL into hostdesc.desc_phy_next
-+** doesn't seem to help.
-+*/
-+/* It is not known whether we need to have 'extra' second
-+** txhostdescs for acx100. Maybe it is acx111-only bug.
-+*/
-+      hostdesc = priv->txhostdesc_start;
-+      hostdesc_phy = priv->txhostdesc_startphy;
-+      txbuf = priv->txbuf_start;
-+      txbuf_phy = priv->txbuf_startphy;
-+
-+#if 0
-+/* Works for xterasys xn2522g, does not for WG311v2 !!? */
-+      for (i = 0; i < TX_CNT*2; i++) {
-+              hostdesc_phy += sizeof(txhostdesc_t);
-+              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 = 3; /* bug workaround */
-+                      /* hostdesc->desc_phy_next = ... */
-+                      /* hostdesc->pNext = ... */
-+                      /* hostdesc->Status = ... */
-+                      /* below: non-hardware fields */
-+                      /* hostdesc->data = ... */
-+              }
-+              hostdesc++;
-+      }
-+#endif
-+      for (i = 0; i < TX_CNT*2; i++) {
-+              hostdesc_phy += sizeof(txhostdesc_t);
-+              if (!(i & 1)) {
-+                      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 = ... */
-+                      /* below: non-hardware fields */
-+                      hostdesc->data = txbuf;
-+
-+                      txbuf += WLAN_HDR_A3_LEN;
-+                      txbuf_phy += WLAN_HDR_A3_LEN;
-+              } else {
-+                      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 = ... */
-+                      /* below: non-hardware fields */
-+                      hostdesc->data = txbuf;
-+
-+                      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(priv->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;
-+}
-+
-+
-+/***************************************************************
-+** acx_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
-+acx_s_create_rx_host_desc_queue(wlandevice_t *priv)
-+{
-+      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 */
-+      priv->rxhostdesc_area_size = RX_CNT * sizeof(rxhostdesc_t);
-+      priv->rxhostdesc_start = allocate(priv, priv->rxhostdesc_area_size,
-+                      &priv->rxhostdesc_startphy, "rxhostdesc_start");
-+      if (!priv->rxhostdesc_start)
-+              goto fail;
-+      /* check for proper alignment of RX host descriptor pool */
-+      if ((long) priv->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 */
-+      priv->rxbuf_area_size = RX_CNT * RX_BUFFER_SIZE;
-+      priv->rxbuf_start = allocate(priv, priv->rxbuf_area_size,
-+                      &priv->rxbuf_startphy, "rxbuf_start");
-+      if (!priv->rxbuf_start)
-+              goto fail;
-+
-+      rxbuf = priv->rxbuf_start;
-+      rxbuf_phy = priv->rxbuf_startphy;
-+      hostdesc = priv->rxhostdesc_start;
-+      hostdesc_phy = priv->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(rxbuffer_t);
-+              hostdesc_phy += sizeof(rxhostdesc_t);
-+              hostdesc->desc_phy_next = cpu2acx(hostdesc_phy);
-+              hostdesc++;
-+      }
-+      hostdesc--;
-+      hostdesc->desc_phy_next = cpu2acx(priv->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;
-+}
-+
-+
-+/***************************************************************
-+** acx_s_create_hostdesc_queues
-+*/
-+int
-+acx_s_create_hostdesc_queues(wlandevice_t *priv)
-+{
-+      int result;
-+      result = acx_s_create_tx_host_desc_queue(priv);
-+      if (OK != result) return result;
-+      result = acx_s_create_rx_host_desc_queue(priv);
-+      return result;
-+}
-+
-+
-+/***************************************************************
-+** acx_create_tx_desc_queue
-+*/
-+static void
-+acx_create_tx_desc_queue(wlandevice_t *priv, u32 tx_queue_start)
-+{
-+      txdesc_t *txdesc;
-+      txhostdesc_t *hostdesc;
-+      dma_addr_t hostmemptr;
-+      u32 mem_offs;
-+      int i;
-+
-+      FN_ENTER;
-+
-+      priv->txdesc_size = sizeof(txdesc_t);
-+
-+      if (IS_ACX111(priv)) {
-+              /* the acx111 txdesc is 4 bytes larger */
-+              priv->txdesc_size = sizeof(txdesc_t) + 4;
-+      }
-+
-+      priv->txdesc_start = (txdesc_t *) (priv->iobase2 + tx_queue_start);
-+
-+      acxlog(L_DEBUG, "priv->iobase2=%p\n"
-+                      "tx_queue_start=%08X\n"
-+                      "priv->txdesc_start=%p\n",
-+                      priv->iobase2,
-+                      tx_queue_start,
-+                      priv->txdesc_start);
-+
-+      priv->tx_free = TX_CNT;
-+      /* done by memset: priv->tx_head = 0; */
-+      /* done by memset: priv->tx_tail = 0; */
-+      txdesc = priv->txdesc_start;
-+      mem_offs = tx_queue_start;
-+      hostmemptr = priv->txhostdesc_startphy;
-+      hostdesc = priv->txhostdesc_start;
-+
-+      if (IS_ACX111(priv)) {
-+              /* 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(txhostdesc_t);
-+                      txdesc = move_txdesc(priv, txdesc, 1);
-+              }
-+      } else {
-+              /* ACX100 Tx buffer needs to be initialized by us */
-+              /* clear whole send pool. sizeof is safe here (we are acx100) */
-+              memset(priv->txdesc_start, 0, TX_CNT * sizeof(txdesc_t));
-+
-+              /* loop over whole send pool */
-+              for (i = 0; i < TX_CNT; i++) {
-+                      acxlog(L_DEBUG, "configure card tx descriptor: 0x%p, "
-+                              "size: 0x%X\n", txdesc, priv->txdesc_size);
-+
-+                      /* pointer to hostdesc memory */
-+                      /* FIXME: type-incorrect assignment, might cause trouble
-+                       * in some cases */
-+                      txdesc->HostMemPtr = ptr2acx(hostmemptr);
-+                      /* initialise ctl */
-+                      txdesc->Ctl_8 = DESC_CTL_INIT;
-+                      txdesc->Ctl2_8 = 0;
-+                      /* point to next txdesc */
-+                      txdesc->pNextDesc = cpu2acx(mem_offs + priv->txdesc_size);
-+                      /* reserve two (hdr desc and payload desc) */
-+                      hostdesc += 2;
-+                      hostmemptr += 2 * sizeof(txhostdesc_t);
-+                      /* go to the next one */
-+                      mem_offs += priv->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;
-+}
-+
-+
-+/***************************************************************
-+** acx_create_rx_desc_queue
-+*/
-+static void
-+acx_create_rx_desc_queue(wlandevice_t *priv, u32 rx_queue_start)
-+{
-+      rxdesc_t *rxdesc;
-+      u32 mem_offs;
-+      int i;
-+
-+      FN_ENTER;
-+
-+      /* done by memset: priv->rx_tail = 0; */
-+
-+      /* ACX111 doesn't need any further config: preconfigures itself.
-+       * Simply print ring buffer for debugging */
-+      if (IS_ACX111(priv)) {
-+              /* rxdesc_start already set here */
-+
-+              priv->rxdesc_start = (rxdesc_t *) ((u8 *)priv->iobase2 + rx_queue_start);
-+
-+              rxdesc = priv->rxdesc_start;
-+              for (i = 0; i < RX_CNT; i++) {
-+                      acxlog(L_DEBUG, "rx descriptor %d @ 0x%p\n", i, rxdesc);
-+                      rxdesc = priv->rxdesc_start = (rxdesc_t *)
-+                              (priv->iobase2 + acx2cpu(rxdesc->pNextDesc));
-+              }
-+      } else {
-+              /* we didn't pre-calculate rxdesc_start in case of ACX100 */
-+              /* rxdesc_start should be right AFTER Tx pool */
-+              priv->rxdesc_start = (rxdesc_t *)
-+                      ((u8 *) priv->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(priv->rxdesc_start, 0, RX_CNT * sizeof(rxdesc_t));
-+
-+              /* loop over whole receive pool */
-+              rxdesc = priv->rxdesc_start;
-+              mem_offs = rx_queue_start;
-+              for (i = 0; i < RX_CNT; i++) {
-+                      acxlog(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_t));
-+                      /* go to the next one */
-+                      mem_offs += sizeof(rxdesc_t);
-+                      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;
-+}
-+
-+
-+/***************************************************************
-+** acx_create_desc_queues
-+*/
-+void
-+acx_create_desc_queues(wlandevice_t *priv, u32 tx_queue_start, u32 rx_queue_start)
-+{
-+      acx_create_tx_desc_queue(priv, tx_queue_start);
-+      acx_create_rx_desc_queue(priv, rx_queue_start);
-+}
-+
-+
-+/***************************************************************
-+** acxpci_s_proc_diag_output
-+*/
-+char*
-+acxpci_s_proc_diag_output(char *p, wlandevice_t *priv)
-+{
-+      const char *rtl, *thd, *ttl;
-+      rxhostdesc_t *rxhostdesc;
-+      txdesc_t *txdesc;
-+      int i;
-+
-+      FN_ENTER;
-+
-+      p += sprintf(p, "** Rx buf **\n");
-+      rxhostdesc = priv->rxhostdesc_start;
-+      if (rxhostdesc) for (i = 0; i < RX_CNT; i++) {
-+              rtl = (i == priv->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", priv->tx_free,
-+                              acx_queue_stopped(priv->netdev) ? "STOPPED" : "running");
-+      txdesc = priv->txdesc_start;
-+      if (txdesc) for (i = 0; i < TX_CNT; i++) {
-+              thd = (i == priv->tx_head) ? " [head]" : "";
-+              ttl = (i == priv->tx_tail) ? " [tail]" : "";
-+              if (txdesc->Ctl_8 & DESC_CTL_ACXDONE)
-+                      p += sprintf(p, "%02u DONE   (%02X)%s%s\n", i, txdesc->Ctl_8, thd, ttl);
-+              else
-+              if (!(txdesc->Ctl_8 & DESC_CTL_HOSTOWN))
-+                      p += sprintf(p, "%02u TxWait (%02X)%s%s\n", i, txdesc->Ctl_8, thd, ttl);
-+              else
-+                      p += sprintf(p, "%02u empty  (%02X)%s%s\n", i, txdesc->Ctl_8, thd, ttl);
-+              txdesc = move_txdesc(priv, 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",
-+              priv->txbuf_start, priv->txbuf_area_size, (u64)priv->txbuf_startphy,
-+              priv->txdesc_size, priv->txdesc_start,
-+              priv->txhostdesc_start, priv->txhostdesc_area_size, (u64)priv->txhostdesc_startphy,
-+              priv->rxdesc_start,
-+              priv->rxhostdesc_start, priv->rxhostdesc_area_size, (u64)priv->rxhostdesc_startphy,
-+              priv->rxbuf_start, priv->rxbuf_area_size, (u64)priv->rxbuf_startphy);
-+
-+      FN_EXIT0;
-+      return p;
-+}
-+
-+
-+/***********************************************************************
-+*/
-+int
-+acx_proc_eeprom_output(char *buf, wlandevice_t *priv)
-+{
-+      char *p = buf;
-+      int i;
-+
-+      FN_ENTER;
-+
-+      for (i = 0; i < 0x400; i++) {
-+              acx_read_eeprom_offset(priv, i, p++);
-+      }
-+
-+      FN_EXIT1(p - buf);
-+      return p - buf;
-+}
-+
-+
-+/***********************************************************************
-+*/
-+void
-+acx_set_interrupt_mask(wlandevice_t *priv)
-+{
-+      if (IS_ACX111(priv)) {
-+              priv->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        */
-+                              );
-+              priv->irq_mask_off = (u16)~( HOST_INT_CMD_COMPLETE ); /* 0xfdff */
-+      } else {
-+              priv->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        */
-+                              );
-+              priv->irq_mask_off = (u16)~( HOST_INT_UNKNOWN ); /* 0x7fff */
-+      }
-+}
-+
-+
-+/***********************************************************************
-+*/
-+int
-+acx100_s_set_tx_level(wlandevice_t *priv, 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 (priv->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",
-+                              priv->netdev->name);
-+              return NOT_OK;
-+      }
-+      printk("%s: changing radio power level to %u dBm (%u)\n",
-+                      priv->netdev->name, level_dbm, table[level_dbm]);
-+      acxpci_s_write_phy_reg(priv, 0x11, table[level_dbm]);
-+      return OK;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_e_init_module
-+*
-+* Module initialization routine, called once at module load time.
-+*
-+* Returns:
-+*     0       - success
-+*     ~0      - failure, module is unloaded.
-+*
-+* Call context:
-+*     process thread (insmod or modprobe)
-+----------------------------------------------------------------*/
-+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
-+      acxlog(L_INIT, "running on a little-endian CPU\n");
-+#else
-+      acxlog(L_INIT, "running on a BIG-ENDIAN CPU\n");
-+#endif
-+      acxlog(L_INIT, "PCI module " WLAN_RELEASE " initialized, "
-+              "waiting for cards to probe...\n");
-+
-+      res = pci_module_init(&acx_pci_drv_id);
-+      FN_EXIT1(res);
-+      return res;
-+}
-+
-+
-+/*----------------------------------------------------------------
-+* acx_e_cleanup_module
-+*
-+* Called at module unload time.  This is our last chance to
-+* clean up after ourselves.
-+*
-+* Call context:
-+*     process thread
-+----------------------------------------------------------------*/
-+void __exit
-+acxpci_e_cleanup_module(void)
-+{
-+      struct net_device *dev;
-+      unsigned long flags;
-+
-+      FN_ENTER;
-+
-+      /* Since the whole module is about to be unloaded,
-+       * we recursively shutdown all cards we handled instead
-+       * of doing it in remove_pci() (which will be activated by us
-+       * via pci_unregister_driver at the end).
-+       * remove_pci() might just get called after a card eject,
-+       * that's why hardware operations have to be done here instead
-+       * when the hardware is available. */
-+
-+      down(&root_acx_dev_sem);
-+
-+      dev = root_acx_dev.newest;
-+      while (dev != NULL) {
-+              /* doh, netdev_priv() doesn't have const! */
-+              wlandevice_t *priv = netdev_priv(dev);
-+
-+              acx_sem_lock(priv);
-+
-+              /* disable both Tx and Rx to shut radio down properly */
-+              acx_s_issue_cmd(priv, ACX1xx_CMD_DISABLE_TX, NULL, 0);
-+              acx_s_issue_cmd(priv, 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(priv, ACX100_CMD_SLEEP, NULL, 0);
-+#endif
-+              acx_lock(priv, flags);
-+
-+              /* disable power LED to save power :-) */
-+              acxlog(L_INIT, "switching off power LED to save power :-)\n");
-+              acx_l_power_led(priv, 0);
-+
-+              /* stop our eCPU */
-+              if (IS_ACX111(priv)) {
-+                      /* FIXME: does this actually keep halting the eCPU?
-+                       * I don't think so...
-+                       */
-+                      acx_l_reset_mac(priv);
-+              } else {
-+                      u16 temp;
-+
-+                      /* halt eCPU */
-+                      temp = acx_read_reg16(priv, IO_ACX_ECPU_CTRL) | 0x1;
-+                      acx_write_reg16(priv, IO_ACX_ECPU_CTRL, temp);
-+                      acx_write_flush(priv);
-+              }
-+
-+              acx_unlock(priv, flags);
-+
-+              acx_sem_unlock(priv);
-+
-+              dev = priv->prev_nd;
-+      }
-+
-+      up(&root_acx_dev_sem);
-+
-+      /* now let the PCI layer recursively remove
-+       * all PCI related things (acx_e_remove_pci()) */
-+      pci_unregister_driver(&acx_pci_drv_id);
-+
-+      FN_EXIT0;
-+}
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/net/wireless/tiacx/setrate.c bt_kernel/drivers/net/wireless/tiacx/setrate.c
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/net/wireless/tiacx/setrate.c        1970-01-01 02:00:00.000000000 +0200
-+++ bt_kernel/drivers/net/wireless/tiacx/setrate.c     2005-09-28 23:54:23.938287000 +0300
-@@ -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;
-+}
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/net/wireless/tiacx/usb.c bt_kernel/drivers/net/wireless/tiacx/usb.c
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/net/wireless/tiacx/usb.c    1970-01-01 02:00:00.000000000 +0200
-+++ bt_kernel/drivers/net/wireless/tiacx/usb.c 2005-09-28 23:54:23.938287000 +0300
-@@ -0,0 +1,1700 @@
-+/***********************************************************************
-+** 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>
-+**
-+** Issues:
-+**  - Note that this driver relies on a native little-endian byteformat
-+**    at some points
-+**
-+** 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>
-+#include <linux/config.h>
-+#include <linux/types.h>
-+#include <linux/module.h>
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
-+#include <linux/moduleparam.h>
-+#endif
-+#include <linux/kernel.h>
-+#include <linux/usb.h>
-+#include <linux/netdevice.h>
-+#include <linux/rtnetlink.h>
-+#include <linux/etherdevice.h>
-+#include <linux/wireless.h>
-+#if WIRELESS_EXT >= 13
-+#include <net/iw_handler.h>
-+#endif
-+
-+#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 ??? */
-+
-+#define QUEUE_BULK    0
-+#define ZERO_PACKET   URB_ZERO_PACKET
-+
-+static inline int
-+submit_urb(struct urb *urb, int mem_flags)
-+{
-+      return usb_submit_urb(urb, mem_flags);
-+}
-+static inline struct urb*
-+alloc_urb(int iso_pk, int mem_flags)
-+{
-+      return usb_alloc_urb(iso_pk, mem_flags);
-+}
-+
-+
-+/***********************************************************************
-+*/
-+#define ACX100_VENDOR_ID 0x2001
-+#define ACX100_PRODUCT_ID_UNBOOTED 0x3B01
-+#define ACX100_PRODUCT_ID_BOOTED 0x3B00
-+
-+/* RX-Timeout: NONE (request waits forever) */
-+#define ACX100_USB_RX_TIMEOUT (0)
-+
-+#define ACX100_USB_TX_TIMEOUT (4*HZ)
-+
-+#define USB_CTRL_HARD_TIMEOUT 5500   /* steps in ms */
-+
-+
-+/***********************************************************************
-+** Prototypes
-+*/
-+static int acx100usb_e_probe(struct usb_interface *, const struct usb_device_id *);
-+static void acx100usb_e_disconnect(struct usb_interface *);
-+static void acx100usb_i_complete_tx(struct urb *, struct pt_regs *);
-+static void acx100usb_i_complete_rx(struct urb *, struct pt_regs *);
-+static int acx100usb_e_open(struct net_device *);
-+static int acx100usb_e_close(struct net_device *);
-+static void acx100usb_i_set_rx_mode(struct net_device *);
-+static int acx100usb_e_init_network_device(struct net_device *);
-+static int acx100usb_boot(struct usb_device *);
-+
-+static struct net_device_stats * acx_e_get_stats(struct net_device *);
-+static struct iw_statistics *acx_e_get_wireless_stats(struct net_device *);
-+
-+static void acx100usb_l_poll_rx(wlandevice_t *, int number);
-+
-+static void acx100usb_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)
-+//// Bogus! We CANNOT pretend that rxbuffer_t is larger than it is.
-+/* make it a multiply of 64 */
-+/* #define RXBUFSIZE ((sizeof(rxbuffer_t)+63) & ~63) */
-+#define RXBUFSIZE sizeof(rxbuffer_t)
-+
-+static const struct usb_device_id
-+acx100usb_ids[] = {
-+      { USB_DEVICE(ACX100_VENDOR_ID, ACX100_PRODUCT_ID_BOOTED) },
-+      { USB_DEVICE(ACX100_VENDOR_ID, ACX100_PRODUCT_ID_UNBOOTED) },
-+      {}
-+};
-+
-+
-+/* USB driver data structure as required by the kernel's USB core */
-+static struct usb_driver
-+acx100usb_driver = {
-+      .name = "acx_usb",
-+      .owner = THIS_MODULE,
-+      .probe = acx100usb_e_probe,
-+      .disconnect = acx100usb_e_disconnect,
-+      .id_table = acx100usb_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 osolete, usb_unlink_urb will always be
-+** asynchronuos while usb_kill_urb is synchronuos and should be called
-+** directly. -> drivers/usb/core/urb.c
-+**
-+** In light of this, timeout is just for paranoid reasons...
-+*/
-+static void
-+acx_unlink_and_free_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) then what?? */
-+      }
-+
-+      /* just a refcounted kfree, safe undef lock */
-+      usb_free_urb(urb);
-+}
-+
-+
-+/***********************************************************************
-+*/
-+#if ACX_DEBUG
-+static char*
-+acx100usb_pstatus(int val)
-+{
-+      static char status[20];
-+
-+      if (val < 0)
-+              sprintf(status, "errno %d", -val);
-+      else
-+              sprintf(status, "length %d", val);
-+
-+      return status;
-+}
-+#endif /* ACX_DEBUG */
-+
-+
-+/***********************************************************************
-+** EEPROM and PHY read/write helpers
-+*/
-+/***********************************************************************
-+** acxusb_s_read_phy_reg
-+*/
-+int
-+acxusb_s_read_phy_reg(wlandevice_t *priv, u32 reg, u8 *charbuf)
-+{
-+      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);
-+      acx_s_issue_cmd(priv, ACX1xx_CMD_MEM_READ, &mem, sizeof(mem) - 4);
-+      *charbuf = mem.data;
-+      acxlog(L_DEBUG, "radio PHY at 0x%04X = 0x%02X\n", *charbuf, reg);
-+
-+      FN_EXIT1(OK);
-+      return OK;
-+}
-+
-+
-+/***********************************************************************
-+*/
-+int
-+acxusb_s_write_phy_reg(wlandevice_t *priv, 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;
-+//FIXME: maybe sizeof() - 4?
-+      acx_s_issue_cmd(priv, ACX1xx_CMD_MEM_WRITE, &mem, sizeof(mem));
-+      acxlog(L_DEBUG, "radio PHY write 0x%02X at 0x%04X\n", value, reg);
-+
-+      FN_EXIT1(OK);
-+      return OK;
-+}
-+
-+
-+/***********************************************************************
-+** acx_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(
-+      wlandevice_t *priv,
-+      unsigned cmd,
-+      void *buffer,
-+      unsigned buflen,
-+      unsigned timeout)
-+{
-+#else
-+int
-+acxusb_s_issue_cmd_timeo_debug(
-+      wlandevice_t *priv,
-+      unsigned cmd,
-+      void *buffer,
-+      unsigned buflen,
-+      unsigned timeout,
-+      const char* cmdstr)
-+{
-+#endif
-+      /* USB ignores timeout param */
-+
-+      struct usb_device *usbdev;
-+      struct {
-+              u16     cmd ACX_PACKED;
-+              u16     status ACX_PACKED;
-+              u8      data[1] ACX_PACKED;
-+      } *loc;
-+      const char *devname;
-+      int acklen, blocklen, inpipe, outpipe;
-+      int cmd_status;
-+      int result;
-+
-+      FN_ENTER;
-+
-+      devname = priv->netdev->name;
-+      if (!devname || !devname[0])
-+              devname = "acx";
-+
-+      acxlog(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 wlandevice */
-+      usbdev = priv->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);
-+      acxlog(L_CTL, "ctrl inpipe=0x%X outpipe=0x%X\n", inpipe, outpipe);
-+      acxlog(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 */
-+              USB_CTRL_HARD_TIMEOUT /* timeout in ms */
-+      );
-+      acxlog(L_CTL, "wrote %d bytes\n", result);
-+      if (result < 0) {
-+              goto bad;
-+      }
-+
-+      /* check for device acknowledge */
-+      acxlog(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 */
-+              USB_CTRL_HARD_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);
-+              acxlog(L_CTL, "response frame: cmd=0x%04X status=%d\n",
-+                      le16_to_cpu(loc->cmd),
-+                      cmd_status);
-+      }
-+      kfree(loc);
-+      FN_EXIT1(OK);
-+      return OK;
-+bad:
-+      kfree(loc);
-+      /* 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;
-+}
-+
-+
-+/***********************************************************************
-+** acx100usb_e_probe()
-+**
-+** Inputs:
-+**    dev -> Pointer to usb_device structure that may or may not be claimed
-+**  ifNum -> Interface number
-+**  devID -> Device ID (vendor and product specific stuff)
-+************************************************************************
-+** Returns:
-+**  (void *) Pointer to (custom) driver context or NULL if we are not interested
-+**           or unable to handle the offered device.
-+**
-+** Description:
-+**  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
-+acx_netdev_init(struct net_device *dev) {}
-+
-+static int
-+acx100usb_e_probe(struct usb_interface *intf, const struct usb_device_id *devID)
-+{
-+      struct usb_device *usbdev = interface_to_usbdev(intf);
-+      wlandevice_t *priv = NULL;
-+      struct net_device *dev = 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;
-+
-+      FN_ENTER;
-+
-+      /* First check if this is the "unbooted" hardware */
-+      if ((usbdev->descriptor.idVendor == ACX100_VENDOR_ID)
-+       && (usbdev->descriptor.idProduct == ACX100_PRODUCT_ID_UNBOOTED)) {
-+              /* Boot the device (i.e. upload the firmware) */
-+              acx100usb_boot(usbdev);
-+
-+              /* OK, we are done with booting. Normally, the
-+              ** ID for the unbooted device should disappear
-+              ** and it will not need a driver anyway...so
-+              ** return a NULL
-+              */
-+              acxlog(L_INIT, "finished booting, returning from probe()\n");
-+              result = OK; /* success */
-+              goto end;
-+      }
-+
-+      if ((usbdev->descriptor.idVendor != ACX100_VENDOR_ID)
-+       || (usbdev->descriptor.idProduct != ACX100_PRODUCT_ID_BOOTED)) {
-+              goto end_nodev;
-+      }
-+
-+      /* Ok, so it's our device and it is already booted */
-+
-+      /* Allocate memory for a network device */
-+      dev = alloc_netdev(sizeof(wlandevice_t), "wlan%d", acx_netdev_init);
-+      /* (NB: memsets to 0 entire area) */
-+      if (!dev) {
-+              msg = "acx: no memory for netdev\n";
-+              goto end_nomem;
-+      }
-+      dev->init = (void *)&acx100usb_e_init_network_device;
-+
-+      /* Setup private driver context */
-+      priv = netdev_priv(dev);
-+      priv->netdev = dev;
-+      priv->dev_type = DEVTYPE_USB;
-+      priv->chip_type = CHIPTYPE_ACX100;
-+      /* FIXME: should be read from register (via firmware) using standard ACX code */
-+      priv->radio_type = RADIO_MAXIM_0D;
-+      priv->usbdev = usbdev;
-+
-+      spin_lock_init(&priv->lock);    /* initial state: unlocked */
-+      sema_init(&priv->sem, 1);       /* initial state: 1 (upped) */
-+
-+      /* Initialize the device context and also check
-+      ** if 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;
-+      acxlog(L_DEBUG, "# of endpoints: %d\n", numep);
-+
-+      /* obtain information about the endpoint
-+      ** addresses, begin with some default values
-+      */
-+      priv->bulkoutep = 1;
-+      priv->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)
-+                              priv->bulkinep = epdesc->bEndpointAddress & 0xF;
-+                      else
-+                              priv->bulkoutep = epdesc->bEndpointAddress & 0xF;
-+              }
-+      }
-+      acxlog(L_DEBUG, "bulkout ep: 0x%X\n", priv->bulkoutep);
-+      acxlog(L_DEBUG, "bulkin ep: 0x%X\n", priv->bulkinep);
-+
-+      /* Set the packet-size equivalent to the buffer size */
-+      /* already done by memset: priv->rxtruncsize = 0; */
-+      acxlog(L_DEBUG, "TXBUFSIZE=%d RXBUFSIZE=%d\n",
-+                              (int) TXBUFSIZE, (int) RXBUFSIZE);
-+
-+      priv->tx_free = ACX100_USB_NUM_BULK_URBS;
-+      /* already done by memset:
-+      for (i = 0; i < ACX100_USB_NUM_BULK_URBS; i++) {
-+              priv->usb_tx[i].busy = 0;
-+      }
-+      */
-+
-+      /* Setup URBs for bulk-in/out messages */
-+      for (i = 0; i < ACX100_USB_NUM_BULK_URBS; i++) {
-+              priv->bulkrx_urbs[i] = alloc_urb(0, GFP_KERNEL);
-+              if (!priv->bulkrx_urbs[i]) {
-+                      msg = "acx: no memory for input URB\n";
-+                      goto end_nomem;
-+              }
-+              priv->bulkrx_urbs[i]->status = 0;
-+
-+              priv->usb_tx[i].urb = alloc_urb(0, GFP_KERNEL);
-+              if (!priv->usb_tx[i].urb) {
-+                      msg = "acx: no memory for output URB\n";
-+                      goto end_nomem;
-+              }
-+              priv->usb_tx[i].urb->status = 0;
-+
-+              priv->usb_tx[i].priv = priv;
-+      }
-+
-+      usb_set_intfdata(intf, priv);
-+      SET_NETDEV_DEV(dev, &intf->dev);
-+
-+      /* Register the network device */
-+      acxlog(L_INIT, "registering network device\n");
-+      result = register_netdev(dev);
-+      if (result != 0) {
-+              msg = "acx: failed to register network device "
-+                      "for USB WLAN (errcode=%d)\n";
-+              goto end_nomem;
-+      }
-+#ifdef CONFIG_PROC_FS
-+      if (OK != acx_proc_register_entries(dev)) {
-+              printk("acx: /proc registration failed\n");
-+      }
-+#endif
-+
-+      printk("acx: USB module " WLAN_RELEASE " loaded successfully\n");
-+
-+#if CMD_DISCOVERY
-+      great_inquisitor(priv);
-+#endif
-+
-+      /* Everything went OK, we are happy now */
-+      result = OK;
-+      goto end;
-+
-+end_nomem:
-+      printk(msg, result);
-+
-+      if (dev) {
-+              for (i = 0; i < ACX100_USB_NUM_BULK_URBS; i++) {
-+                      usb_free_urb(priv->bulkrx_urbs[i]);
-+                      usb_free_urb(priv->usb_tx[i].urb);
-+              }
-+              free_netdev(dev);
-+      }
-+      result = -ENOMEM;
-+      goto end;
-+
-+end_nodev:
-+
-+      /* no device we could handle, return error. */
-+      result = -EIO;
-+
-+end:
-+      FN_EXIT1(result);
-+      return result;
-+}
-+
-+
-+/***********************************************************************
-+** acx100usb_e_disconnect():
-+** Inputs:
-+**         dev -> Pointer to usb_device structure handled by this module
-+**  devContext -> Pointer to own device context (acx100usb_context)
-+************************************************************************
-+** Description:
-+**  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
-+acx100usb_e_disconnect(struct usb_interface *intf)
-+{
-+      wlandevice_t *priv = usb_get_intfdata(intf);
-+      unsigned long flags;
-+      int i;
-+
-+      FN_ENTER;
-+
-+      /* No WLAN device...no sense */
-+      if (!priv)
-+              goto end;
-+
-+      /*
-+       * We get the sem *after* FLUSH to avoid a deadlock.
-+       * See pci.c:acx_s_down() for deails.
-+       */
-+      FLUSH_SCHEDULED_WORK();
-+      acx_sem_lock(priv);
-+
-+      acx_lock(priv, flags);
-+
-+      /* I wonder if above is enough to prevent tx/rx callbacks
-+      ** to start queue again? Like this:
-+      ** complete_rx -> acx_l_process_rxbuf -> associated -> acx_start_queue()
-+      ** Oh well... */
-+
-+      /* This device exists no more. */
-+      usb_set_intfdata(intf, NULL);
-+
-+      /* stop the transmit queue */
-+      if (priv->netdev) {
-+              acx_stop_queue(priv->netdev, "on USB disconnect");
-+#ifdef CONFIG_PROC_FS
-+              acx_proc_unregister_entries(priv->netdev);
-+#endif
-+      }
-+
-+      /* now abort pending URBs and free them */
-+      for (i = 0; i < ACX100_USB_NUM_BULK_URBS; i++) {
-+              acx_unlink_and_free_urb(priv->bulkrx_urbs[i]);
-+              acx_unlink_and_free_urb(priv->usb_tx[i].urb);
-+      }
-+
-+      acx_unlock(priv, flags);
-+      acx_sem_unlock(priv);
-+
-+      /* Unregister the network devices */
-+      if (priv->netdev) {
-+              unregister_netdev(priv->netdev);
-+              free_netdev(priv->netdev);
-+      }
-+end:
-+      FN_EXIT0;
-+}
-+
-+
-+/***********************************************************************
-+** acx100usb_boot():
-+** Inputs:
-+**    usbdev -> Pointer to kernel's usb_device structure
-+**  endpoint -> Address of the endpoint for control transfers
-+************************************************************************
-+** Returns:
-+**  (int) Errorcode or 0 on success
-+**
-+** Description:
-+**  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 int
-+acx100usb_boot(struct usb_device *usbdev)
-+{
-+      static const char filename[] = "tiacx100usb";
-+
-+      char *firmware = NULL;
-+      char *usbbuf;
-+      unsigned int offset;
-+      unsigned int len, inpipe, outpipe;
-+      u32 checksum;
-+      u32 size;
-+      int result;
-+
-+      FN_ENTER;
-+
-+      usbbuf = kmalloc(ACX100_USB_RWMEM_MAXLEN, GFP_KERNEL);
-+      if (!usbbuf) {
-+              printk(KERN_ERR "acx: no memory for USB transfer buffer ("
-+                      STRING(ACX100_USB_RWMEM_MAXLEN)" bytes)\n");
-+              result = -ENOMEM;
-+              goto end;
-+      }
-+      firmware = (char *)acx_s_read_fw(&usbdev->dev, filename, &size);
-+      if (!firmware) {
-+              result = -EIO;
-+              goto end;
-+      }
-+      acxlog(L_INIT, "firmware size: %d bytes\n", size);
-+
-+      /* Obtain the I/O pipes */
-+      outpipe = usb_sndctrlpipe(usbdev, 0);
-+      inpipe = usb_rcvctrlpipe(usbdev, 0);
-+
-+      /* now upload the firmware, slice the data into blocks */
-+      offset = 8;
-+      while (offset < size) {
-+              len = size - offset;
-+              if (len >= ACX100_USB_RWMEM_MAXLEN) {
-+                      len = ACX100_USB_RWMEM_MAXLEN;
-+              }
-+              acxlog(L_INIT, "uploading firmware (%d bytes, offset=%d)\n",
-+                                              len, offset);
-+              result = 0;
-+              memcpy(usbbuf, firmware + offset, len);
-+              result = usb_control_msg(usbdev, outpipe,
-+                      ACX_USB_REQ_UPLOAD_FW,
-+                      USB_TYPE_VENDOR|USB_DIR_OUT,
-+                      size - 8, /* value */
-+                      0, /* index */
-+                      usbbuf, /* dataptr */
-+                      len, /* size */
-+                      3000 /* timeout in ms */
-+              );
-+              offset += len;
-+              if (result < 0) {
-+#if ACX_DEBUG
-+                      printk(KERN_ERR "acx: error %d (%s) during upload "
-+                              "of firmware, aborting\n", result,
-+                              acx100usb_pstatus(result));
-+#else
-+                      printk(KERN_ERR "acx: error %d during upload "
-+                              "of firmware, aborting\n", result);
-+#endif
-+                      goto end;
-+              }
-+      }
-+
-+      /* finally, send the checksum and reboot the device */
-+      checksum = le32_to_cpu(*(u32 *)firmware);
-+      /* is this triggers the reboot? */
-+      result = usb_control_msg(usbdev, outpipe,
-+              ACX_USB_REQ_UPLOAD_FW,
-+              USB_TYPE_VENDOR|USB_DIR_OUT,
-+              checksum & 0xffff, /* value */
-+              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,
-+              checksum & 0xffff, /* value */
-+              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) {
-+              kfree(usbbuf);
-+              printk(KERN_ERR "acx: invalid checksum?\n");
-+              result = -EINVAL;
-+              goto end;
-+      }
-+      result = 0;
-+end:
-+      vfree(firmware);
-+      kfree(usbbuf);
-+
-+      FN_EXIT1(result);
-+      return result;
-+}
-+
-+
-+/***********************************************************************
-+** acx100usb_e_init_network_device():
-+** Inputs:
-+**    dev -> Pointer to network device
-+************************************************************************
-+** Description:
-+**  Basic setup of a network device for use with the WLAN device.
-+*/
-+static int
-+acx100usb_e_init_network_device(struct net_device *dev)
-+{
-+      wlandevice_t *priv;
-+      int result = 0;
-+
-+      FN_ENTER;
-+
-+      /* Setup the device and stop the queue */
-+      ether_setup(dev);
-+      acx_stop_queue(dev, "on init");
-+
-+      priv = netdev_priv(dev);
-+
-+      acx_sem_lock(priv);
-+
-+      /* put the ACX100 out of sleep mode */
-+      acx_s_issue_cmd(priv, ACX1xx_CMD_WAKE, NULL, 0);
-+
-+      /* Register the callbacks for the network device functions */
-+      dev->open = &acx100usb_e_open;
-+      dev->stop = &acx100usb_e_close;
-+      dev->hard_start_xmit = (void *)&acx_i_start_xmit;
-+      dev->get_stats = (void *)&acx_e_get_stats;
-+      dev->get_wireless_stats = (void *)&acx_e_get_wireless_stats;
-+#if WIRELESS_EXT >= 13
-+      dev->wireless_handlers = (struct iw_handler_def *)&acx_ioctl_handler_def;
-+#else
-+      dev->do_ioctl = (void *)&acx_e_ioctl_old;
-+#endif
-+      dev->set_multicast_list = (void *)&acx100usb_i_set_rx_mode;
-+#ifdef HAVE_TX_TIMEOUT
-+      dev->tx_timeout = &acx100usb_i_tx_timeout;
-+      dev->watchdog_timeo = 4 * HZ;
-+#endif
-+      result = acx_s_init_mac(dev);
-+      if (OK != result)
-+              goto end;
-+      result = acx_s_set_defaults(priv);
-+      if (OK != result) {
-+              printk("%s: acx_set_defaults FAILED\n", dev->name);
-+              goto end;
-+      }
-+
-+      SET_MODULE_OWNER(dev);
-+end:
-+      acx_sem_unlock(priv);
-+
-+      FN_EXIT1(result);
-+      return result;
-+}
-+
-+
-+/***********************************************************************
-+** acx100usb_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
-+acx100usb_e_open(struct net_device *dev)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+      unsigned long flags;
-+      int i;
-+
-+      FN_ENTER;
-+
-+      acx_sem_lock(priv);
-+
-+      /* put the ACX100 out of sleep mode */
-+      acx_s_issue_cmd(priv, ACX1xx_CMD_WAKE, NULL, 0);
-+
-+      acx_init_task_scheduler(priv);
-+
-+      init_timer(&priv->mgmt_timer);
-+      priv->mgmt_timer.function = acx_i_timer;
-+      priv->mgmt_timer.data = (unsigned long)priv;
-+
-+      /* set ifup to 1, since acx_start needs it */
-+      SET_BIT(priv->dev_state_mask, ACX_STATE_IFACE_UP);
-+      acx_s_start(priv);
-+
-+      acx_start_queue(dev, "on open");
-+
-+      acx_lock(priv, flags);
-+      for (i = 0; i < ACX100_USB_NUM_BULK_URBS; i++) {
-+              acx100usb_l_poll_rx(priv, i);
-+      }
-+      acx_unlock(priv, flags);
-+
-+      WLAN_MOD_INC_USE_COUNT;
-+
-+      acx_sem_unlock(priv);
-+
-+      FN_EXIT0;
-+      return 0;
-+}
-+
-+
-+/***********************************************************************
-+** acx100usb_l_poll_rx
-+** This function initiates a bulk-in USB transfer (in case the interface
-+** is up).
-+*/
-+static void
-+acx100usb_l_poll_rx(wlandevice_t *priv, int number)
-+{
-+      struct usb_device *usbdev;
-+      rxbuffer_t *inbuf;
-+      acx_usb_bulk_context_t *rxcon;
-+      struct urb *rxurb;
-+      int errcode;
-+      unsigned int inpipe;
-+
-+      FN_ENTER;
-+
-+      if (!(priv->dev_state_mask & ACX_STATE_IFACE_UP)) {
-+              goto end;
-+      }
-+
-+      rxcon = &priv->rxcons[number];
-+      inbuf = &priv->bulkins[number];
-+      rxurb = priv->bulkrx_urbs[number];
-+      usbdev = priv->usbdev;
-+
-+      rxcon->device = priv;
-+      rxcon->number = number;
-+      inpipe = usb_rcvbulkpipe(usbdev, priv->bulkinep);
-+      if (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);
-+      }
-+      rxurb->actual_length = 0;
-+      usb_fill_bulk_urb(rxurb, usbdev, inpipe,
-+              inbuf, /* dataptr */
-+              RXBUFSIZE, /* size */
-+              acx100usb_i_complete_rx, /* handler */
-+              rxcon /* handler param */
-+      );
-+      rxurb->transfer_flags = QUEUE_BULK;
-+
-+      /* ATOMIC: we may be called from complete_rx() usb callback */
-+      errcode = submit_urb(rxurb, GFP_ATOMIC);
-+      /* FIXME: evaluate the error code! */
-+      acxlog(L_USBRXTX, "SUBMIT RX (%d) inpipe=0x%X size=%d errcode=%d\n",
-+                      number, inpipe, (int) RXBUFSIZE, errcode);
-+
-+end:
-+      FN_EXIT0;
-+}
-+
-+
-+/***********************************************************************
-+** acx100usb_i_complete_rx():
-+** Inputs:
-+**     urb -> Pointer to USB request block
-+**    regs -> Pointer to register-buffer for syscalls (see asm/ptrace.h)
-+************************************************************************
-+** Description:
-+**  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
-+acx100usb_i_complete_rx(struct urb *urb, struct pt_regs *regs)
-+{
-+      wlandevice_t *priv;
-+      rxbuffer_t *ptr;
-+      rxbuffer_t *inbuf;
-+      unsigned long flags;
-+      int size, number, remsize, packetsize;
-+
-+      FN_ENTER;
-+
-+      if (!urb->context) {
-+              printk(KERN_ERR "acx: error, urb context was NULL\n");
-+              goto end; /* at least try to prevent the worst */
-+      }
-+
-+      priv = ((acx_usb_bulk_context_t *)urb->context)->device;
-+
-+      acx_lock(priv, flags);
-+
-+      /* TODO: we maybe need to check whether urb was unlinked
-+      ** (happens on disconnect and close, see there). How? */
-+
-+      number = ((acx_usb_bulk_context_t *)urb->context)->number;
-+      size = urb->actual_length;
-+      remsize = size;
-+
-+      acxlog(L_USBRXTX, "RETURN RX (%d) status=%d size=%d\n",
-+                              number, urb->status, size);
-+
-+      inbuf = &priv->bulkins[number];
-+      ptr = inbuf;
-+
-+      /* check if the transfer was aborted */
-+      switch (urb->status) {
-+      case 0: /* No error */
-+              break;
-+      case -EOVERFLOW:
-+              printk(KERN_ERR "acx: error in rx, data overrun -> emergency stop\n");
-+              /* LOCKING BUG! acx100usb_e_close(priv->netdev); */
-+              goto end_unlock;
-+      case -ECONNRESET:
-+              goto do_poll_rx;
-+      default:
-+              priv->stats.rx_errors++;
-+              printk("acx: rx error (urb status=%d)\n", urb->status);
-+              goto do_poll_rx;
-+      }
-+
-+      if (!size)
-+              printk("acx: warning, encountered zerolength rx packet\n");
-+
-+      if (urb->transfer_buffer != inbuf)
-+              goto do_poll_rx;
-+
-+      /* check if previous frame was truncated
-+      ** FIXME: this code can only handle truncation
-+      ** of consecutive packets!
-+      */
-+      if (priv->rxtruncsize) {
-+              int tail_size;
-+
-+              ptr = &priv->rxtruncbuf;
-+              packetsize = RXBUF_BYTES_RCVD(ptr) + RXBUF_HDRSIZE;
-+              if (acx_debug & L_USBRXTX) {
-+                      printk("handling truncated frame (truncsize=%d size=%d "
-+                                      "packetsize(from trunc)=%d)\n",
-+                                      priv->rxtruncsize, size, packetsize);
-+                      acx_dump_bytes(ptr, RXBUF_HDRSIZE);
-+                      acx_dump_bytes(inbuf, RXBUF_HDRSIZE);
-+              }
-+
-+              /* bytes needed for rxtruncbuf completion: */
-+              tail_size = packetsize - priv->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) + priv->rxtruncsize, inbuf, size);
-+                      priv->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: priv->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) + priv->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(priv, ptr);
-+                      priv->rxtruncsize = 0;
-+                      ptr = (rxbuffer_t *) (((char *)inbuf) + tail_size);
-+                      remsize -= tail_size;
-+              }
-+              acxlog(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);
-+                      break;
-+              }
-+              packetsize = RXBUF_BYTES_RCVD(ptr) + RXBUF_HDRSIZE;
-+              acxlog(L_USBRXTX, "packet with packetsize=%d\n", packetsize);
-+              if (packetsize > sizeof(rxbuffer_t)) {
-+                      printk("acx: packet exceeds max wlan "
-+                              "frame size (%d > %d). size=%d\n",
-+                              packetsize, (int) sizeof(rxbuffer_t), size);
-+                      /* FIXME: put some real error-handling in here! */
-+                      break;
-+              }
-+
-+              /* skip null packets (does this really happen?!) */
-+              if (packetsize == RXBUF_HDRSIZE) {
-+                      remsize -= RXBUF_HDRSIZE;
-+                      if (acx_debug & L_USBRXTX) {
-+                              printk("acx: null packet, new remsize=%d. "
-+                                      "header follows:\n", remsize);
-+                              acx_dump_bytes(ptr, RXBUF_HDRSIZE);
-+                      }
-+                      ptr = (rxbuffer_t *)(((char *)ptr) + RXBUF_HDRSIZE);
-+                      continue;
-+              }
-+
-+              if (packetsize > remsize) {
-+                      /* frame truncation handling */
-+                      if (acx_debug & L_USBRXTX) {
-+                              printk("need to truncate packet, "
-+                                      "packetsize=%d remsize=%d "
-+                                      "size=%d\n",
-+                                      packetsize, remsize, size);
-+                              acx_dump_bytes(ptr, RXBUF_HDRSIZE);
-+                      }
-+                      memcpy(&priv->rxtruncbuf, ptr, remsize);
-+                      priv->rxtruncsize = remsize;
-+                      break;
-+              } else { /* packetsize <= remsize */
-+                      /* now handle the received data */
-+                      acx_l_process_rxbuf(priv, ptr);
-+
-+                      ptr = (rxbuffer_t *)(((char *)ptr) + packetsize);
-+                      remsize -= packetsize;
-+                      if ((acx_debug & L_USBRXTX) && remsize) {
-+                              printk("more than one packet in buffer, "
-+                                              "second packet hdr follows\n");
-+                              acx_dump_bytes(ptr, RXBUF_HDRSIZE);
-+                      }
-+              }
-+      }
-+
-+do_poll_rx:
-+      /* look for the next rx */
-+      if (priv->dev_state_mask & ACX_STATE_IFACE_UP) {
-+              /* receive of frame completed, now look for the next one */
-+              acx100usb_l_poll_rx(priv, number);
-+      }
-+
-+end_unlock:
-+      acx_unlock(priv, flags);
-+end:
-+      FN_EXIT0;
-+}
-+
-+
-+/***********************************************************************
-+** acx100usb_i_complete_tx():
-+** Inputs:
-+**     urb -> Pointer to USB request block
-+**    regs -> Pointer to register-buffer for syscalls (see asm/ptrace.h)
-+************************************************************************
-+** Description:
-+**   This function is invoked upon termination of a USB transfer. As the
-+**   USB device is only capable of sending a limited amount of bytes per
-+**   transfer to the bulk-out endpoint, this routine checks if there are
-+**   more bytes to send and triggers subsequent transfers. In case the
-+**   transfer size exactly matches the maximum bulk-out size, it triggers
-+**   a transfer of a null-frame, telling the card that this is it. Upon
-+**   completion of a frame, it checks whether the Tx ringbuffer contains
-+**   more data to send and invokes the Tx routines if this is the case.
-+**   If there are no more occupied Tx descriptors, the Tx Mutex is unlocked
-+**   and the network queue is switched back to life again.
-+**
-+** FIXME: unlike PCI code, we do not analyze tx rate used, retries, etc...
-+** Thus we have no automatic rate control in USB!
-+*/
-+static void
-+acx100usb_i_complete_tx(struct urb *urb, struct pt_regs *regs)
-+{
-+      wlandevice_t *priv;
-+      usb_tx_t *tx;
-+      unsigned long flags;
-+
-+      FN_ENTER;
-+
-+      if (!urb->context) {
-+              printk(KERN_ERR "acx: error, NULL context in tx completion callback\n");
-+              /* FIXME: real error-handling code must go here! */
-+              goto end;
-+      }
-+
-+      tx = (usb_tx_t *)urb->context;
-+      priv = tx->priv;
-+
-+      acx_lock(priv, flags);
-+
-+      /* TODO: we maybe need to check whether urb was unlinked
-+      ** (happens on disconnect and close, see there). How? */
-+
-+      acxlog(L_USBRXTX, "RETURN TX (%p): status=%d size=%d\n",
-+                              tx, urb->status, urb->actual_length);
-+
-+      /* handle USB transfer errors */
-+      switch (urb->status) {
-+      case 0: /* No error */
-+              break;
-+      case -ECONNRESET:
-+              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 */
-+      priv->tx_free++;
-+      tx->busy = 0;
-+
-+/* end_unlock: */
-+      acx_unlock(priv, flags);
-+end:
-+      FN_EXIT0;
-+}
-+
-+
-+/***********************************************************************
-+** acx100usb_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
-+acx100usb_e_close(struct net_device *dev)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+      unsigned long flags;
-+      int i;
-+
-+      FN_ENTER;
-+
-+#if WE_STILL_DONT_CARE_ABOUT_IT
-+      /* Transmit a disassociate frame */
-+      lock
-+      acx_l_transmit_disassoc(priv, &client);
-+      unlock
-+#endif
-+
-+      /*
-+       * We get the sem *after* FLUSH to avoid a deadlock.
-+       * See pci.c:acx_s_down() for deails.
-+       */
-+      FLUSH_SCHEDULED_WORK();
-+      acx_sem_lock(priv);
-+
-+      /* stop the transmit queue, mark the device as DOWN */
-+      acx_lock(priv, flags);
-+      acx_stop_queue(dev, "on iface stop");
-+      CLEAR_BIT(priv->dev_state_mask, ACX_STATE_IFACE_UP);
-+
-+      /* I wonder if above is enough to prevent tx/rx callbacks
-+      ** to start queue again? Like this:
-+      ** complete_rx -> acx_l_process_rxbuf -> associated -> acx_start_queue()
-+      ** Oh well... */
-+
-+      /* stop pending rx/tx urb transfers */
-+      for (i = 0; i < ACX100_USB_NUM_BULK_URBS; i++) {
-+              acx_unlink_and_free_urb(priv->bulkrx_urbs[i]);
-+              acx_unlink_and_free_urb(priv->usb_tx[i].urb);
-+      }
-+      acx_unlock(priv, flags);
-+
-+      /* disable rx and tx */
-+      acx_s_issue_cmd(priv, ACX1xx_CMD_DISABLE_TX, NULL, 0);
-+      acx_s_issue_cmd(priv, ACX1xx_CMD_DISABLE_RX, NULL, 0);
-+
-+      /* power down the device */
-+      acx_s_issue_cmd(priv, ACX1xx_CMD_SLEEP, NULL, 0);
-+
-+      acx_sem_unlock(priv);
-+
-+      /* decrease module-in-use count (if necessary) */
-+
-+      WLAN_MOD_DEC_USE_COUNT;
-+
-+      FN_EXIT0;
-+      return 0;
-+}
-+
-+
-+/***************************************************************
-+** acxusb_l_alloc_tx
-+** Actually returns a usb_tx_t* ptr
-+*/
-+tx_t*
-+acxusb_l_alloc_tx(wlandevice_t* priv)
-+{
-+      int i;
-+      usb_tx_t *tx = NULL;
-+
-+      FN_ENTER;
-+
-+      for (i = 0; i < ACX100_USB_NUM_BULK_URBS; i++) {
-+              if (!priv->usb_tx[i].busy) {
-+                      tx = &priv->usb_tx[i];
-+                      tx->busy = 1;
-+                      break;
-+              }
-+      }
-+      if (i >= ACX100_USB_NUM_BULK_URBS) {
-+              printk("acx: tx buffers full\n");
-+      }
-+
-+      FN_EXIT0;
-+
-+      return (tx_t*)tx;
-+}
-+
-+
-+/***************************************************************
-+*/
-+void*
-+acxusb_l_get_txbuf(wlandevice_t *priv, 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(wlandevice_t *priv, 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;
-+      u8 rate100;
-+
-+      FN_ENTER;
-+
-+      tx = ((usb_tx_t *)tx_opaque);
-+      txurb = tx->urb;
-+      txbuf = &tx->bulkout;
-+      whdr = (wlan_hdr_t *)txbuf->data;
-+
-+      priv->tx_free--;
-+      acxlog(L_DEBUG, "using buf#%d free=%d len=%d\n",
-+                      (int)(tx - priv->usb_tx),
-+                      priv->tx_free, wlanpkt_len);
-+
-+      switch (priv->mode) {
-+      case ACX_MODE_0_ADHOC:
-+      case ACX_MODE_3_AP:
-+              clt = acx_l_sta_list_get(priv, whdr->a1);
-+              break;
-+      case ACX_MODE_2_STA:
-+              clt = priv->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;
-+      }
-+
-+      /* used in tx cleanup routine for auto rate and accounting: */
-+//TODO: currently unused - fix that
-+      tx->txc = clt;
-+
-+      rate100 = clt ? clt->rate_100 : priv->rate_bcast100;
-+
-+      /* fill the USB transfer header */
-+      txbuf->desc = cpu_to_le16(USB_TXBUF_TXDESC);
-+      txbuf->MPDUlen = cpu_to_le16(wlanpkt_len);
-+      txbuf->ctrl1 = 0;
-+      txbuf->ctrl2 = 0;
-+      txbuf->hostData = cpu_to_le32(wlanpkt_len | (rate100 << 24));
-+      if (1 == priv->preamble_cur)
-+              SET_BIT(txbuf->ctrl1, DESC_CTL_SHORT_PREAMBLE);
-+      SET_BIT(txbuf->ctrl1, DESC_CTL_FIRSTFRAG);
-+      txbuf->txRate = rate100;
-+      txbuf->index = 1;
-+      txbuf->dataLength = cpu_to_le16(wlanpkt_len);
-+
-+      if ( (WF_FC_FTYPEi & whdr->fc) == WF_FTYPE_DATAi )
-+              SET_BIT(txbuf->hostData, cpu_to_le32(USB_TXBUF_HD_ISDATA));
-+      if (mac_is_directed(whdr->a1))
-+              SET_BIT(txbuf->hostData, cpu_to_le32(USB_TXBUF_HD_DIRECTED));
-+      else if (mac_is_bcast(whdr->a1))
-+              SET_BIT(txbuf->hostData, cpu_to_le32(USB_TXBUF_HD_BROADCAST));
-+
-+      if (acx_debug & L_DATA) {
-+              printk("dump of bulk out urb:\n");
-+              acx_dump_bytes(txbuf, wlanpkt_len + USB_TXBUF_HDRSIZE);
-+      }
-+
-+      if (txurb->status == -EINPROGRESS) {
-+              printk("acx: trying to submit tx urb while already in progress\n");
-+      }
-+
-+      /* now schedule the USB transfer */
-+      usbdev = priv->usbdev;
-+      outpipe = usb_sndbulkpipe(usbdev, priv->bulkoutep);
-+//can be removed, please try & test:
-+      tx->priv = priv;
-+
-+      usb_fill_bulk_urb(txurb, usbdev, outpipe,
-+              txbuf, /* dataptr */
-+              wlanpkt_len + USB_TXBUF_HDRSIZE, /* size */
-+              acx100usb_i_complete_tx, /* handler */
-+              tx /* handler param */
-+      );
-+
-+      txurb->transfer_flags = QUEUE_BULK|ZERO_PACKET;
-+      ucode = submit_urb(txurb, GFP_ATOMIC);
-+      acxlog(L_USBRXTX, "SUBMIT TX (%p): outpipe=0x%X buf=%p txsize=%d "
-+              "errcode=%d\n", tx, outpipe, txbuf,
-+              wlanpkt_len + USB_TXBUF_HDRSIZE, ucode);
-+
-+      if (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
-+              */
-+              priv->stats.tx_errors++;
-+              tx->busy = 0;
-+              priv->tx_free++;
-+      }
-+end:
-+      FN_EXIT0;
-+}
-+
-+
-+/***********************************************************************
-+*/
-+static struct net_device_stats*
-+acx_e_get_stats(netdevice_t *dev)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+      return &priv->stats;
-+}
-+
-+
-+/***********************************************************************
-+*/
-+static struct iw_statistics*
-+acx_e_get_wireless_stats(netdevice_t *dev)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+      FN_ENTER;
-+      FN_EXIT0;
-+      return &priv->wstats;
-+}
-+
-+
-+/***********************************************************************
-+*/
-+static void
-+acx100usb_i_set_rx_mode(struct net_device *dev)
-+{
-+}
-+
-+
-+/***********************************************************************
-+*/
-+#ifdef HAVE_TX_TIMEOUT
-+static void
-+acx100usb_i_tx_timeout(struct net_device *dev)
-+{
-+      wlandevice_t *priv = netdev_priv(dev);
-+      unsigned long flags;
-+      int i;
-+
-+      FN_ENTER;
-+
-+      acx_lock(priv, flags);
-+      /* unlink the URBs */
-+      for (i = 0; i < ACX100_USB_NUM_BULK_URBS; i++) {
-+              if (priv->usb_tx[i].urb->status == -EINPROGRESS)
-+                      usb_unlink_urb(priv->usb_tx[i].urb);
-+      }
-+      /* TODO: stats update */
-+      acx_unlock(priv, 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)
-+{
-+      acxlog(L_INIT, "USB module " WLAN_RELEASE " initialized, "
-+              "probing for devices...\n");
-+      return usb_register(&acx100usb_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(&acx100usb_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, 8)
-+      /* halted removed in 2.6.9-rc1 */
-+      /* DOH, Canbreak... err... Mandrake decided to do their very own very
-+       * special version "2.6.8.1" which already includes this change, so we
-+       * need to blacklist that version already (i.e. 2.6.8) */
-+      printk("  halted[0]: 0x%X  halted[1]: 0x%X\n", usbdev->halted[0], usbdev->halted[1]);
-+#endif
-+#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)
-+              printk("%d ", usbdev->ep_in[i]->desc.wMaxPacketSize);
-+      printk("\n");
-+      printk("  ep_out wMaxPacketSize: ");
-+      for (i = 0; i < 15; ++i)
-+              printk("%d ", 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);
-+#if 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 */
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/net/wireless/tiacx/wlan.c bt_kernel/drivers/net/wireless/tiacx/wlan.c
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/net/wireless/tiacx/wlan.c   1970-01-01 02:00:00.000000000 +0200
-+++ bt_kernel/drivers/net/wireless/tiacx/wlan.c        2005-09-28 23:54:23.938287000 +0300
-@@ -0,0 +1,392 @@
-+/***********************************************************************
-+** 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/config.h>
-+#include <linux/version.h>
-+
-+#include <linux/types.h>
-+#include <linux/if_arp.h>
-+#include <linux/wireless.h>
-+#if WIRELESS_EXT >= 13
-+#include <net/iw_handler.h>
-+#endif
-+
-+#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_NONERP:
-+              /* was seen from WRT54GS with OpenWrt: 2F 01 07 */
-+              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);
-+}
-+
-+
-+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);
-+      }
-+}
-+
-+
-+/* 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;
-+              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 */
-+}
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/net/wireless/tiacx/wlan_compat.h bt_kernel/drivers/net/wireless/tiacx/wlan_compat.h
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/net/wireless/tiacx/wlan_compat.h    1970-01-01 02:00:00.000000000 +0200
-+++ bt_kernel/drivers/net/wireless/tiacx/wlan_compat.h 2005-09-28 23:54:23.938287000 +0300
-@@ -0,0 +1,297 @@
-+/***********************************************************************
-+** 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_ATTRIB_PACK__          __attribute__ ((packed))
-+#define __WLAN_PRAGMA_PACK1__
-+#define __WLAN_PRAGMA_PACKDFLT__
-+
-+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,38))
-+ typedef struct device netdevice_t;
-+#elif (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,4))
-+ typedef struct net_device netdevice_t;
-+#else
-+ #undef netdevice_t
-+ typedef struct net_device netdevice_t;
-+#endif
-+
-+#ifdef WIRELESS_EXT
-+#if (WIRELESS_EXT < 13)
-+struct iw_request_info {
-+      __u16 cmd;              /* Wireless Extension command */
-+      __u16 flags;            /* More to come ;-) */
-+};
-+#endif
-+#endif
-+
-+/* Interrupt handler backwards compatibility stuff */
-+#ifndef IRQ_NONE
-+#define IRQ_NONE
-+#define IRQ_HANDLED
-+typedef void irqreturn_t;
-+#endif
-+
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,41)  /* more or less */
-+#define WLAN_MOD_INC_USE_COUNT        MOD_INC_USE_COUNT
-+#define WLAN_MOD_DEC_USE_COUNT        MOD_DEC_USE_COUNT
-+#else
-+#define WLAN_MOD_INC_USE_COUNT
-+#define WLAN_MOD_DEC_USE_COUNT
-+#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
-+/* unused
-+#define WLAN_ETHHDR_LEN       14
-+#define WLAN_ETHCONV_ENCAP    1
-+#define WLAN_ETHCONV_RFC1042  2
-+#define WLAN_ETHCONV_8021h    3
-+#define WLAN_MIN_ETHFRM_LEN   60
-+#define WLAN_MAX_ETHFRM_LEN   1514
-+*/
-+
-+/*============================================================================*
-+ * Types                                                                      *
-+ *============================================================================*/
-+
-+/* local ether header type */
-+typedef struct wlan_ethhdr {
-+      u8      daddr[ETH_ALEN] __WLAN_ATTRIB_PACK__;
-+      u8      saddr[ETH_ALEN] __WLAN_ATTRIB_PACK__;
-+      u16     type __WLAN_ATTRIB_PACK__;
-+} wlan_ethhdr_t;
-+
-+/* local llc header type */
-+typedef struct wlan_llc {
-+      u8      dsap __WLAN_ATTRIB_PACK__;
-+      u8      ssap __WLAN_ATTRIB_PACK__;
-+      u8      ctl __WLAN_ATTRIB_PACK__;
-+} wlan_llc_t;
-+
-+/* local snap header type */
-+typedef struct wlan_snap {
-+      u8      oui[WLAN_IEEE_OUI_LEN] __WLAN_ATTRIB_PACK__;
-+      u16     type __WLAN_ATTRIB_PACK__;
-+} wlan_snap_t;
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/net/wireless/tiacx/wlan_hdr.h bt_kernel/drivers/net/wireless/tiacx/wlan_hdr.h
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/net/wireless/tiacx/wlan_hdr.h       1970-01-01 02:00:00.000000000 +0200
-+++ bt_kernel/drivers/net/wireless/tiacx/wlan_hdr.h    2005-09-28 23:54:23.938287000 +0300
-@@ -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     */
-+/*    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 __WLAN_ATTRIB_PACK__;
-+      u16     dur __WLAN_ATTRIB_PACK__;
-+      u8      a1[ETH_ALEN] __WLAN_ATTRIB_PACK__;
-+      u8      a2[ETH_ALEN] __WLAN_ATTRIB_PACK__;
-+      u8      a3[ETH_ALEN] __WLAN_ATTRIB_PACK__;
-+      u16     seq __WLAN_ATTRIB_PACK__;
-+      u8      a4[ETH_ALEN] __WLAN_ATTRIB_PACK__;
-+} wlan_hdr_t;
-+
-+/* Separate structs for use if frame type is known */
-+typedef struct wlan_hdr_a3 {
-+      u16     fc __WLAN_ATTRIB_PACK__;
-+      u16     dur __WLAN_ATTRIB_PACK__;
-+      u8      a1[ETH_ALEN] __WLAN_ATTRIB_PACK__;
-+      u8      a2[ETH_ALEN] __WLAN_ATTRIB_PACK__;
-+      u8      a3[ETH_ALEN] __WLAN_ATTRIB_PACK__;
-+      u16     seq __WLAN_ATTRIB_PACK__;
-+} wlan_hdr_a3_t;
-+
-+typedef struct wlan_hdr_mgmt {
-+      u16     fc __WLAN_ATTRIB_PACK__;
-+      u16     dur __WLAN_ATTRIB_PACK__;
-+      u8      da[ETH_ALEN] __WLAN_ATTRIB_PACK__;
-+      u8      sa[ETH_ALEN] __WLAN_ATTRIB_PACK__;
-+      u8      bssid[ETH_ALEN] __WLAN_ATTRIB_PACK__;
-+      u16     seq __WLAN_ATTRIB_PACK__;
-+} wlan_hdr_mgmt_t;
-+
-+#ifdef NOT_NEEDED_YET
-+typedef struct { /* ad-hoc peer->peer (to/from DS = 0/0) */
-+      u16     fc __WLAN_ATTRIB_PACK__;
-+      u16     dur __WLAN_ATTRIB_PACK__;
-+      u8      da[ETH_ALEN] __WLAN_ATTRIB_PACK__;
-+      u8      sa[ETH_ALEN] __WLAN_ATTRIB_PACK__;
-+      u8      bssid[ETH_ALEN] __WLAN_ATTRIB_PACK__;
-+      u16     seq __WLAN_ATTRIB_PACK__;
-+} ibss;
-+typedef struct { /* ap->sta (to/from DS = 0/1) */
-+      u16     fc __WLAN_ATTRIB_PACK__;
-+      u16     dur __WLAN_ATTRIB_PACK__;
-+      u8      da[ETH_ALEN] __WLAN_ATTRIB_PACK__;
-+      u8      bssid[ETH_ALEN] __WLAN_ATTRIB_PACK__;
-+      u8      sa[ETH_ALEN] __WLAN_ATTRIB_PACK__;
-+      u16     seq __WLAN_ATTRIB_PACK__;
-+} fromap;
-+typedef struct { /* sta->ap (to/from DS = 1/0) */
-+      u16     fc __WLAN_ATTRIB_PACK__;
-+      u16     dur __WLAN_ATTRIB_PACK__;
-+      u8      bssid[ETH_ALEN] __WLAN_ATTRIB_PACK__;
-+      u8      sa[ETH_ALEN] __WLAN_ATTRIB_PACK__;
-+      u8      da[ETH_ALEN] __WLAN_ATTRIB_PACK__;
-+      u16     seq __WLAN_ATTRIB_PACK__;
-+} toap;
-+typedef struct { /* wds->wds (to/from DS = 1/1), the only 4addr pkt */
-+      u16     fc __WLAN_ATTRIB_PACK__;
-+      u16     dur __WLAN_ATTRIB_PACK__;
-+      u8      ra[ETH_ALEN] __WLAN_ATTRIB_PACK__;
-+      u8      ta[ETH_ALEN] __WLAN_ATTRIB_PACK__;
-+      u8      da[ETH_ALEN] __WLAN_ATTRIB_PACK__;
-+      u16     seq __WLAN_ATTRIB_PACK__;
-+      u8      sa[ETH_ALEN] __WLAN_ATTRIB_PACK__;
-+} wds;
-+typedef struct { /* all management packets */
-+      u16     fc __WLAN_ATTRIB_PACK__;
-+      u16     dur __WLAN_ATTRIB_PACK__;
-+      u8      da[ETH_ALEN] __WLAN_ATTRIB_PACK__;
-+      u8      sa[ETH_ALEN] __WLAN_ATTRIB_PACK__;
-+      u8      bssid[ETH_ALEN] __WLAN_ATTRIB_PACK__;
-+      u16     seq __WLAN_ATTRIB_PACK__;
-+} mgmt;
-+typedef struct { /* has no body, just a FCS */
-+      u16     fc __WLAN_ATTRIB_PACK__;
-+      u16     dur __WLAN_ATTRIB_PACK__;
-+      u8      ra[ETH_ALEN] __WLAN_ATTRIB_PACK__;
-+      u8      ta[ETH_ALEN] __WLAN_ATTRIB_PACK__;
-+} rts;
-+typedef struct { /* has no body, just a FCS */
-+      u16     fc __WLAN_ATTRIB_PACK__;
-+      u16     dur __WLAN_ATTRIB_PACK__;
-+      u8      ra[ETH_ALEN] __WLAN_ATTRIB_PACK__;
-+} cts;
-+typedef struct { /* has no body, just a FCS */
-+      u16     fc __WLAN_ATTRIB_PACK__;
-+      u16     dur __WLAN_ATTRIB_PACK__;
-+      u8      ra[ETH_ALEN] __WLAN_ATTRIB_PACK__;
-+} ack;
-+typedef struct { /* has no body, just a FCS */
-+      u16     fc __WLAN_ATTRIB_PACK__;
-+      /* NB: this one holds Assoc ID in dur field: */
-+      u16     aid __WLAN_ATTRIB_PACK__;
-+      u8      bssid[ETH_ALEN] __WLAN_ATTRIB_PACK__;
-+      u8      ta[ETH_ALEN] __WLAN_ATTRIB_PACK__;
-+} pspoll;
-+typedef struct { /* has no body, just a FCS */
-+      u16     fc __WLAN_ATTRIB_PACK__;
-+      u16     dur __WLAN_ATTRIB_PACK__;
-+      u8      ra[ETH_ALEN] __WLAN_ATTRIB_PACK__;
-+      u8      bssid[ETH_ALEN] __WLAN_ATTRIB_PACK__;
-+} cfend;
-+typedef struct { /* has no body, just a FCS */
-+      u16     fc __WLAN_ATTRIB_PACK__;
-+      u16     dur __WLAN_ATTRIB_PACK__;
-+      u8      ra[ETH_ALEN] __WLAN_ATTRIB_PACK__;
-+      u8      bssid[ETH_ALEN] __WLAN_ATTRIB_PACK__;
-+} cfendcfack;
-+#endif
-+
-+/* Prism header emulation (monitor mode) */
-+typedef struct wlanitem_u32 {
-+      u32     did __WLAN_ATTRIB_PACK__;
-+      u16     status __WLAN_ATTRIB_PACK__;
-+      u16     len __WLAN_ATTRIB_PACK__;
-+      u32     data __WLAN_ATTRIB_PACK__;
-+} 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 __WLAN_ATTRIB_PACK__;
-+      u32             msglen __WLAN_ATTRIB_PACK__;
-+      u8              devname[WLAN_DEVNAMELEN_MAX] __WLAN_ATTRIB_PACK__;
-+      wlanitem_u32_t  hosttime __WLAN_ATTRIB_PACK__;
-+      wlanitem_u32_t  mactime __WLAN_ATTRIB_PACK__;
-+      wlanitem_u32_t  channel __WLAN_ATTRIB_PACK__;
-+      wlanitem_u32_t  rssi __WLAN_ATTRIB_PACK__;
-+      wlanitem_u32_t  sq __WLAN_ATTRIB_PACK__;
-+      wlanitem_u32_t  signal __WLAN_ATTRIB_PACK__;
-+      wlanitem_u32_t  noise __WLAN_ATTRIB_PACK__;
-+      wlanitem_u32_t  rate __WLAN_ATTRIB_PACK__;
-+      wlanitem_u32_t  istx __WLAN_ATTRIB_PACK__;      /* tx? 0:no 1:yes */
-+      wlanitem_u32_t  frmlen __WLAN_ATTRIB_PACK__;
-+} 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
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/net/wireless/tiacx/wlan_mgmt.h bt_kernel/drivers/net/wireless/tiacx/wlan_mgmt.h
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/net/wireless/tiacx/wlan_mgmt.h      1970-01-01 02:00:00.000000000 +0200
-+++ bt_kernel/drivers/net/wireless/tiacx/wlan_mgmt.h   2005-09-28 23:54:23.938287000 +0300
-@@ -0,0 +1,579 @@
-+/***********************************************************************
-+** 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_ERP_INFO     42
-+#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_GENERIC      221
-+
-+#if 0
-+#define WLAN_EID_PWR_CONSTRAINT               32      /* 11H PowerConstraint */
-+#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 __WLAN_ATTRIB_PACK__;
-+      u8 len __WLAN_ATTRIB_PACK__;
-+} wlan_ie_t;
-+
-+/*-- Service Set Identity (SSID)  -----------------*/
-+typedef struct wlan_ie_ssid {
-+      u8 eid __WLAN_ATTRIB_PACK__;
-+      u8 len __WLAN_ATTRIB_PACK__;
-+      u8 ssid[1] __WLAN_ATTRIB_PACK__;        /* may be zero */
-+} wlan_ie_ssid_t;
-+
-+/*-- Supported Rates  -----------------------------*/
-+typedef struct wlan_ie_supp_rates {
-+      u8 eid __WLAN_ATTRIB_PACK__;
-+      u8 len __WLAN_ATTRIB_PACK__;
-+      u8 rates[1] __WLAN_ATTRIB_PACK__;       /* had better be at LEAST one! */
-+} wlan_ie_supp_rates_t;
-+
-+/*-- FH Parameter Set  ----------------------------*/
-+typedef struct wlan_ie_fh_parms {
-+      u8 eid __WLAN_ATTRIB_PACK__;
-+      u8 len __WLAN_ATTRIB_PACK__;
-+      u16 dwell __WLAN_ATTRIB_PACK__;
-+      u8 hopset __WLAN_ATTRIB_PACK__;
-+      u8 hoppattern __WLAN_ATTRIB_PACK__;
-+      u8 hopindex __WLAN_ATTRIB_PACK__;
-+} wlan_ie_fh_parms_t;
-+
-+/*-- DS Parameter Set  ----------------------------*/
-+typedef struct wlan_ie_ds_parms {
-+      u8 eid __WLAN_ATTRIB_PACK__;
-+      u8 len __WLAN_ATTRIB_PACK__;
-+      u8 curr_ch __WLAN_ATTRIB_PACK__;
-+} wlan_ie_ds_parms_t;
-+
-+/*-- CF Parameter Set  ----------------------------*/
-+typedef struct wlan_ie_cf_parms {
-+      u8 eid __WLAN_ATTRIB_PACK__;
-+      u8 len __WLAN_ATTRIB_PACK__;
-+      u8 cfp_cnt __WLAN_ATTRIB_PACK__;
-+      u8 cfp_period __WLAN_ATTRIB_PACK__;
-+      u16 cfp_maxdur __WLAN_ATTRIB_PACK__;
-+      u16 cfp_durremaining __WLAN_ATTRIB_PACK__;
-+} wlan_ie_cf_parms_t;
-+
-+/*-- TIM ------------------------------------------*/
-+typedef struct wlan_ie_tim {
-+      u8 eid __WLAN_ATTRIB_PACK__;
-+      u8 len __WLAN_ATTRIB_PACK__;
-+      u8 dtim_cnt __WLAN_ATTRIB_PACK__;
-+      u8 dtim_period __WLAN_ATTRIB_PACK__;
-+      u8 bitmap_ctl __WLAN_ATTRIB_PACK__;
-+      u8 virt_bm[1] __WLAN_ATTRIB_PACK__;
-+} wlan_ie_tim_t;
-+
-+/*-- IBSS Parameter Set ---------------------------*/
-+typedef struct wlan_ie_ibss_parms {
-+      u8 eid __WLAN_ATTRIB_PACK__;
-+      u8 len __WLAN_ATTRIB_PACK__;
-+      u16 atim_win __WLAN_ATTRIB_PACK__;
-+} wlan_ie_ibss_parms_t;
-+
-+/*-- Challenge Text  ------------------------------*/
-+typedef struct wlan_ie_challenge {
-+      u8 eid __WLAN_ATTRIB_PACK__;
-+      u8 len __WLAN_ATTRIB_PACK__;
-+      u8 challenge[1] __WLAN_ATTRIB_PACK__;
-+} wlan_ie_challenge_t;
-+
-+/*-- ERP (42) -------------------------------------*/
-+typedef struct wlan_ie_erp {
-+      u8 eid __WLAN_ATTRIB_PACK__;
-+      u8 len __WLAN_ATTRIB_PACK__;
-+      /* bit 0:Non ERP present
-+      **     1:Use Protection
-+      **     2:Barker Preamble mode
-+      **     3-7:reserved */
-+      u8 erp __WLAN_ATTRIB_PACK__;
-+} 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_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 __WLAN_ATTRIB_PACK__;
-+      u16     auth_seq __WLAN_ATTRIB_PACK__;
-+      u16     status __WLAN_ATTRIB_PACK__;
-+      wlan_ie_challenge_t challenge __WLAN_ATTRIB_PACK__;
-+} auth_frame_body_t;
-+
-+typedef struct assocresp_frame_body {
-+      u16     cap_info __WLAN_ATTRIB_PACK__;
-+      u16     status __WLAN_ATTRIB_PACK__;
-+      u16     aid __WLAN_ATTRIB_PACK__;
-+      wlan_ie_supp_rates_t rates __WLAN_ATTRIB_PACK__;
-+} assocresp_frame_body_t;
-+
-+typedef struct reassocreq_frame_body {
-+      u16     cap_info __WLAN_ATTRIB_PACK__;
-+      u16     listen_int __WLAN_ATTRIB_PACK__;
-+      u8      current_ap[ETH_ALEN] __WLAN_ATTRIB_PACK__;
-+      wlan_ie_ssid_t ssid __WLAN_ATTRIB_PACK__;
-+/* access to this one is disabled since ssid_t is variable length: */
-+     /* wlan_ie_supp_rates_t rates __WLAN_ATTRIB_PACK__; */
-+} reassocreq_frame_body_t;
-+
-+typedef struct reassocresp_frame_body {
-+      u16     cap_info __WLAN_ATTRIB_PACK__;
-+      u16     status __WLAN_ATTRIB_PACK__;
-+      u16     aid __WLAN_ATTRIB_PACK__;
-+      wlan_ie_supp_rates_t rates __WLAN_ATTRIB_PACK__;
-+} reassocresp_frame_body_t;
-+
-+typedef struct deauthen_frame_body {
-+      u16     reason __WLAN_ATTRIB_PACK__;
-+} deauthen_frame_body_t;
-+
-+typedef struct disassoc_frame_body {
-+      u16     reason __WLAN_ATTRIB_PACK__;
-+} disassoc_frame_body_t;
-+
-+typedef struct probereq_frame_body {
-+      wlan_ie_ssid_t ssid __WLAN_ATTRIB_PACK__;
-+      wlan_ie_supp_rates_t rates __WLAN_ATTRIB_PACK__;
-+} probereq_frame_body_t;
-+
-+typedef struct proberesp_frame_body {
-+      u8      timestamp[8] __WLAN_ATTRIB_PACK__;
-+      u16     beacon_int __WLAN_ATTRIB_PACK__;
-+      u16     cap_info __WLAN_ATTRIB_PACK__;
-+      wlan_ie_ssid_t ssid __WLAN_ATTRIB_PACK__;
-+/* access to these is disabled since ssid_t is variable length: */
-+     /* wlan_ie_supp_rates_t rates __WLAN_ATTRIB_PACK__; */
-+     /* fhps_t        fhps __WLAN_ATTRIB_PACK__; */
-+     /* dsps_t        dsps __WLAN_ATTRIB_PACK__; */
-+     /* cfps_t        cfps __WLAN_ATTRIB_PACK__; */
-+} 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;
-+}
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/pci/.gitignore bt_kernel/drivers/pci/.gitignore
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/pci/.gitignore      2005-10-20 09:23:05.000000000 +0300
-+++ bt_kernel/drivers/pci/.gitignore   1970-01-01 02:00:00.000000000 +0200
-@@ -1,4 +0,0 @@
--classlist.h
--devlist.h
--gen-devlist
--
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/ssi/omap-tsc2101.c bt_kernel/drivers/ssi/omap-tsc2101.c
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/ssi/omap-tsc2101.c  2005-10-30 17:44:18.415932786 +0200
-+++ bt_kernel/drivers/ssi/omap-tsc2101.c       2005-10-22 03:52:45.687256000 +0300
-@@ -36,10 +36,11 @@
- #include <asm/arch/hardware.h>
- #include <asm/hardware/tsc2101.h>
- #include <asm/arch/gpioexpander.h>
-+#include <asm/arch/gpio.h>
- #include "omap-tsc2101.h"
--#if CONFIG_ARCH_OMAP16XX
-+#if CONFIG_ARCH_OMAP1
- #include <../drivers/ssi/omap-uwire.h>
- #else
- #error "Unsupported configuration"
-@@ -66,27 +67,28 @@
-       if (count++ == 0) {
-               int ret = 0;
-               /* set the Mux to provide MCLK to TSC2101 */
--              if (machine_is_omap_h3()) {
-+              if (machine_is_omap_h3())
-                       ret = omap_cfg_reg(V5_1710_MCLK_ON);
--              } else {
--                      if (machine_is_omap_h2()) {
--                              ret = omap_cfg_reg(R10_1610_MCLK_ON);
-+              else if (machine_is_omap_h2())
-+                      ret = omap_cfg_reg(R10_1610_MCLK_ON);
-+              else if (machine_is_h6300 ())
-+                      ret = omap_cfg_reg(R10_1510_MCLK_ON);
-+
-+              if (!cpu_is_omap1510 ()) {
-+                      /* Get the MCLK */
-+                      tsc2101_mclk_ck = clk_get(NULL, "mclk");
-+                      if (NULL == tsc2101_mclk_ck) {
-+                              printk(KERN_ERR "Unable to get the clock MCLK!!!\n");;
-+                              ret = -EPERM;
-+                              goto done;
-                       }
--              }
--
--              /* Get the MCLK */
--              tsc2101_mclk_ck = clk_get(NULL, "mclk");
--              if (NULL == tsc2101_mclk_ck) {
--                      printk(KERN_ERR "Unable to get the clock MCLK!!!\n");;
--                      ret = -EPERM;
--                      goto done;
--              }
--              if (clk_set_rate(tsc2101_mclk_ck, 12000000)) {
--                      printk(KERN_ERR "Unable to set rate to the MCLK!!!\n");;
--                      ret = -EPERM;
--                      goto done;
--              }
--              clk_enable(tsc2101_mclk_ck);
-+                      if (clk_set_rate(tsc2101_mclk_ck, 12000000)) {
-+                              printk(KERN_ERR "Unable to set rate to the MCLK!!!\n");;
-+                              ret = -EPERM;
-+                              goto done;
-+                      }
-+                      clk_enable(tsc2101_mclk_ck);
-+              } /* if (!cpu_is_omap1510 ()) */
-               ret = omap_tsc2101_configure();
-@@ -116,10 +118,16 @@
-                       }
-               }
--              /* Release the MCLK */
--              clk_disable(tsc2101_mclk_ck);
--              clk_put(tsc2101_mclk_ck);
--              tsc2101_mclk_ck = NULL;
-+              if (!cpu_is_omap1510 ()) {
-+                      /* Release the MCLK */
-+                      clk_disable(tsc2101_mclk_ck);
-+                      clk_put(tsc2101_mclk_ck);
-+                      tsc2101_mclk_ck = NULL;
-+              }
-+
-+#if defined(CONFIG_MACH_OMAP_H6300)
-+              omap_free_gpio(8);
-+#endif
-               module_put(THIS_MODULE);
-       }
-@@ -150,7 +158,10 @@
-                       return;
-               }
-       }
--      if (machine_is_omap_h3()) {
-+      if (machine_is_omap_h3() || machine_is_h6300 ()) {
-+
-+              if (machine_is_h6300 ())
-+                      omap_set_gpio_dataout (8, 0);
-               ret =
-                   omap_uwire_data_transfer(0, ((page << 11) | (address << 5)),
-@@ -159,6 +170,8 @@
-                       printk(KERN_ERR
-                              "uwire-write returned error for address %x\n",
-                              address);
-+              if (machine_is_h6300 ())
-+                      omap_set_gpio_dataout (8, 1);
-                       return;
-               }
-               ret = omap_uwire_data_transfer(0, data, 16, 0, NULL, 0);
-@@ -166,10 +179,14 @@
-                       printk(KERN_ERR
-                              "uwire-write returned error for address %x\n",
-                              address);
-+                      if (machine_is_h6300 ())
-+                              omap_set_gpio_dataout (8, 1);
-                       return;
-               }
--      }
-+              if (machine_is_h6300 ())
-+                      omap_set_gpio_dataout (8, 1);
-+      }
- }
- void omap_tsc2101_reads(int page, u8 startaddress, u16 * data, int numregs)
-@@ -178,9 +195,13 @@
-       if (machine_is_omap_h2()) {
-               cs = 1;
-       }
--      if (machine_is_omap_h3()) {
-+      if (machine_is_omap_h3() || machine_is_h6300 ()) {
-               cs = 0;
-       }
-+
-+      if (machine_is_h6300 ())
-+              omap_set_gpio_dataout(8, 0);
-+
-       (void)omap_uwire_data_transfer(cs, (0x8000 | (page << 11)
-                                           | (startaddress << 5)),
-                                      16, 0, NULL, 1);
-@@ -188,6 +209,9 @@
-               omap_uwire_data_transfer(cs, 0, 0, 16, data, 1);
-       }
-       omap_uwire_data_transfer(cs, 0, 0, 16, data, 0);
-+
-+      if (machine_is_h6300 ())
-+              omap_set_gpio_dataout(8, 1);
- }
- u16 omap_tsc2101_read(int page, u8 address)
-@@ -228,9 +252,24 @@
-               omap_cfg_reg(N14_1610_UWIRE_CS0);
-               omap_uwire_configure_mode(0, uwire_flags);
-       }
-+      if (machine_is_h6300()) {
-+              uwire_flags = UWIRE_READ_RISING_EDGE | UWIRE_WRITE_RISING_EDGE;
-+              omap_cfg_reg(N14_1510_UWIRE_CS0);
-+              omap_uwire_configure_mode(0, uwire_flags);
-+
-+              omap_request_gpio(8);
-+              omap_set_gpio_dataout(8, 0);
-+              omap_set_gpio_direction (8, 0);
-+      }
-       /* Configure MCLK enable */
--      omap_writel(omap_readl(PU_PD_SEL_2) | (1 << 22), PU_PD_SEL_2);  
-+      if (cpu_is_omap16xx() || cpu_is_omap1710())
-+              omap_writel(omap_readl(PU_PD_SEL_2) | (1 << 22), PU_PD_SEL_2);  
-+      if (machine_is_h6300()) {
-+              omap_cfg_reg(V19_1510_UWIRE_SCLK);
-+              omap_cfg_reg(W21_1510_UWIRE_SDO);
-+              omap_cfg_reg(U18_1510_UWIRE_SDI);
-+      }
-       return 0;
- }
-@@ -243,5 +282,5 @@
- MODULE_AUTHOR("Texas Instruments");
- MODULE_DESCRIPTION
--    ("Glue audio driver for the TI OMAP1610/OMAP1710 TSC2101 codec.");
-+    ("Glue audio driver for the TI OMAP1510/1610/OMAP1710 TSC2101 codec.");
- MODULE_LICENSE("GPL");
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/ssi/omap-uwire.c bt_kernel/drivers/ssi/omap-uwire.c
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/ssi/omap-uwire.c    2005-10-30 17:44:18.435929603 +0200
-+++ bt_kernel/drivers/ssi/omap-uwire.c 2005-08-12 13:46:22.016114000 +0300
-@@ -212,6 +212,10 @@
-               omap_cfg_reg(N14_1610_UWIRE_CS0);
-               omap_cfg_reg(P15_1610_UWIRE_CS3);
-       }
-+      if (machine_is_h6300 ()) {
-+              omap_cfg_reg(N14_1510_UWIRE_CS0);
-+              omap_cfg_reg(P15_1510_UWIRE_CS3);
-+      }
-       if (machine_is_omap_perseus2()) {
-               /* configure pins: MPU_UW_nSCS1, MPU_UW_SDO, MPU_UW_SCLK */
-               int val = omap_readl(OMAP730_IO_CONF_9) & ~0x00EEE000;
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/telephony/Kconfig bt_kernel/drivers/telephony/Kconfig
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/telephony/Kconfig   2005-10-20 09:23:05.000000000 +0300
-+++ bt_kernel/drivers/telephony/Kconfig        2005-10-06 02:34:39.057478000 +0300
-@@ -41,7 +41,18 @@
-       help
-         Say Y here to configure in PCMCIA service support for the Quicknet
-         cards manufactured by Quicknet Technologies, Inc.  This changes the
--        card initialization code to work with the card manager daemon.
-+        card initialization code to work with the card manager daemon.          
-+
-+config GSM_H6300
-+      tristate "H6300 P5186 GSM/GPRS DRIVER"
-+      depends on PHONE && I2C && PCA9535
-+      help
-+        Bluetooth H6300 P5186 gsm/gprs driver.
-+        This driver provides the firmware loading mechanism for the P5185
-+        gsm/gprs hardware in iPAQ h6300.
-+
-+        Say Y here to compile support for P5186 gsm/gprs devices into the
-+        kernel or say M to compile it as module (h6300_gsm).
- endmenu
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/telephony/Makefile bt_kernel/drivers/telephony/Makefile
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/telephony/Makefile  2005-10-20 09:23:05.000000000 +0300
-+++ bt_kernel/drivers/telephony/Makefile       2005-10-06 02:34:39.057478000 +0300
-@@ -2,6 +2,7 @@
- # Makefile for drivers/telephony
- #
--obj-$(CONFIG_PHONE) += phonedev.o
--obj-$(CONFIG_PHONE_IXJ) += ixj.o
--obj-$(CONFIG_PHONE_IXJ_PCMCIA) += ixj_pcmcia.o
-+obj-$(CONFIG_PHONE)                           += phonedev.o
-+obj-$(CONFIG_PHONE_IXJ)                       += ixj.o
-+obj-$(CONFIG_PHONE_IXJ_PCMCIA)        += ixj_pcmcia.o
-+obj-$(CONFIG_GSM_H6300)                       += omap/
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/telephony/omap/h6300_gsm_led.c bt_kernel/drivers/telephony/omap/h6300_gsm_led.c
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/telephony/omap/h6300_gsm_led.c      1970-01-01 02:00:00.000000000 +0200
-+++ bt_kernel/drivers/telephony/omap/h6300_gsm_led.c   2005-10-06 02:34:39.057478000 +0300
-@@ -0,0 +1,40 @@
-+/* 
-+ * GSM interface driver helper for controlling bluetooth leds available in iPAQ h6300.
-+ * 
-+ * Copyright (C) 2005 Mika Laitio  <lamikr@cc.jyu.fi>
-+ * 
-+ * This program is free software; you can 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/delay.h>
-+#include <linux/device.h>
-+
-+#include <asm/hardware.h>
-+#include <asm/arch/gpio.h>
-+
-+/* 
-+ * Low level access for disabling h6300 gsm led.
-+ *
-+ * TODO: implement for h6300 
-+ */
-+void h6300_clear_gsm_led(int led_num)
-+{
-+      printk(KERN_NOTICE "h6300_gsm_led.c h6300_clear_gsm_led() done\n");
-+      //hx4700_set_led(led_num, 0, 16);
-+}
-+EXPORT_SYMBOL(h6300_clear_gsm_led);
-+
-+/* 
-+ * Low level access for setting up the gsm led.
-+ *
-+ * TODO: implement for h6300 
-+ */
-+void h6300_set_gsm_led(int led_num, int duty_time, int cycle_time)
-+{
-+      printk(KERN_NOTICE "h6300_gsm_led.c h6300_set_gsm_led() done\n");
-+}
-+EXPORT_SYMBOL(h6300_set_gsm_led);
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/telephony/omap/h6300_gsm_led.h bt_kernel/drivers/telephony/omap/h6300_gsm_led.h
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/telephony/omap/h6300_gsm_led.h      1970-01-01 02:00:00.000000000 +0200
-+++ bt_kernel/drivers/telephony/omap/h6300_gsm_led.h   2005-10-06 02:34:39.057478000 +0300
-@@ -0,0 +1,10 @@
-+#ifndef H6300_GSM_LED_H_
-+#define H6300_GSM_LED_H_
-+
-+#define INDEX_GSM_LED 1
-+
-+void h6300_clear_gsm_led(int led_num);
-+void h6300_set_gsm_led(int led_num, int duty_time, int cycle_time);
-+
-+
-+#endif /*H6300_GSM_LED_H_*/
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/telephony/omap/h6300_gsm_p5186.c bt_kernel/drivers/telephony/omap/h6300_gsm_p5186.c
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/telephony/omap/h6300_gsm_p5186.c    1970-01-01 02:00:00.000000000 +0200
-+++ bt_kernel/drivers/telephony/omap/h6300_gsm_p5186.c 2005-10-20 20:57:07.074687000 +0300
-@@ -0,0 +1,171 @@
-+/* 
-+ * Wavecom P5186 GPRS and GSM module driver for iPAQ h6300.
-+ * 
-+ * Copyright (C) 2005 Mika Laitio <lamikr@cc.jyu.fi>
-+ * 
-+ * This program is free software; you can 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/delay.h>
-+#include <linux/device.h>
-+
-+#include <asm/hardware.h>
-+#include <asm/arch/gpio.h>
-+
-+#include <asm/arch/pca9535.h>
-+#include <asm/arch/h6300_uart_info.h>
-+#include "h6300_gsm_led.h"
-+
-+static void
-+h6300_gsm_configure(struct uart_omap_port *up, int enable)
-+{
-+      printk(KERN_NOTICE "h6300_gsm_p5186.c h6300_gsm_configure() started, enable = %d\n", enable);
-+      
-+      // printk( KERN_NOTICE "h6300 configure bluetooth: %d\n", enable );
-+      if (enable == 0) {
-+              pca9535_gpio_write(GPIO_I2C_GPRS_RESET, GPIO_VALUE_OFF);        // turn off gpio
-+              mdelay(5);
-+              h6300_clear_gsm_led(INDEX_GSM_LED);
-+      }
-+      else if (enable == 1) {
-+              pca9535_gpio_write(GPIO_I2C_GPRS_RESET, GPIO_VALUE_ON); // turn on gpio
-+              mdelay(5);                              
-+      }
-+      else if (enable == 2) {
-+              h6300_set_gsm_led(INDEX_GSM_LED, 16, 16);
-+      }
-+      printk(KERN_NOTICE "h6300_gsm_p5186.c h6300_gsm_configure() done\n");
-+}
-+
-+static void
-+h6300_gsm_set_txrx(struct uart_omap_port *up, int txrx)
-+{
-+      printk(KERN_NOTICE "h6300_gsm_p5186.c h6300_gsm_set_txrx(), txrx = %d done\n", txrx);
-+      /* do nothing */
-+}
-+
-+static int
-+h6300_gsm_get_txrx(struct uart_omap_port *up)
-+{
-+      printk(KERN_NOTICE "h6300_gsm_p5186.c h6300_gsm_get_txrx() done\n");
-+      /* do nothing */
-+      return 0;
-+}
-+
-+static int
-+h6300_gsm_probe(struct device *dev)
-+{
-+      int     ii;
-+      int     curVal;
-+      
-+      struct h6300_uart_funcs *funcs = (struct h6300_uart_funcs *)dev->platform_data;
-+/*
-+      printk(KERN_NOTICE "h6300_gsm_p5186.c h6300_gsm_probe() started\n");    
-+      for (ii = 0; ii < 8; ii++)
-+      {
-+              curVal  = pca9535_gpio_read(ii);
-+              printk(KERN_NOTICE "I2C[%d] = %d ", ii, curVal);
-+      }
-+      for (ii = 10; ii < 18; ii++)
-+      {
-+              curVal  = pca9535_gpio_read(ii);
-+              printk(KERN_NOTICE "I2C[%d] = %d ", ii, curVal);
-+      }
-+      printk(KERN_NOTICE "\nfirst check done\n");
-+*/
-+      pca9535_gpio_direction(GPIO_I2C_GPRS_RESET, GPIO_DIR_OUTPUT);   // set gpio direction to be output
-+      pca9535_gpio_write(GPIO_I2C_GPRS_RESET, GPIO_VALUE_ON); // turn on gpio
-+      mdelay(200);
-+      
-+      pca9535_gpio_direction(GPIO_I2C_MIC_OP_EN, GPIO_DIR_OUTPUT);    // set gpio direction to be output
-+      pca9535_gpio_write(GPIO_I2C_MIC_OP_EN, GPIO_VALUE_ON);  // turn on gpio
-+      mdelay(200);
-+
-+      pca9535_gpio_direction(GPIO_I2C_SPK_OP_PD, GPIO_DIR_OUTPUT);    // set gpio direction to be output
-+      pca9535_gpio_write(GPIO_I2C_SPK_OP_PD, GPIO_VALUE_ON);  // pd = pulldown?, normal off = on
-+
-+      mdelay(200);
-+      
-+      //pca9535_gpio_direction(
-+      /* configure bluetooth UART */
-+      //h6300_gpio_mode(GPIO_NR_H6300_BT_RXD_MD);
-+      //h6300_gpio_mode(GPIO_NR_H6300_BT_TXD_MD);
-+      //h6300_gpio_mode(GPIO_NR_H6300_BT_UART_CTS_MD);
-+      //h6300_gpio_mode(GPIO_NR_H6300_BT_UART_RTS_MD);
-+
-+      funcs->configure        = h6300_gsm_configure;
-+      funcs->set_txrx         = h6300_gsm_set_txrx;
-+      funcs->get_txrx         = h6300_gsm_get_txrx;
-+
-+      /* Make sure the LED is off */
-+      h6300_clear_gsm_led(INDEX_GSM_LED);     
-+/*    
-+      for (ii = 0; ii < 8; ii++)
-+      {
-+              curVal  = pca9535_gpio_read(ii);
-+              printk(KERN_NOTICE "I2C[%d] = %d ", ii, curVal);
-+      }
-+      for (ii = 10; ii < 18; ii++)
-+      {
-+              curVal  = pca9535_gpio_read(ii);
-+              printk(KERN_NOTICE "I2C[%d] = %d ", ii, curVal);
-+      }
-+*/    
-+      printk(KERN_NOTICE "\nh6300_gsm_p5186.c h6300_gsm_probe() done\n");
-+              
-+      return 0;
-+}
-+
-+static int
-+h6300_gsm_remove(struct device *dev)
-+{
-+      struct h6300_uart_funcs *funcs = (struct h6300_uart_funcs *)dev->platform_data;
-+      
-+      printk(KERN_NOTICE "h6300_gsm_p5186.c h6300_gsm_remove() started\n");   
-+
-+      pca9535_gpio_write(GPIO_I2C_GPRS_RESET, 0);     // turn off gpio
-+      
-+      funcs->configure        = NULL;
-+      funcs->set_txrx         = NULL;
-+      funcs->get_txrx         = NULL;
-+
-+      /* Make sure the LED is off */
-+      h6300_clear_gsm_led(INDEX_GSM_LED);
-+      
-+      printk(KERN_NOTICE "h6300_gsm_p5186.c, h6300_gsm_remove() done\n");
-+
-+      return 0;
-+}
-+
-+static struct device_driver gsm_driver = {
-+      .name     = "h6300_gsm",
-+      .bus      = &platform_bus_type,
-+      .probe    = h6300_gsm_probe,
-+      .remove   = h6300_gsm_remove,
-+};
-+
-+static int __init
-+h6300_gsm_init(void)
-+{
-+      printk(KERN_NOTICE "h6300 GSM Driver init()\n");
-+      return driver_register(&gsm_driver);
-+}
-+
-+static void __exit
-+h6300_gsm_exit(void)
-+{
-+      printk(KERN_NOTICE "h6300 GSM Driver exit()\n");
-+      driver_unregister(&gsm_driver);
-+}
-+
-+module_init(h6300_gsm_init);
-+module_exit(h6300_gsm_exit);
-+
-+MODULE_AUTHOR("Mika Laitio, <lamikr@cc.jyu.fi>");
-+MODULE_DESCRIPTION("iPAQ h6300 Wavecom P5186 GPRS and GSM module driver.");
-+MODULE_LICENSE("GPL");
-+
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/telephony/omap/Makefile bt_kernel/drivers/telephony/omap/Makefile
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/telephony/omap/Makefile     1970-01-01 02:00:00.000000000 +0200
-+++ bt_kernel/drivers/telephony/omap/Makefile  2005-10-06 02:34:39.057478000 +0300
-@@ -0,0 +1,6 @@
-+#
-+# Makefile for the Linux iPAQ H6300 BRF6100 Bluetooth device drivers.
-+#
-+
-+h6300_gsm-objs                        := h6300_gsm_led.o h6300_gsm_p5186.o
-+obj-$(CONFIG_GSM_H6300)       += h6300_gsm.o
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/usb/gadget/omap_udc.c bt_kernel/drivers/usb/gadget/omap_udc.c
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/usb/gadget/omap_udc.c       2005-10-30 17:44:18.495920054 +0200
-+++ bt_kernel/drivers/usb/gadget/omap_udc.c    2005-10-30 16:32:39.609796000 +0200
-@@ -622,17 +622,24 @@
-                       || (cpu_is_omap15xx() && length < ep->maxpacket)) {
-               txdma_ctrl = UDC_TXN_EOT | length;
-               omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S8,
--                              length, 1, sync_mode);
-+                              length, 1, sync_mode, 0, 0);
-       } else {
-               length = min(length / ep->maxpacket,
-                               (unsigned) UDC_TXN_TSC + 1);
-               txdma_ctrl = length;
--              omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S16,
--                              ep->ep.maxpacket >> 1, length, sync_mode);
-+              if (machine_is_h6300())
-+                      omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S8,
-+                                      ep->ep.maxpacket, length, sync_mode,
-+                                      0, 0);
-+              else
-+                      omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S16,
-+                                      ep->ep.maxpacket >> 1, length, sync_mode,
-+                                      0, 0);
-               length *= ep->maxpacket;
-       }
-       omap_set_dma_src_params(ep->lch, OMAP_DMA_PORT_EMIFF,
--              OMAP_DMA_AMODE_POST_INC, req->req.dma + req->req.actual);
-+              OMAP_DMA_AMODE_POST_INC, req->req.dma + req->req.actual,
-+              0, 0);
-       omap_start_dma(ep->lch);
-       ep->dma_counter = dma_csac(ep->lch);
-@@ -675,11 +682,19 @@
-       packets = (req->req.length - req->req.actual) / ep->ep.maxpacket;
-       packets = min(packets, (unsigned)UDC_RXN_TC + 1);
-       req->dma_bytes = packets * ep->ep.maxpacket;
--      omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S16,
--                      ep->ep.maxpacket >> 1, packets,
--                      OMAP_DMA_SYNC_ELEMENT);
-+      if (machine_is_h6300())
-+              omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S8,
-+                              ep->ep.maxpacket, packets,
-+                              OMAP_DMA_SYNC_ELEMENT,
-+                              0, 0);
-+      else
-+              omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S16,
-+                              ep->ep.maxpacket >> 1, packets,
-+                              OMAP_DMA_SYNC_ELEMENT,
-+                              0, 0);
-       omap_set_dma_dest_params(ep->lch, OMAP_DMA_PORT_EMIFF,
--              OMAP_DMA_AMODE_POST_INC, req->req.dma + req->req.actual);
-+              OMAP_DMA_AMODE_POST_INC, req->req.dma + req->req.actual,
-+              0, 0);
-       ep->dma_counter = DMA_DEST_LAST(ep->lch);
-       UDC_RXDMA_REG(ep->dma_channel) = UDC_RXN_STOP | (packets - 1);
-@@ -822,7 +837,8 @@
-                       omap_set_dma_dest_params(ep->lch,
-                               OMAP_DMA_PORT_TIPB,
-                               OMAP_DMA_AMODE_CONSTANT,
--                              (unsigned long) io_v2p((u32)&UDC_DATA_DMA_REG));
-+                              (unsigned long) io_v2p((u32)&UDC_DATA_DMA_REG),
-+                              0, 0);
-               }
-       } else {
-               status = omap_request_dma(OMAP_DMA_USB_W2FC_RX0 - 1 + channel,
-@@ -833,7 +849,8 @@
-                       omap_set_dma_src_params(ep->lch,
-                               OMAP_DMA_PORT_TIPB,
-                               OMAP_DMA_AMODE_CONSTANT,
--                              (unsigned long) io_v2p((u32)&UDC_DATA_DMA_REG));
-+                              (unsigned long) io_v2p((u32)&UDC_DATA_DMA_REG),
-+                              0, 0);
-                       /* EMIFF */
-                       omap_set_dma_dest_burst_mode(ep->lch,
-                                               OMAP_DMA_DATA_BURST_4);
-@@ -2103,7 +2120,7 @@
-       /* boards that don't have VBUS sensing can't autogate 48MHz;
-        * can't enter deep sleep while a gadget driver is active.
-        */
--      if (machine_is_omap_innovator() || machine_is_omap_osk())
-+      if (machine_is_omap_innovator() || machine_is_omap_osk() || machine_is_h6300())
-               omap_vbus_session(&udc->gadget, 1);
- done:
-@@ -2121,7 +2138,7 @@
-       if (!driver || driver != udc->driver)
-               return -EINVAL;
--      if (machine_is_omap_innovator() || machine_is_omap_osk())
-+      if (machine_is_omap_innovator() || machine_is_omap_osk() || machine_is_h6300())
-               omap_vbus_session(&udc->gadget, 0);
-       if (udc->transceiver)
-@@ -2729,7 +2746,7 @@
-               hmc = HMC_1510;
-               type = "(unknown)";
--              if (machine_is_omap_innovator()) {
-+              if (machine_is_omap_innovator() || machine_is_h6300()) {
-                       /* just set up software VBUS detect, and then
-                        * later rig it so we always report VBUS.
-                        * FIXME without really sensing VBUS, we can't
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/video/logo/.gitignore bt_kernel/drivers/video/logo/.gitignore
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/video/logo/.gitignore       2005-10-20 09:23:05.000000000 +0300
-+++ bt_kernel/drivers/video/logo/.gitignore    1970-01-01 02:00:00.000000000 +0200
-@@ -1,7 +0,0 @@
--#
--# Generated files
--#
--*_mono.c
--*_vga16.c
--*_clut224.c
--*_gray256.c
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/video/omap/lcd_h6300.c bt_kernel/drivers/video/omap/lcd_h6300.c
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/video/omap/lcd_h6300.c      1970-01-01 02:00:00.000000000 +0200
-+++ bt_kernel/drivers/video/omap/lcd_h6300.c   2005-10-30 16:32:39.609796000 +0200
-@@ -0,0 +1,107 @@
-+/*
-+ * File: drivers/video/omap_new/lcd-h6300.c
-+ *
-+ * LCD panel support for the TI OMAP1510 Innovator board
-+ *
-+ * Copyright (C) 2004 Nokia Corporation
-+ * Author: Imre Deak <imre.deak@nokia.com>
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License as published by the
-+ * Free Software Foundation; either version 2 of the License, or (at your
-+ * option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful, but
-+ * WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+ * General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License along
-+ * with this program; if not, write to the Free Software Foundation, Inc.,
-+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-+ */
-+
-+#include <linux/module.h>
-+#include <asm/io.h>
-+
-+#include <asm/hardware/clock.h>
-+#include <asm/arch/omapfb.h>
-+
-+/* #define OMAPFB_DBG 1 */
-+
-+#include "debug.h"
-+
-+//static struct clk *h6300_lcd_ck;
-+
-+static int h6300_panel_init(struct omapfb_device *fbdev)
-+{
-+      DBGENTER(1);
-+/*
-+      if ((h6300_lcd_ck = clk_get (NULL, "lcd_ck")) == NULL) {
-+              printk(KERN_ERR "Unable to get the clock LCD_CK!!!\n");
-+              return -EPERM;
-+      } clk_enable (h6300_lcd_ck);
-+*/
-+      DBGLEAVE(1);
-+      printk(KERN_INFO "lcd_h6300.c: h6300_panel_init() done\n");
-+      return 0;
-+}
-+
-+static void h6300_panel_cleanup(void)
-+{
-+      DBGENTER(1);
-+/*
-+      if (h6300_lcd_ck) {
-+              clk_disable (h6300_lcd_ck);
-+              clk_put (h6300_lcd_ck);
-+              h6300_lcd_ck = NULL;
-+      }
-+*/
-+      DBGLEAVE(1);
-+      printk(KERN_INFO "lcd_h6300.c: h6300_panel_cleanup() done\n");
-+}
-+
-+static int h6300_panel_enable(void)
-+{
-+      DBGENTER(1);
-+      DBGLEAVE(1);
-+      printk(KERN_INFO "lcd_h6300.c: h6300_panel_enable() done\n");
-+      return 0;
-+}
-+
-+static void h6300_panel_disable(void)
-+{
-+      DBGENTER(1);
-+      DBGLEAVE(1);
-+      printk(KERN_INFO "lcd_h6300.c: h6300_panel_disable() done\n");  
-+}
-+
-+static unsigned long h6300_panel_get_caps(void)
-+{
-+      printk(KERN_INFO "lcd_h6300.c: h6300_panel_get_caps() called\n");       
-+      return 0;
-+}
-+
-+struct lcd_panel h6300_panel = {
-+      .name           = "h6300",
-+      .config         = OMAP_LCDC_PANEL_TFT,
-+
-+      .bpp            = 16,
-+      .data_lines     = 16,
-+      .x_res          = 240,
-+      .y_res          = 320,
-+      .pixel_clock    = 21000,
-+      .hsw            = 12,
-+      .hfp            = 10,
-+      .hbp            = 10,
-+      .vsw            = 3,
-+      .vfp            = 10,
-+      .vbp            = 3,
-+      .pcd            = 0,
-+
-+      .init           = h6300_panel_init,
-+      .cleanup        = h6300_panel_cleanup,
-+      .enable         = h6300_panel_enable,
-+      .disable        = h6300_panel_disable,
-+      .get_caps       = h6300_panel_get_caps,
-+};
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/video/omap/Makefile bt_kernel/drivers/video/omap/Makefile
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/video/omap/Makefile 2005-10-30 17:44:18.730882654 +0200
-+++ bt_kernel/drivers/video/omap/Makefile      2005-10-22 03:52:45.687256000 +0300
-@@ -21,6 +21,7 @@
- objs-$(CONFIG_ARCH_OMAP15XX)$(CONFIG_MACH_OMAP_INNOVATOR) += lcd_inn1510.o
- objs-y$(CONFIG_MACH_OMAP_OSK) += lcd_osk.o
- objs-y$(CONFIG_MACH_OMAP_PERSEUS2) += lcd_p2.o
-+objs-$(CONFIG_ARCH_OMAP15XX)$(CONFIG_MACH_OMAP_H6300) += lcd_h6300.o
- omapfb-objs := $(objs-yy)
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/video/omap/omapfb.h bt_kernel/drivers/video/omap/omapfb.h
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/video/omap/omapfb.h 1970-01-01 02:00:00.000000000 +0200
-+++ bt_kernel/drivers/video/omap/omapfb.h      2005-08-12 13:46:22.016114000 +0300
-@@ -0,0 +1,325 @@
-+/*
-+ * File: drivers/video/omap_new/omapfb.c
-+ *
-+ * Framebuffer driver for TI OMAP boards
-+ *
-+ * Copyright (C) 2004 Nokia Corporation
-+ * Author: Imre Deak <imre.deak@nokia.com>
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License as published by the
-+ * Free Software Foundation; either version 2 of the License, or (at your
-+ * option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful, but
-+ * WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+ * General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License along
-+ * with this program; if not, write to the Free Software Foundation, Inc.,
-+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-+ */
-+
-+#ifndef __OMAPFB_H
-+#define __OMAPFB_H
-+
-+/* IOCTL commands. */
-+
-+#define OMAP_IOW(num, dtype)  _IOW('O', num, dtype)
-+#define OMAP_IOR(num, dtype)  _IOR('O', num, dtype)
-+#define OMAP_IOWR(num, dtype) _IOWR('O', num, dtype)
-+#define OMAP_IO(num)          _IO('O', num)
-+
-+#define OMAPFB_FILLRECT               OMAP_IOW(0, struct fb_fillrect)
-+#define OMAPFB_COPYAREA               OMAP_IOW(1, struct fb_copyarea)
-+#define OMAPFB_IMAGEBLIT      OMAP_IOW(2, struct fb_image)
-+
-+#define OMAPFB_TRANSPARENT_BLIT       OMAP_IOW(30, struct fb_image)
-+#define OMAPFB_MIRROR         OMAP_IOW(31, int)
-+#define OMAPFB_SCALE          OMAP_IOW(32, struct fb_scale)
-+#define OMAPFB_SELECT_VIS_FRAME       OMAP_IOW(33, int)
-+#define OMAPFB_SELECT_SRC_FRAME OMAP_IOW(34, int)
-+#define OMAPFB_SELECT_DST_FRAME       OMAP_IOW(35, int)
-+#define OMAPFB_GET_FRAME_OFFSET       OMAP_IOWR(36, struct fb_frame_offset)
-+#define OMAPFB_SYNC_GFX               OMAP_IO(37)
-+#define OMAPFB_VSYNC          OMAP_IO(38)
-+#define OMAPFB_LATE_ACTIVATE  OMAP_IO(39)
-+#define OMAPFB_SET_UPDATE_MODE        OMAP_IOW(40, enum fb_update_mode)
-+#define OMAPFB_UPDATE_WINDOW  OMAP_IOW(41, struct fb_update_window)
-+#define OMAPFB_GET_CAPS               OMAP_IOR(42, unsigned long)
-+#define OMAPFB_GET_UPDATE_MODE        OMAP_IOW(43, enum fb_update_mode)
-+#define OMAPFB_GET_GFX_STATUS OMAP_IOR(44, unsigned long)
-+
-+#define FBCAPS_GENERIC_MASK   0x00000fff
-+#define FBCAPS_LCDC_MASK      0x00fff000
-+#define FBCAPS_PANEL_MASK     0xff000000
-+
-+#define FBCAPS_MANUAL_UPDATE  0x00001000
-+#define FBCAPS_SET_BACKLIGHT  0x01000000
-+
-+enum omapfb_gfx_status {
-+      OMAPFB_GFX_STATUS_OK    = 0,
-+      OMAPFB_GFX_STATUS_CHANGED
-+};
-+
-+#define OMAPFB_UPDATE_FAILED  0x01
-+#define OMAPFB_FILLRECT_FAILED        0x02
-+#define OMAPFB_COPYAREA_FAILED        0x04
-+#define OMAPFB_IMGBLIT_FAILED 0x08
-+
-+struct fb_copyarea_ext {
-+      __u32 dx;
-+      __u32 dy;
-+      __u32 width;
-+      __u32 height;
-+      __u32 sx;
-+      __u32 sy;
-+      __u32 trans_color;
-+      __u32 rev_dir;
-+};
-+
-+struct fb_scale {
-+      unsigned int xscale, yscale;
-+};
-+
-+struct fb_frame_offset {
-+      unsigned int idx;
-+      unsigned long offset;
-+};
-+
-+struct fb_update_window {
-+      unsigned int x, y;
-+      unsigned int width, height;
-+};
-+
-+enum fb_update_mode {
-+      FB_UPDATE_DISABLED = 0,
-+      FB_AUTO_UPDATE,
-+      FB_MANUAL_UPDATE
-+};
-+
-+#ifdef __KERNEL__
-+
-+#include <linux/completion.h>
-+#include <linux/interrupt.h>
-+#include <linux/fb.h>
-+
-+#define OMAPFB_DEVICE "omapfb"
-+#define OMAPFB_DRIVER "omapfb"
-+
-+#define PRNERR(fmt, args...)  printk(KERN_ERR OMAPFB_DRIVER ": " fmt, ## args)
-+
-+#define GFX_FIFO_SIZE 2
-+
-+#define LCD_PANEL_TFT 0x01
-+
-+#define OMAP_LCDC_INV_VSYNC             0x01
-+#define OMAP_LCDC_INV_HSYNC             0x02
-+#define OMAP_LCDC_INV_PIX_CLOCK         0x04
-+#define OMAP_LCDC_INV_OUTPUT_EN         0x08
-+#define OMAP_LCDC_HSVS_RISING_EDGE      0x10
-+#define OMAP_LCDC_HSVS_OPPOSITE         0x20
-+
-+struct lcdc_video_mode {
-+      u16     x_res, y_res;
-+      u32     pixel_clock;    /* In kHz */
-+      int     bpp;
-+      u8      hsw;            /* Horizontal synchronization pulse width */
-+      u8      hfp;            /* Horizontal front porch */
-+      u8      hbp;            /* Horizontal back porch */
-+      u8      vsw;            /* Vertical synchronization pulse width */
-+      u8      vfp;            /* Vertical front porch */
-+      u8      vbp;            /* Vertical back porch */
-+      u8      acb;            /* ac-bias pin frequency */
-+      u8      pcd;            /* Pixel clock divider (this will change) */
-+      u8  flags;
-+};
-+
-+struct lcd_panel {
-+      const char *name;
-+      int  config;
-+      int  signals;
-+      struct lcdc_video_mode *video_mode;
-+
-+      int  (*init)    (struct lcd_panel *panel);
-+      void (*cleanup) (struct lcd_panel *panel);
-+      int  (*enable)  (struct lcd_panel *panel);
-+      void (*disable) (struct lcd_panel *panel);
-+      unsigned long (*get_caps)(struct lcd_panel *panel);
-+      int           (*set_bklight_level)(struct lcd_panel *panel,
-+                                         unsigned int level);
-+      unsigned int  (*get_bklight_level)(struct lcd_panel *panel);
-+      unsigned int  (*get_bklight_max)  (struct lcd_panel *panel);
-+};
-+
-+struct omapfb_device;
-+
-+struct lcd_ctrl {
-+      const char      *name;
-+      void            *data;
-+      int             (*init)           (struct omapfb_device *fbdev);
-+      void            (*cleanup)        (struct omapfb_device *fbdev);
-+      void            (*get_mem_layout) (struct omapfb_device *fbdev,
-+                                         unsigned long *size,
-+                                         unsigned long *fb_org);
-+      unsigned long   (*get_caps)       (struct omapfb_device *fbdev);
-+      int             (*set_update_mode)(struct omapfb_device *fbdev,
-+                                         enum fb_update_mode mode);
-+      enum fb_update_mode (*get_update_mode)(struct omapfb_device *fbdev);
-+      int             (*update_window)  (struct omapfb_device *fbdev,
-+                                         struct fb_update_window *win);
-+      void            (*suspend)        (struct omapfb_device *fbdev);
-+      void            (*resume)         (struct omapfb_device *fbdev);
-+      void            (*change_mode)    (struct omapfb_device *fbdev);
-+};
-+
-+enum omapfb_state {
-+      OMAPFB_DISABLED = 0,
-+      OMAPFB_SUSPENDED= 99,
-+      OMAPFB_ACTIVE   = 100
-+};
-+
-+struct gfx_lchannel {
-+      int                     lch_num;
-+      struct gfx_lchannel     *next, *prev;
-+};
-+
-+struct gfx_dma {
-+      spinlock_t              spinlock;
-+
-+      struct completion       sync_complete;          /* Signalled when the
-+                                                         fifo gets empty */
-+      volatile int            done;                   /* Indicates the
-+                                                         end of a DMA chain
-+                                                         transfer */
-+      struct gfx_lchannel     fifo[GFX_FIFO_SIZE];
-+      struct gfx_lchannel     *f_head, *f_tail;       /* Process and insert
-+                                                         points on the
-+                                                         fifo */
-+      struct gfx_lchannel     *f_chain_end;           /* Points to the new
-+                                                         chain end */
-+      struct semaphore        f_free;                 /* # of free lch-s */
-+      int                     f_run;                  /* # of active lch-s */
-+      int                     f_wait;                 /* # of lch-s
-+                                                         waiting */
-+      struct tasklet_struct   dequeue_tasklet;        /* Processes new DMA
-+                                                         chain  transfers on
-+                                                         the fifo */
-+};
-+
-+#define OMAPFB_RQUEUE_SIZE 20
-+
-+struct omapfb_fillrect_params
-+{
-+      struct fb_info          *fbi;
-+      struct fb_fillrect      rect; 
-+};
-+
-+struct omapfb_copyarea_params
-+{
-+      struct fb_info          *fbi;
-+      struct fb_copyarea_ext  area;
-+};
-+
-+struct omapfb_update_window_params
-+{
-+      struct fb_info          *fbi;
-+      struct fb_update_window win;
-+};
-+
-+struct omapfb_imageblit_params
-+{
-+      struct fb_info  *fbi;
-+      struct fb_image image;
-+      int             flags;
-+};
-+
-+union req_params
-+{
-+      /* All possible requests are to be listed here */
-+      struct omapfb_fillrect_params           fillrect;
-+      struct omapfb_copyarea_params           copyarea;
-+      struct omapfb_update_window_params      update_window;
-+      struct omapfb_imageblit_params          imageblit;
-+};
-+
-+struct omapfb_request
-+{
-+      struct list_head        entry;
-+      int                     (*function)(void *par);
-+      union req_params        par;
-+};
-+
-+struct omapfb_rqueue
-+{
-+      spinlock_t              lock;
-+      struct list_head        free_list;
-+      struct list_head        pending_list;
-+      struct completion       rqueue_empty;
-+      struct semaphore        free_sema;
-+      struct omapfb_request   req_pool[OMAPFB_RQUEUE_SIZE];
-+      struct work_struct      work;
-+      unsigned long           status;
-+};
-+
-+struct omapfb_device {
-+      int                     state;
-+      int                     ext_lcdc;               /* Using external
-+                                                           LCD controller */
-+      void                    *lcddma_base;           /* MPU virtual
-+                                                         address */
-+      dma_addr_t              lcddma_handle;          /* Bus physical
-+                                                         address */
-+      unsigned long           lcddma_mem_size;
-+      unsigned long           palette_org;            /* Palette offset into
-+                                                         lcddma_base/handle */
-+      unsigned long           frame0_org, frame1_org; /* Frame offsets for
-+                                                         back and front
-+                                                         frame buffers into
-+                                                         lcddma_base/handle */
-+      unsigned long           vis_frame_org;          /* Offset of visible
-+                                                         frame buffer.
-+                                                         = frame0/1_org */
-+      unsigned long           src_frame_org;          /* Offset of source
-+                                                         frame for drawing
-+                                                         operations.
-+                                                         = frame0/1_org */
-+      unsigned long           dst_frame_org;          /* Offset of dest
-+                                                         frame for drawing
-+                                                         operations.
-+                                                         = frame0/1_org */
-+      unsigned long           view_org;               /* View offset into
-+                                                         lcddma_base/handle+
-+                                                         vis_frame_org.
-+                                                         Used for panning */
-+      unsigned long           palette_size;
-+      int                     xscale, yscale, mirror; /* transformations.
-+                                                         rotate is stored in
-+                                                         fb_info->var */
-+
-+      u32                     pseudo_palette[17];
-+
-+      struct gfx_dma          gfx;                    /* Accelerator */
-+      struct omapfb_rqueue    rqueue;
-+      struct lcd_panel        *panel;                 /* LCD panel */
-+      struct lcd_ctrl         *ctrl;                  /* LCD controller */
-+
-+      struct fb_info          *fb_info;               /* Linux fbdev
-+                                                         framework data */
-+      struct device           *dev;
-+};
-+
-+extern struct lcd_panel h3_panel;
-+extern struct lcd_panel h2_panel;
-+extern struct lcd_panel p2_panel;
-+extern struct lcd_panel osk_panel;
-+extern struct lcd_panel innovator1610_panel;
-+extern struct lcd_panel innovator1510_panel;
-+extern struct lcd_panel h6300_panel;
-+
-+extern struct lcd_ctrl omapfb_lcdc_ctrl;
-+
-+#endif /* __KERNEL__ */
-+
-+#endif /* __OMAPFB_H */
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/video/omap/omapfb_main.c bt_kernel/drivers/video/omap/omapfb_main.c
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/drivers/video/omap/omapfb_main.c    2005-10-30 17:44:18.967844936 +0200
-+++ bt_kernel/drivers/video/omap/omapfb_main.c 2005-10-24 19:16:46.600530000 +0300
-@@ -89,6 +89,7 @@
- extern struct lcd_panel innovator1610_panel;
- extern struct lcd_panel innovator1510_panel;
- extern struct lcd_panel lph8923_panel;
-+extern struct lcd_panel h6300_panel;
- static struct lcd_panel *panels[] = {
- #ifdef CONFIG_MACH_OMAP_H2
-@@ -109,6 +110,9 @@
- #ifdef CONFIG_MACH_OMAP_PALMTE
-       &palmte_panel,
- #endif
-+#ifdef CONFIG_MACH_OMAP_H6300
-+      &h6300_panel,
-+#endif
- #ifdef CONFIG_MACH_OMAP_INNOVATOR
-@@ -260,18 +264,40 @@
-                       u_int blue, u_int transp, int update_hw_pal)
- {
-       struct omapfb_device *fbdev = (struct omapfb_device *)info->par;
--      u16 pal;
-       int r = 0;
--      if (regno < 16) {
--              pal = ((red >> 11) << 11) | ((green >> 10) << 5) | (blue >> 11);
--              ((u32 *)(info->pseudo_palette))[regno] = pal;
--      }
-+      switch (fbdev->color_mode) {
-+      case OMAPFB_COLOR_YUV422:
-+      case OMAPFB_COLOR_YUV420:
-+              r = -EINVAL;
-+              break;
-+      case OMAPFB_COLOR_CLUT_8BPP:
-+      case OMAPFB_COLOR_CLUT_4BPP:
-+      case OMAPFB_COLOR_CLUT_2BPP:
-+      case OMAPFB_COLOR_CLUT_1BPP:
-+              if (fbdev->ctrl->setcolreg)
-+                      r = fbdev->ctrl->setcolreg(regno, red, green, blue,
-+                                                      transp, update_hw_pal);
-+              /* Fallthrough */
-+      case OMAPFB_COLOR_RGB565:
-+              if (r != 0)
-+                      break;
--      if (fbdev->ctrl->setcolreg)
--              r = fbdev->ctrl->setcolreg(regno, red, green, blue, transp,
--                                              update_hw_pal);
-+              if (regno < 0) {
-+                      r = -EINVAL;
-+                      break;
-+              }
-+              if (regno < 16) {
-+                      u16 pal;
-+                      pal = ((red >> 11) << 11) | ((green >> 10) << 5) |
-+                              (blue >> 11);
-+                      ((u32 *)(info->pseudo_palette))[regno] = pal;
-+              }
-+              break;
-+      default:
-+              BUG();
-+      }
-       return r;
- }
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/.gitignore bt_kernel/.gitignore
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/.gitignore  2005-10-20 09:23:05.000000000 +0300
-+++ bt_kernel/.gitignore       1970-01-01 02:00:00.000000000 +0200
-@@ -1,30 +0,0 @@
--#
--# NOTE! Don't add files that are generated in specific
--# subdirectories here. Add them in the ".gitignore" file
--# in that subdirectory instead.
--#
--# Normal rules
--#
--.*
--*.o
--*.a
--*.s
--*.ko
--*.mod.c
--
--#
--# Top-level generic files
--#
--vmlinux*
--System.map
--Module.symvers
--
--#
--# Generated include files
--#
--include/asm
--include/config
--include/linux/autoconf.h
--include/linux/compile.h
--include/linux/version.h
--
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/include/asm-arm/arch-omap/board-h6300.h bt_kernel/include/asm-arm/arch-omap/board-h6300.h
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/include/asm-arm/arch-omap/board-h6300.h     1970-01-01 02:00:00.000000000 +0200
-+++ bt_kernel/include/asm-arm/arch-omap/board-h6300.h  2005-08-12 13:46:22.016114000 +0300
-@@ -0,0 +1,40 @@
-+/*
-+ * linux/include/asm-arm/arch-omap/board-innovator.h
-+ *
-+ * Copyright (C) 2001 RidgeRun, Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License as published by the
-+ * Free Software Foundation; either version 2 of the License, or (at your
-+ * option) any later version.
-+ *
-+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
-+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
-+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
-+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-+ *
-+ * You should have received a copy of the GNU General Public License along
-+ * with this program; if not, write to the Free Software Foundation, Inc.,
-+ * 675 Mass Ave, Cambridge, MA 02139, USA.
-+ */
-+#ifndef __ASM_ARCH_H6300_H
-+#define __ASM_ARCH_H6300_H
-+
-+#ifndef OMAP_SDRAM_DEVICE
-+#define OMAP_SDRAM_DEVICE                     D256M_1X16_4B
-+#endif
-+
-+#define OMAP1510P1_IMIF_PRI_VALUE             0x00
-+#define OMAP1510P1_EMIFS_PRI_VALUE            0x00
-+#define OMAP1510P1_EMIFF_PRI_VALUE            0x00
-+
-+#define NR_FPGA_IRQS          24
-+#define NR_IRQS                 IH_BOARD_BASE + NR_FPGA_IRQS
-+
-+#endif /* __ASM_ARCH_H6300_H */
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/include/asm-arm/arch-omap/cpu.h bt_kernel/include/asm-arm/arch-omap/cpu.h
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/include/asm-arm/arch-omap/cpu.h     2005-10-30 17:44:19.208806581 +0200
-+++ bt_kernel/include/asm-arm/arch-omap/cpu.h  2005-10-30 16:32:39.609796000 +0200
-@@ -215,4 +215,9 @@
- #  define cpu_is_omap2420()           1
- #endif
-+/* Macros to detect if we have OMAP1 or OMAP2 */
-+#define cpu_class_is_omap1() (cpu_is_omap730() || cpu_is_omap15xx() || \
-+ cpu_is_omap16xx())
-+#define cpu_class_is_omap2() cpu_is_omap24xx()
-+
- #endif
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/include/asm-arm/arch-omap/dma.h bt_kernel/include/asm-arm/arch-omap/dma.h
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/include/asm-arm/arch-omap/dma.h     2005-10-20 09:23:05.000000000 +0300
-+++ bt_kernel/include/asm-arm/arch-omap/dma.h  2005-10-30 16:32:39.609796000 +0200
-@@ -217,19 +217,22 @@
- extern void omap_stop_dma(int lch);
- extern void omap_set_dma_transfer_params(int lch, int data_type,
-                                        int elem_count, int frame_count,
--                                       int sync_mode);
-+                                       int sync_mode,
-+                                       int dma_trigger, int src_or_dst_synch);
- extern void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode,
-                                   u32 color);
- extern void omap_set_dma_src_params(int lch, int src_port, int src_amode,
--                                  unsigned long src_start);
-+                                  unsigned long src_start,
-+                                  int src_ei, int src_fi);
- extern void omap_set_dma_src_index(int lch, int eidx, int fidx);
- extern void omap_set_dma_src_data_pack(int lch, int enable);
- extern void omap_set_dma_src_burst_mode(int lch,
-                                       enum omap_dma_burst_mode burst_mode);
- extern void omap_set_dma_dest_params(int lch, int dest_port, int dest_amode,
--                                   unsigned long dest_start);
-+                                   unsigned long dest_start,
-+                                   int dst_ei, int dst_fi);
- extern void omap_set_dma_dest_index(int lch, int eidx, int fidx);
- extern void omap_set_dma_dest_data_pack(int lch, int enable);
- extern void omap_set_dma_dest_burst_mode(int lch,
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/include/asm-arm/arch-omap/hardware.h bt_kernel/include/asm-arm/arch-omap/hardware.h
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/include/asm-arm/arch-omap/hardware.h        2005-10-30 17:44:19.364781754 +0200
-+++ bt_kernel/include/asm-arm/arch-omap/hardware.h     2005-10-22 03:52:45.687256000 +0300
-@@ -290,6 +290,10 @@
- #include "board-innovator.h"
- #endif
-+#ifdef CONFIG_MACH_OMAP_H6300
-+#include "board-h6300.h"
-+#endif
-+
- #ifdef CONFIG_MACH_OMAP_H2
- #include "board-h2.h"
- #endif
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/include/asm-arm/arch-omap/h6300_uart_info.h bt_kernel/include/asm-arm/arch-omap/h6300_uart_info.h
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/include/asm-arm/arch-omap/h6300_uart_info.h 1970-01-01 02:00:00.000000000 +0200
-+++ bt_kernel/include/asm-arm/arch-omap/h6300_uart_info.h      2005-10-14 18:55:31.156317000 +0300
-@@ -0,0 +1,33 @@
-+/*
-+ * Support file for calling h6300 uart configuration functions.
-+ * Used at least by h6300_bt driver.
-+ * 
-+ * Copyright (c) 2005 SDG Systems, LLC
-+ * 2005-03-29   Todd Blumer     Converted  basic structure to support hx4700
-+ * 2005-10-03   Mika Laitio (lamikr@cc.jyu.fi)        Reorganized for the iPAQ h6300 bt driver.
-+ */
-+
-+#ifndef _H6300_UART_INFO_H
-+#define _H6300_UART_INFO_H
-+
-+#include "omap_serial.h"
-+
-+#define GPIO_BT_PWR_EN 3
-+#define GPIO_N_BT_RST 9
-+
-+#define GPIO_I2C_GPRS_RESET 16
-+#define GPIO_I2C_MIC_OP_EN 10
-+#define GPIO_I2C_SPK_OP_PD 11
-+
-+#define GPIO_VALUE_OFF        0
-+#define GPIO_VALUE_ON 1
-+
-+#define GPIO_DIR_OUTPUT 1
-+
-+struct h6300_uart_funcs {
-+      void (*configure)( struct uart_omap_port *up, int state);
-+      void (*set_txrx)( struct uart_omap_port *up, int txrx);
-+      int (*get_txrx)( struct uart_omap_port *up);
-+};
-+
-+#endif
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/include/asm-arm/arch-omap/mux.h bt_kernel/include/asm-arm/arch-omap/mux.h
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/include/asm-arm/arch-omap/mux.h     2005-10-30 17:44:19.465765680 +0200
-+++ bt_kernel/include/asm-arm/arch-omap/mux.h  2005-10-14 18:55:31.156317000 +0300
-@@ -316,6 +316,13 @@
-       P15_1610_UWIRE_CS3,
-       N15_1610_UWIRE_CS1,
-+      /* OMAP-1510 uWire */
-+      P15_1510_UWIRE_CS3,
-+      N14_1510_UWIRE_CS0,
-+      V19_1510_UWIRE_SCLK,
-+      W21_1510_UWIRE_SDO,
-+      U18_1510_UWIRE_SDI,
-+
-       /* OMAP-1610 Flash */
-       L3_1610_FLASH_CS2B_OE,
-       M8_1610_FLASH_CS2B_WE,
-@@ -380,6 +387,7 @@
-       T20_1610_LOW_PWR,
-       /* MCLK Settings */
-+      R10_1510_MCLK_ON,
-       V5_1710_MCLK_ON,
-       V5_1710_MCLK_OFF,
-       R10_1610_MCLK_ON,
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/include/asm-arm/arch-omap/omapfb.h bt_kernel/include/asm-arm/arch-omap/omapfb.h
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/include/asm-arm/arch-omap/omapfb.h  2005-10-30 17:44:19.557751038 +0200
-+++ bt_kernel/include/asm-arm/arch-omap/omapfb.h       2005-10-22 03:52:45.687256000 +0300
-@@ -267,6 +267,7 @@
- extern struct lcd_panel osk_panel;
- extern struct lcd_panel innovator1610_panel;
- extern struct lcd_panel innovator1510_panel;
-+extern struct lcd_panel h6300_panel;
- #ifdef CONFIG_ARCH_OMAP1
- extern struct lcd_ctrl omap1_lcd_ctrl;
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/include/asm-arm/arch-omap/omap_serial.h bt_kernel/include/asm-arm/arch-omap/omap_serial.h
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/include/asm-arm/arch-omap/omap_serial.h     1970-01-01 02:00:00.000000000 +0200
-+++ bt_kernel/include/asm-arm/arch-omap/omap_serial.h  2005-10-04 00:58:34.589442000 +0300
-@@ -0,0 +1,62 @@
-+/*
-+ * Omap/h6300 serial driver private interface. 
-+ * Code originates from the pxa-serial.h available in the handheld org drivers
-+ * for iPAQ PXA4700.
-+ *
-+ * Copyright (c) 2005 SDG Systems, LLC
-+ * 2005-03-29   Todd Blumer     Converted  basic structure to support hx4700
-+ * 2005-10-03   Mika Laitio (lamikr@cc.jyu.fi)        Reorganized for the iPAQ h6300 bt driver.
-+ */
-+ 
-+#ifndef _OMAP_SERIAL_H
-+#define _OMAP_SERIAL_H
-+
-+#define OMAP_SERIAL_TX 1
-+#define OMAP_SERIAL_RX 2
-+
-+#include <linux/tty.h>
-+#include <linux/serial_core.h>
-+
-+struct platform_omap_serial_funcs;
-+
-+struct uart_omap_port {
-+      struct uart_port                        port;
-+      unsigned char                           ier;
-+      unsigned char                           lcr;
-+      unsigned char                           mcr;
-+      unsigned int                            lsr_break_flag;
-+      unsigned int                            cken;
-+      char                                    *name;
-+      struct platform_omap_serial_funcs       *pf;
-+};
-+
-+/* A pointer to such a structure can be contained in the platform_data
-+ * field of every PXA UART platform_device. If the field is NULL, the
-+ * serial port works as usual.
-+ *
-+ * For the sake of simplicity/performance no one of the function pointers
-+ * in the structure below can be NULL.
-+ */
-+struct platform_omap_serial_funcs {
-+      /* Platform-specific function to initialize whatever is connected
-+         to this serial port... enable=1 -> enable transceiver,
-+         0 -> disable transceiver. */
-+      void (*configure) (struct uart_omap_port *up, int enable);
-+        /* Platform-specific function to 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) (struct uart_omap_port *up, int txrx);
-+      /* Get the current state of tx/rx (see bitflags above) */
-+      int (*get_txrx) (struct uart_omap_port *up);
-+};
-+
-+/*
-+ * The variables below are located in arch/arm/mach-omap/board_h6300.c
-+ * Machine-specific code may want to put a pointer to a static
-+ * platform_pxa_serial_funcs structure in the dev.platform_data
-+ * field of the respective port device.
-+ */
-+extern struct platform_device btuart_device;
-+
-+#endif
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/include/asm-arm/arch-omap/pca9535.h bt_kernel/include/asm-arm/arch-omap/pca9535.h
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/include/asm-arm/arch-omap/pca9535.h 1970-01-01 02:00:00.000000000 +0200
-+++ bt_kernel/include/asm-arm/arch-omap/pca9535.h      2005-10-25 03:24:45.525766000 +0300
-@@ -0,0 +1,39 @@
-+#ifndef _PCA9535_H
-+#define _PCA9535_H
-+
-+enum  pca9535_gpios {
-+      GPIO0 = 0,
-+      GPIO1 = 1,
-+      GPIO2 = 2,
-+      GPIO3 = 3,
-+      GPIO4 = 4,
-+      GPIO5 = 5,
-+      GPIO6 = 6,
-+      GPIO7 = 7,
-+      GPIO8 = 8,
-+      GPIO9 = 9,
-+      GPIO10 = 10,
-+      GPIO11 = 11,
-+      GPIO12 = 12,
-+      GPIO13 = 13,
-+      GPIO14 = 14,
-+      GPIO15 = 15,
-+      GPIO16 = 16,
-+      GPIO17 = 17
-+};
-+
-+enum gpio_values {
-+      HI      = 0,
-+      LOW     = 1
-+};
-+
-+enum gpio_direction {
-+      GPIO_INPUT      = 0,
-+      GPIO_OUTPUT     = 1
-+};
-+
-+extern int pca9535_gpio_read(int gpio);
-+extern int pca9535_gpio_write(int gpio, unsigned char val);   
-+extern int pca9535_gpio_direction(int gpio, unsigned char direction);
-+
-+#endif
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/lib/.gitignore bt_kernel/lib/.gitignore
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/lib/.gitignore      2005-10-20 09:23:05.000000000 +0300
-+++ bt_kernel/lib/.gitignore   1970-01-01 02:00:00.000000000 +0200
-@@ -1,6 +0,0 @@
--#
--# Generated files
--#
--gen_crc32table
--crc32table.h
--
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/Makefile bt_kernel/Makefile
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/Makefile    2005-10-30 17:44:14.606539141 +0200
-+++ bt_kernel/Makefile 2005-10-22 03:52:45.687256000 +0300
-@@ -11,7 +11,7 @@
- # expect to learn how to build the kernel reading this file.
- # Add custom flags here to avoid conflict with updates
--EXTRAVERSION :=  $(EXTRAVERSION)-omap1
-+EXTRAVERSION :=  $(EXTRAVERSION)-omap-h6300
- # Do not print "Entering directory ..."
- MAKEFLAGS += --no-print-directory
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/scripts/basic/.gitignore bt_kernel/scripts/basic/.gitignore
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/scripts/basic/.gitignore    2005-10-20 09:23:05.000000000 +0300
-+++ bt_kernel/scripts/basic/.gitignore 1970-01-01 02:00:00.000000000 +0200
-@@ -1,3 +0,0 @@
--fixdep
--split-include
--docproc
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/scripts/.gitignore bt_kernel/scripts/.gitignore
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/scripts/.gitignore  2005-10-20 09:23:05.000000000 +0300
-+++ bt_kernel/scripts/.gitignore       1970-01-01 02:00:00.000000000 +0200
-@@ -1,4 +0,0 @@
--conmakehash
--kallsyms
--pnmtologo
--
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/scripts/kconfig/.gitignore bt_kernel/scripts/kconfig/.gitignore
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/scripts/kconfig/.gitignore  2005-10-20 09:23:05.000000000 +0300
-+++ bt_kernel/scripts/kconfig/.gitignore       1970-01-01 02:00:00.000000000 +0200
-@@ -1,16 +0,0 @@
--#
--# Generated files
--#
--config*
--lex.*.c
--*.tab.c
--*.tab.h
--
--#
--# configuration programs
--#
--conf
--mconf
--qconf
--gconf
--kxgettext
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/scripts/mod/.gitignore bt_kernel/scripts/mod/.gitignore
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/scripts/mod/.gitignore      2005-10-20 09:23:05.000000000 +0300
-+++ bt_kernel/scripts/mod/.gitignore   1970-01-01 02:00:00.000000000 +0200
-@@ -1,4 +0,0 @@
--elfconfig.h
--mk_elfconfig
--modpost
--
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/sound/arm/Kconfig bt_kernel/sound/arm/Kconfig
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/sound/arm/Kconfig   2005-10-30 17:44:20.184651252 +0200
-+++ bt_kernel/sound/arm/Kconfig        2005-10-14 18:55:31.156317000 +0300
-@@ -15,6 +15,13 @@
-         To compile this driver as a module, choose M here: the module
-         will be called snd-sa11xx-uda1341.
-+config SND_OMAP_TSC2101
-+      tristate "OMAP TSC2101 driver (iPaq H63xx)"
-+      depends ARCH_OMAP1
-+      select SND_PCM
-+      help
-+              ALSA driver for TI TSC2101.
-+
- config SND_ARMAACI
-       tristate "ARM PrimeCell PL041 AC Link support"
-       depends on SND && ARM_AMBA
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/sound/arm/Makefile bt_kernel/sound/arm/Makefile
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/sound/arm/Makefile  2005-10-30 17:44:20.234643295 +0200
-+++ bt_kernel/sound/arm/Makefile       2005-10-14 18:55:31.156317000 +0300
-@@ -16,3 +16,6 @@
- obj-$(CONFIG_SND_OMAP_AIC23) += snd-omap-aic23.o
- snd-omap-aic23-objs := omap-aic23.o omap-alsa-dma.o omap-alsa-mixer.o
-+
-+obj-$(CONFIG_SND) += \
-+      omap/
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/sound/arm/omap/Makefile bt_kernel/sound/arm/omap/Makefile
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/sound/arm/omap/Makefile     1970-01-01 02:00:00.000000000 +0200
-+++ bt_kernel/sound/arm/omap/Makefile  2005-08-12 13:46:22.016114000 +0300
-@@ -0,0 +1,8 @@
-+#
-+# Makefile for ALSA
-+#
-+
-+snd-omap-tsc2101-objs := tsc2101_main.o tsc2101_mix.o tsc2101_pcm.o
-+
-+# Toplevel Module Dependency
-+obj-$(CONFIG_SND_OMAP_TSC2101)   += snd-omap-tsc2101.o
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/sound/arm/omap/omap-tsc2101.h bt_kernel/sound/arm/omap/omap-tsc2101.h
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/sound/arm/omap/omap-tsc2101.h       1970-01-01 02:00:00.000000000 +0200
-+++ bt_kernel/sound/arm/omap/omap-tsc2101.h    2005-08-20 00:24:45.622662000 +0300
-@@ -0,0 +1,81 @@
-+/*
-+ *  OMAP tsc2101 soundcard
-+ *  Copyright (c) by Everett Coleman II <gcc80x86@fuzzyneural.net>
-+ *
-+ *   This program is free software; you can redistribute it and/or modify
-+ *   it under the terms of the GNU General Public License as published by
-+ *   the Free Software Foundation; either version 2 of the License, or
-+ *   (at your option) any later version.
-+ *
-+ *   This program is distributed in the hope that it will be useful,
-+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ *   GNU General Public License for more details.
-+ *
-+ *   You should have received a copy of the GNU General Public License
-+ *   along with this program; if not, write to the Free Software
-+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
-+ *
-+ */
-+#ifndef __SOUND_OMAP_TSC2101_H
-+# define __SOUND_OMAP_TSC2101_H 1
-+
-+# include <sound/driver.h>
-+# include <linux/init.h>
-+# include <sound/core.h>
-+# include <sound/initval.h>
-+# include <sound/control.h>
-+# include <sound/pcm.h>
-+# include <asm/arch/dma.h>
-+# include <asm/hardware/tsc2101.h>
-+# include <../drivers/ssi/omap-tsc2101.h>
-+
-+# define TSC2101_AUDIO_CODEC_REGISTERS 2
-+# define OUTPUT_VOLUME_MIN  0
-+# define OUTPUT_VOLUME_MAX  127
-+# define AUDIO_RATE_DEFAULT 44100
-+# define AUDIO_BPS_DEFAULT  16
-+
-+# define AUDIO_DMA_BUF_SIZE (8 * 1024)
-+
-+# define AUDIO_DMA_RX OMAP_DMA_MCBSP1_RX
-+# define AUDIO_DMA_TX OMAP_DMA_MCBSP1_TX
-+# define AUDIO_MCBSP  OMAP_MCBSP1
-+
-+# define DEBUG 1
-+# ifdef DEBUG
-+#  define dprintk(x, y...) printk (x, ##y);
-+# else
-+#  define dprintk(x, y...) {}
-+# endif /* DEBUG */
-+
-+//# define DUMP_TSC2101_REGISTERS
-+
-+typedef struct audio_stream {
-+      char *id;
-+      int sid;
-+      int dev;
-+      int channel;
-+      spinlock_t lock;
-+      unsigned int offset, period, position;
-+      u8 active;
-+      snd_pcm_substream_t *stream;
-+} audio_stream_t;
-+
-+typedef struct snd_card_tsc2101 {
-+      snd_card_t *card;
-+      snd_pcm_t  *pcm;
-+
-+      long samplerate;
-+      audio_stream_t s[2];
-+} snd_card_tsc2101_t;
-+
-+# ifdef DUMP_TSC2101_REGISTERS
-+void dump_tsc2101_reg (void);
-+# endif /* DUMP_TSC2101_REGISTERS */
-+
-+int snd_tsc2101_setup_mix (snd_card_tsc2101_t *);
-+int snd_tsc2101_setup_pcm (snd_card_tsc2101_t *);
-+void snd_tsc2101_disable_pcm (snd_card_tsc2101_t *);
-+
-+#endif /* __SOUND_OMAP_TSC2101_H */
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/sound/arm/omap/tsc2101_main.c bt_kernel/sound/arm/omap/tsc2101_main.c
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/sound/arm/omap/tsc2101_main.c       1970-01-01 02:00:00.000000000 +0200
-+++ bt_kernel/sound/arm/omap/tsc2101_main.c    2005-08-12 13:46:22.016114000 +0300
-@@ -0,0 +1,109 @@
-+/*
-+ *  OMAP tsc2101 soundcard
-+ *  Copyright (c) by Everett Coleman II <gcc80x86@fuzzyneural.net>
-+ *
-+ *   This program is free software; you can redistribute it and/or modify
-+ *   it under the terms of the GNU General Public License as published by
-+ *   the Free Software Foundation; either version 2 of the License, or
-+ *   (at your option) any later version.
-+ *
-+ *   This program is distributed in the hope that it will be useful,
-+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ *   GNU General Public License for more details.
-+ *
-+ *   You should have received a copy of the GNU General Public License
-+ *   along with this program; if not, write to the Free Software
-+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
-+ *
-+ */
-+
-+#include <asm/hardware.h>
-+#include <asm/mach-types.h>
-+#include "omap-tsc2101.h"
-+
-+#ifdef DUMP_TSC2101_REGISTERS
-+void
-+dump_tsc2101_reg (void) {
-+      int i=0;
-+      printk ("TSC2101 Register DUMP:\n");
-+      for (i=0; i <= 0x27; i++) {
-+              printk ("0x%02x: %04x    ", i, omap_tsc2101_read (TSC2101_AUDIO_CODEC_REGISTERS, i));
-+              if ((i % 4) == 3)
-+                      printk ("\n");
-+      } printk ("\n");
-+} /* dump_tsc2101_reg */
-+#endif /* DUMP_TSC2101_REGISTERS */
-+
-+/* Globals
-+ **********/
-+static struct snd_card_tsc2101 *tsc2101=NULL;
-+static char *id=NULL;
-+
-+/* Module init/exit Functions
-+ ****************************/
-+static void
-+snd_tsc2101_free (snd_card_t *card) {
-+      snd_card_tsc2101_t *chip=card->private_data;
-+
-+      tsc2101=0;
-+      card->private_data=0;
-+      kfree (chip);
-+} /* snd_tsc2101_free */
-+
-+static int __init
-+alsa_card_tsc2101_init (void) {
-+      int err=0;
-+      snd_card_t *card;
-+
-+      if (!machine_is_h6300 ())
-+              return -ENODEV;
-+
-+      if ((card=snd_card_new (-1, id, THIS_MODULE, sizeof (snd_card_tsc2101_t))) == 0)
-+              return -ENOMEM;
-+      if ((tsc2101=kcalloc (1, sizeof (*tsc2101), GFP_KERNEL)) == 0)
-+              return -ENOMEM;
-+
-+      card->private_data=(void *)tsc2101;
-+      card->private_free=snd_tsc2101_free;
-+
-+      tsc2101->card=card;
-+      tsc2101->samplerate=AUDIO_RATE_DEFAULT;
-+
-+      if ((err=snd_tsc2101_setup_pcm (tsc2101)) < 0)
-+              goto nodev;
-+      if ((err=snd_tsc2101_setup_mix (tsc2101)) < 0)
-+              goto nodev;
-+
-+      // TODO: PM
-+
-+      strncpy (card->driver, "TSC2101", sizeof (card->driver));
-+      strncpy (card->shortname, "OMAP TSC2101", sizeof (card->shortname));
-+      strncpy (card->longname, "TI OMAP TSC2101 Audio Codec", sizeof (card->longname));
-+
-+      if ((err=snd_card_register (card)) == 0) {
-+              printk (KERN_INFO "TSC2101 audio support initialized\n");
-+              return 0;
-+      }
-+
-+nodev:
-+      snd_tsc2101_disable_pcm (tsc2101);
-+      snd_card_free (card);
-+      return err;
-+} /* alsa_card_tsc2101_init */
-+
-+static void __exit
-+alsa_card_tsc2101_exit (void) {
-+      snd_tsc2101_disable_pcm (tsc2101);
-+      snd_card_free(tsc2101->card);
-+} /* alsa_card_tsc2101_exit */
-+
-+module_init(alsa_card_tsc2101_init)
-+module_exit(alsa_card_tsc2101_exit)
-+
-+MODULE_AUTHOR("Everett Coleman II <gcc80x86@fuzzyneural.net>");
-+MODULE_DESCRIPTION("TI TSC2101 Audio Driver");
-+MODULE_LICENSE("GPL");
-+
-+module_param(id, charp, 0444);
-+MODULE_PARM_DESC(id, "ID string for OMAP TSC2101 soundcard.");
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/sound/arm/omap/tsc2101_mix.c bt_kernel/sound/arm/omap/tsc2101_mix.c
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/sound/arm/omap/tsc2101_mix.c        1970-01-01 02:00:00.000000000 +0200
-+++ bt_kernel/sound/arm/omap/tsc2101_mix.c     2005-08-12 13:46:22.016114000 +0300
-@@ -0,0 +1,211 @@
-+/*
-+ *  OMAP tsc2101 soundcard
-+ *  Copyright (c) by Everett Coleman II <gcc80x86@fuzzyneural.net>
-+ *
-+ *   This program is free software; you can redistribute it and/or modify
-+ *   it under the terms of the GNU General Public License as published by
-+ *   the Free Software Foundation; either version 2 of the License, or
-+ *   (at your option) any later version.
-+ *
-+ *   This program is distributed in the hope that it will be useful,
-+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ *   GNU General Public License for more details.
-+ *
-+ *   You should have received a copy of the GNU General Public License
-+ *   along with this program; if not, write to the Free Software
-+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
-+ *
-+ */
-+
-+#include "omap-tsc2101.h"
-+
-+static int
-+__pcm_playback_volume_info (snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) {
-+      uinfo->type =SNDRV_CTL_ELEM_TYPE_INTEGER;
-+      uinfo->count=2;
-+      uinfo->value.integer.min=OUTPUT_VOLUME_MIN;
-+      uinfo->value.integer.max=OUTPUT_VOLUME_MAX;
-+      return 0;
-+} /* __pcm_playback_volume_info */
-+
-+# define dgc_dalvl_extract(x) ((x & 0x7f00) >> 8)
-+# define dgc_darvl_extract(x) ((x & 0x007f))
-+static int
-+__pcm_playback_volume_get (snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) {
-+      u16 val=omap_tsc2101_read (TSC2101_AUDIO_CODEC_REGISTERS, TSC2101_DAC_GAIN_CTRL);
-+      ucontrol->value.integer.value[0]=dgc_dalvl_extract(val); // L
-+      ucontrol->value.integer.value[1]=dgc_darvl_extract(val); // R
-+      return 0;
-+} /* __pcm_playback_volume_get */
-+
-+static int
-+__pcm_playback_volume_put (snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) {
-+      u16 val=omap_tsc2101_read (TSC2101_AUDIO_CODEC_REGISTERS, TSC2101_DAC_GAIN_CTRL);
-+      int count=0;
-+      if (dgc_dalvl_extract(val) != ucontrol->value.integer.value[0]) {
-+              val=(val & ~DGC_DALVL(OUTPUT_VOLUME_MAX)) |
-+                      DGC_DALVL(ucontrol->value.integer.value[0]);
-+              count++;
-+      } /* L */
-+
-+      if (dgc_darvl_extract(val) != ucontrol->value.integer.value[1]) {
-+              val=(val & ~DGC_DARVL(OUTPUT_VOLUME_MAX)) |
-+                      DGC_DARVL((u16)ucontrol->value.integer.value[1]);
-+              count++;
-+      } /* R */
-+
-+      if (count)
-+              omap_tsc2101_write (TSC2101_AUDIO_CODEC_REGISTERS, TSC2101_DAC_GAIN_CTRL, val);
-+
-+      return count;
-+} /* __pcm_playback_volume_put */
-+
-+static int
-+__pcm_playback_switch_info (snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) {
-+      uinfo->type =SNDRV_CTL_ELEM_TYPE_BOOLEAN;
-+      uinfo->count=2;
-+      uinfo->value.integer.min=0;
-+      uinfo->value.integer.max=1;
-+      return 0;
-+} /* __pcm_playback_switch_info */
-+
-+static int
-+__pcm_playback_switch_get (snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) {
-+      u16 val=omap_tsc2101_read (TSC2101_AUDIO_CODEC_REGISTERS, TSC2101_DAC_GAIN_CTRL);
-+      ucontrol->value.integer.value[0]=(val & DGC_DALMU) == DGC_DALMU; // L
-+      ucontrol->value.integer.value[1]=(val & DGC_DARMU) == DGC_DARMU; // R
-+      return 0;
-+} /* __pcm_playback_switch_get */
-+
-+static int
-+__pcm_playback_switch_put (snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) {
-+      u16 val=omap_tsc2101_read (TSC2101_AUDIO_CODEC_REGISTERS, TSC2101_DAC_GAIN_CTRL);
-+      int count=0;
-+
-+      if (((val & DGC_DALMU) == DGC_DALMU) != ucontrol->value.integer.value[0]) {
-+              val=(val & ~DGC_DALMU) |
-+                      (ucontrol->value.integer.value[0] ? DGC_DALMU : 0);
-+              count++;
-+      } /* L */
-+      if (((val & DGC_DARMU) == DGC_DARMU) != ucontrol->value.integer.value[1]) {
-+              val=(val & ~DGC_DARMU) |
-+                      (ucontrol->value.integer.value[1] ? DGC_DARMU : 0);
-+              count++;
-+      } /* R */
-+
-+      if (count)
-+              omap_tsc2101_write (TSC2101_AUDIO_CODEC_REGISTERS, TSC2101_DAC_GAIN_CTRL, val);
-+      return count;
-+} /* __pcm_playback_switch_put */
-+
-+static int
-+__line_playback_volume_info (snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) {
-+      uinfo->type =SNDRV_CTL_ELEM_TYPE_INTEGER;
-+      uinfo->count=1;
-+      uinfo->value.integer.min=OUTPUT_VOLUME_MIN;
-+      uinfo->value.integer.max=OUTPUT_VOLUME_MAX;
-+      return 0;
-+} /* __line_playback_volume_info */
-+
-+#define hgc_adpga_hed_extract(x) ((x & 0x7f00) >> 8)
-+static int
-+__line_playback_volume_get (snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) {
-+      u16 val=omap_tsc2101_read (TSC2101_AUDIO_CODEC_REGISTERS, TSC2101_HEADSET_GAIN_CTRL);
-+      ucontrol->value.integer.value[0]=hgc_adpga_hed_extract(val);
-+      return 0;
-+} /* __line_playback_volume_get */
-+
-+static int
-+__line_playback_volume_put (snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) {
-+      u16 val=omap_tsc2101_read (TSC2101_AUDIO_CODEC_REGISTERS, TSC2101_HEADSET_GAIN_CTRL);
-+      int count=0;
-+      if (hgc_adpga_hed_extract(val) != ucontrol->value.integer.value[0]) {
-+              val=(val & ~HGC_ADPGA_HED(OUTPUT_VOLUME_MAX)) |
-+                      HGC_ADPGA_HED((u16)ucontrol->value.integer.value[0]);
-+              count++;
-+      }
-+      if (count)
-+              omap_tsc2101_write (TSC2101_AUDIO_CODEC_REGISTERS, TSC2101_HEADSET_GAIN_CTRL, val);
-+      return count;
-+} /* __line_playback_volume_put */
-+
-+static int
-+__line_playback_switch_info (snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) {
-+      uinfo->type =SNDRV_CTL_ELEM_TYPE_BOOLEAN;
-+      uinfo->count=1;
-+      uinfo->value.integer.min=0;
-+      uinfo->value.integer.max=1;
-+      return 0;
-+} /* __line_playback_switch_info */
-+
-+static int
-+__line_playback_switch_get (snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) {
-+      u16 val=omap_tsc2101_read (TSC2101_AUDIO_CODEC_REGISTERS, TSC2101_HEADSET_GAIN_CTRL);
-+      ucontrol->value.integer.value[0]=(val & HGC_ADMUT_HED) == HGC_ADMUT_HED;
-+      return 0;
-+} /* __line_playback_switch_get */
-+
-+static int
-+__line_playback_switch_put (snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) {
-+      u16 val=omap_tsc2101_read (TSC2101_AUDIO_CODEC_REGISTERS, TSC2101_HEADSET_GAIN_CTRL);
-+      int count=0;
-+
-+      if (((val & HGC_ADMUT_HED) == HGC_ADMUT_HED) != ucontrol->value.integer.value[0]) {
-+              val=(val & ~HGC_ADMUT_HED) | 
-+                      (ucontrol->value.integer.value[0] ? HGC_ADMUT_HED : 0);
-+              count++;
-+      }
-+      
-+      if (count)
-+              omap_tsc2101_write (TSC2101_AUDIO_CODEC_REGISTERS, TSC2101_HEADSET_GAIN_CTRL, val);
-+      return count;
-+} /* __line_playback_switch_put */
-+
-+
-+static snd_kcontrol_new_t tsc2101_control[] __devinitdata={
-+      { .name  = "PCM Playback Volume",
-+              .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-+              .index = 0,
-+              .access= SNDRV_CTL_ELEM_ACCESS_READWRITE,
-+              .info  = __pcm_playback_volume_info,
-+              .get   = __pcm_playback_volume_get,
-+              .put   = __pcm_playback_volume_put,
-+      }, {
-+              .name  = "PCM Playback Switch",
-+              .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-+              .index = 0,
-+              .access= SNDRV_CTL_ELEM_ACCESS_READWRITE,
-+              .info  = __pcm_playback_switch_info,
-+              .get   = __pcm_playback_switch_get,
-+              .put   = __pcm_playback_switch_put,
-+      }, {
-+              .name  = "Line Playback Volume",
-+              .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-+              .index = 1,
-+              .access= SNDRV_CTL_ELEM_ACCESS_READWRITE,
-+              .info  = __line_playback_volume_info,
-+              .get   = __line_playback_volume_get,
-+              .put   = __line_playback_volume_put,
-+      }, {
-+              .name  = "Line Playback Switch",
-+              .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-+              .index = 1,
-+              .access= SNDRV_CTL_ELEM_ACCESS_READWRITE,
-+              .info  = __line_playback_switch_info,
-+              .get   = __line_playback_switch_get,
-+              .put   = __line_playback_switch_put,
-+      }
-+};
-+
-+int
-+snd_tsc2101_setup_mix (snd_card_tsc2101_t *tsc2101) {
-+      int i=0, err=0;
-+
-+      if (!tsc2101)
-+              return -EINVAL;
-+      for (i=0; i < ARRAY_SIZE(tsc2101_control); i++)
-+              if ((err=snd_ctl_add (tsc2101->card, snd_ctl_new1 (&tsc2101_control[i], tsc2101->card))) < 0)
-+                      return err;
-+      return 0;
-+} /* snd_tsc2101_setup_mix */
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/sound/arm/omap/tsc2101_pcm.c bt_kernel/sound/arm/omap/tsc2101_pcm.c
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/sound/arm/omap/tsc2101_pcm.c        1970-01-01 02:00:00.000000000 +0200
-+++ bt_kernel/sound/arm/omap/tsc2101_pcm.c     2005-08-31 01:22:50.289885000 +0300
-@@ -0,0 +1,555 @@
-+/*
-+ *  OMAP tsc2101 soundcard
-+ *  Copyright (c) by Everett Coleman II <gcc80x86@fuzzyneural.net>
-+ *
-+ *   This program is free software; you can redistribute it and/or modify
-+ *   it under the terms of the GNU General Public License as published by
-+ *   the Free Software Foundation; either version 2 of the License, or
-+ *   (at your option) any later version.
-+ *
-+ *   This program is distributed in the hope that it will be useful,
-+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ *   GNU General Public License for more details.
-+ *
-+ *   You should have received a copy of the GNU General Public License
-+ *   along with this program; if not, write to the Free Software
-+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
-+ *
-+ */
-+
-+#include <asm/arch/mcbsp.h>
-+#include <linux/delay.h>
-+#include <asm/arch/gpio.h>
-+#include "omap-tsc2101.h"
-+
-+static snd_pcm_hardware_t pcm_hardware[2] = {
-+      {
-+              .info =
-+                      SNDRV_PCM_INFO_INTERLEAVED |
-+                      SNDRV_PCM_INFO_BLOCK_TRANSFER   |
-+                      SNDRV_PCM_INFO_MMAP |
-+                      SNDRV_PCM_INFO_MMAP_VALID |
-+                      SNDRV_PCM_INFO_PAUSE |
-+                      SNDRV_PCM_INFO_RESUME,
-+              .formats = SNDRV_PCM_FMTBIT_U16_LE,
-+              .rates   = 
-+                      SNDRV_PCM_RATE_8000_44100 | 
-+                      SNDRV_PCM_RATE_KNOT,
-+              .rate_min         = 7350,
-+              .rate_max         = 48000,
-+              .channels_min     = 2,
-+              .channels_max     = 2,
-+              .buffer_bytes_max = 128 * 1024,
-+              .period_bytes_min = 64,
-+              .period_bytes_max = AUDIO_DMA_BUF_SIZE,
-+              .periods_min      = 2,
-+              .periods_max      = 255,
-+              .fifo_size        = 0,
-+      }, {
-+              .info =
-+                      SNDRV_PCM_INFO_INTERLEAVED |
-+                      SNDRV_PCM_INFO_BLOCK_TRANSFER   |
-+                      SNDRV_PCM_INFO_MMAP |
-+                      SNDRV_PCM_INFO_MMAP_VALID |
-+                      SNDRV_PCM_INFO_PAUSE |
-+                      SNDRV_PCM_INFO_RESUME,
-+                      .formats = SNDRV_PCM_FMTBIT_U16_LE,
-+                      .rates   = 
-+                              SNDRV_PCM_RATE_8000_44100 | 
-+                              SNDRV_PCM_RATE_KNOT,
-+                      .rate_min         = 7350,
-+                      .rate_max         = 48000,
-+                      .channels_min     = 2,
-+                      .channels_max     = 2,
-+                      .buffer_bytes_max = 128 * 1024,
-+                      .period_bytes_min = 64,
-+                      .period_bytes_max = AUDIO_DMA_BUF_SIZE,
-+                      .periods_min      = 2,
-+                      .periods_max      = 255,
-+                      .fifo_size        = 0,
-+      }
-+};
-+
-+static unsigned int rate_list[] = {
-+      7350,  8000,  8018,  8727, 
-+      8820,  9600,  11025, 12000,
-+      14700, 16000, 22050, 24000,
-+      29400, 32000, 44100, 48000
-+};
-+
-+static snd_pcm_hw_constraint_list_t rate_constraint = {
-+      .count = ARRAY_SIZE (rate_list),
-+      .list  = rate_list,
-+      .mask  = 0,
-+};
-+
-+
-+static int
-+__tsc2101_open (snd_pcm_substream_t *substream) {
-+      snd_pcm_runtime_t *runtime = substream->runtime;
-+      snd_card_tsc2101_t *chip = snd_pcm_substream_chip (substream);
-+      int sid   = substream->pstr->stream, err;
-+
-+      dprintk ("[%s]\n", __FUNCTION__);
-+      chip->s[sid].stream = substream;
-+      runtime->hw = pcm_hardware[sid];
-+
-+      if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
-+              return err;
-+      if ((err = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &rate_constraint)) < 0)
-+              return err;
-+
-+      dprintk ("[%s] pass\n", __FUNCTION__);
-+      return 0;
-+} /* __tsc2101_open */
-+
-+static int
-+__tsc2101_close (snd_pcm_substream_t *substream) {
-+      snd_card_tsc2101_t *chip = snd_pcm_substream_chip (substream);
-+      dprintk ("[%s]\n", __FUNCTION__);
-+      chip->s[substream->pstr->stream].stream = 0;
-+      dprintk ("[%s] pass\n", __FUNCTION__);
-+      return 0;
-+} /* __tsc2101_close */
-+
-+static int
-+__tsc2101_hw_params (snd_pcm_substream_t *substream, snd_pcm_hw_params_t *hw_params) {
-+      dprintk ("[%s> pass\n", __FUNCTION__);
-+      return snd_pcm_lib_malloc_pages (substream, params_buffer_bytes (hw_params));
-+} /* __tsc2101_hw_params */
-+
-+static int
-+__tsc2101_hw_free (snd_pcm_substream_t *substream) {
-+      dprintk ("[%s> pass\n", __FUNCTION__);
-+      return snd_pcm_lib_free_pages (substream);
-+} /* __tsc2101_hw_free */
-+
-+static struct omap_mcbsp_reg_cfg mcbsp_cfg = {
-+//    .pcr0  = FSXM | FSRM | CLKXM | CLKRM | CLKXP | CLKRP,
-+//    .pcr0  = CLKXP | CLKRP,
-+      .pcr0  = CLKRM | SCLKME | FSXP | FSRP | CLKXP | CLKRP,
-+
-+//    .spcr2 = FREE | FRST | GRST | XRST | XINTM(3) | XEMPTY,
-+//    .spcr1 = RINTM(3) | RRST | RFULL,
-+      .spcr2 = FREE | FRST | GRST | XRST | XINTM(3),
-+      .spcr1 = RINTM(3) | RRST,
-+
-+      .rcr2  = RPHASE | RFRLEN2(OMAP_MCBSP_WORD_8) |
-+               RWDLEN2(OMAP_MCBSP_WORD_16) | RDATDLY(1),
-+      .rcr1  = RFRLEN1(OMAP_MCBSP_WORD_8) | RWDLEN1(OMAP_MCBSP_WORD_16),
-+      .xcr2  = XPHASE | XFRLEN2(OMAP_MCBSP_WORD_8) |
-+               XWDLEN2(OMAP_MCBSP_WORD_16) | XDATDLY(1) | XFIG,
-+      .xcr1  = XFRLEN1(OMAP_MCBSP_WORD_8) | XWDLEN1(OMAP_MCBSP_WORD_16),
-+      .srgr1 = FWID(15),
-+      .srgr2 = GSYNC | CLKSP | FSGM | FPER(31),
-+};
-+
-+static int
-+__set_samplerate (snd_card_tsc2101_t *tsc2101, long sample_rate) {
-+      static u8 div_list[] = {
-+              7, 7, 6, 6,
-+              5, 5, 4, 4,
-+              3, 3, 2, 2,
-+              1, 1, 0, 0
-+      };
-+      int i = 0, clkgdv = 0;
-+      u8  khz  = 0;
-+      u16 data = 0;
-+
-+      dprintk ("[%s]\n", __FUNCTION__);
-+      udelay (125);
-+      for (i=rate_constraint.count-1; i >= 0 ; i--)
-+              if (sample_rate >= rate_list[i])
-+                      break;
-+      if (i == -1)
-+              i=0;
-+      khz=(i%2) ? 0 : 1;
-+
-+      dprintk ("rate=%u\n", rate_list[i]);
-+
-+      data=omap_tsc2101_read (TSC2101_AUDIO_CODEC_REGISTERS, TSC2101_AUDIO_CTRL_1);
-+      data &= ~(AC1_DACFS(0x07) | AC1_ADCFS(0x07));
-+      data |= AC1_DACFS(div_list[i])
-+              | AC1_ADCFS(div_list[i]);
-+      omap_tsc2101_write (TSC2101_AUDIO_CODEC_REGISTERS, TSC2101_AUDIO_CTRL_1, data);
-+
-+      data=omap_tsc2101_read (TSC2101_AUDIO_CODEC_REGISTERS, TSC2101_AUDIO_CTRL_3);
-+      data &= ~(AC3_REFFS | AC3_SLVMS);
-+      data |= (khz) ? AC3_REFFS : 0;
-+      data |= AC3_SLVMS;
-+      omap_tsc2101_write (TSC2101_AUDIO_CODEC_REGISTERS, TSC2101_AUDIO_CTRL_3, data);
-+
-+      if (khz) {
-+              omap_tsc2101_write (
-+                              TSC2101_AUDIO_CODEC_REGISTERS, TSC2101_PLL_PROG_1,
-+                              PLL1_PLLSEL | PLL1_PVAL(1) | PLL1_I_VAL(7));
-+              omap_tsc2101_write (
-+                              TSC2101_AUDIO_CODEC_REGISTERS, TSC2101_PLL_PROG_2,
-+                              PLL2_D_VAL(0x1490));
-+
-+      } else {
-+              omap_tsc2101_write (
-+                              TSC2101_AUDIO_CODEC_REGISTERS, TSC2101_PLL_PROG_1,
-+                              PLL1_PLLSEL | PLL1_PVAL(1) | PLL1_I_VAL(8));
-+              omap_tsc2101_write (
-+                              TSC2101_AUDIO_CODEC_REGISTERS, TSC2101_PLL_PROG_2,
-+                              PLL2_D_VAL(0x780));
-+      }
-+
-+      tsc2101->samplerate=rate_list[i];
-+
-+      mcbsp_cfg.srgr1 =
-+          (FWID(AUDIO_BPS_DEFAULT - 1) | CLKGDV(clkgdv));
-+      mcbsp_cfg.srgr2 =
-+          ((GSYNC | CLKSP | FSGM | FPER(AUDIO_BPS_DEFAULT * 2 - 1)));
-+
-+      omap_mcbsp_config(AUDIO_MCBSP, &mcbsp_cfg);
-+      dprintk ("[%s] pass\n", __FUNCTION__);
-+      return 0;
-+} /* __set_samplerate */
-+
-+static int
-+__tsc2101_prepare (snd_pcm_substream_t *substream) {
-+      snd_pcm_runtime_t *runtime = substream->runtime;
-+      snd_card_tsc2101_t *chip   = snd_pcm_substream_chip (substream);
-+      audio_stream_t *s = &chip->s[substream->pstr->stream];
-+
-+      dprintk ("[%s]\n", __FUNCTION__);
-+      __set_samplerate (chip, runtime->rate);
-+
-+      // set FMT here ????
-+      s->period  =0;
-+      s->offset  =0;
-+      s->position=0;
-+      dprintk ("[%s] pass\n", __FUNCTION__);
-+      return 0;
-+} /* __tsc2101_prepare */
-+
-+# define DCSR_ERROR           0x3
-+# define DCSR_END_BLOCK       (1 << 5)
-+# define DCCR_EN              (1 << 7)
-+static void
-+tsc2101_playback_callback (int channel, u16 ch_status, void *data) {
-+      audio_stream_t *s=(audio_stream_t *)data;
-+
-+      dprintk ("[%s]\n", __FUNCTION__);
-+
-+      if (ch_status & DCSR_ERROR) {
-+              omap_writew (omap_readw (OMAP_DMA_CCR (channel)) &
-+                              ~DCCR_EN, OMAP_DMA_CCR (channel));
-+              printk (KERN_ERR "[%s] DCSR_ERROR!\n", __FUNCTION__);
-+              dprintk ("[%s] x-fail\n", __FUNCTION__);
-+              return;
-+      }
-+
-+      if (!(ch_status & DCSR_END_BLOCK)) {
-+              dprintk ("[%s] y-fail\n", __FUNCTION__);
-+              return;
-+      }
-+
-+      if (s->active) {
-+              unsigned int dma_size;
-+              unsigned int offset;
-+              snd_pcm_runtime_t *runtime;
-+
-+              snd_pcm_period_elapsed (s->stream);
-+
-+              spin_lock (&s->lock);
-+              runtime=s->stream->runtime;
-+
-+              dma_size = frames_to_bytes(runtime, runtime->period_size);
-+              offset = dma_size * s->period;
-+              snd_assert(dma_size <= AUDIO_DMA_BUF_SIZE,);
-+
-+              dprintk ("pb: offset=%08lx size=%u period=%u\n", (unsigned long)(runtime->dma_area + offset), dma_size, s->period);
-+#if 0
-+              omap_set_dma_transfer_params(channel, OMAP_DMA_DATA_TYPES16, 32, dma_size/(2*32), OMAP_DMA_SYNC_ELEMENT);
-+              omap_set_dma_dest_params(channel, OMAP_DMA_PORT_MPUI, OMAP_DMA_AMODE_CONSTANT, (OMAP1510_MCBSP1_BASE + OMAP_MCBSP_REG_DXR1));
-+              omap_set_dma_src_params(channel, 0x00, 0x01, (unsigned long)(runtime->dma_area + offset));
-+              omap_start_dma (channel);
-+#else
-+//            omap_set_gpio_dataout (2, 1);
-+              omap_set_dma_transfer_params (channel,
-+                              OMAP_DMA_DATA_TYPE_S16,
-+                              dma_size >> 1, 1,
-+                              OMAP_DMA_SYNC_ELEMENT
-+                              );
-+              omap_set_dma_dest_params (channel,
-+//                            OMAP_DMA_PORT_TIPB,
-+                              OMAP_DMA_PORT_MPUI,
-+                              OMAP_DMA_AMODE_CONSTANT,
-+                              (OMAP1510_MCBSP1_BASE + OMAP_MCBSP_REG_DXR1)
-+                              );
-+              omap_set_dma_src_params (channel,
-+                              OMAP_DMA_PORT_EMIFF,
-+                              OMAP_DMA_AMODE_POST_INC,
-+                              runtime->dma_area + offset
-+                              );
-+              omap_start_dma (channel);
-+//            omap_set_gpio_dataout (2, 0);
-+#endif
-+
-+              s->period++;
-+              s->period %= runtime->periods;
-+//            s->periods++;
-+
-+              s->offset = offset;
-+
-+              spin_unlock (&s->lock);
-+      }
-+
-+      dprintk ("[%s] pass\n", __FUNCTION__);
-+} /* tsc2101_playback_callback */
-+
-+static void
-+tsc2101_capture_callback (int channel, u16 ch_status, void *data) {
-+      dprintk ("[%s]\n", __FUNCTION__);
-+      omap_start_dma (channel);
-+      dprintk ("[%s] pass\n", __FUNCTION__);
-+} /* tsc2101_capture_callback */
-+
-+static int
-+__tsc2101_trigger (snd_pcm_substream_t *substream, int command) {
-+      snd_card_tsc2101_t *chip = snd_pcm_substream_chip (substream);
-+      audio_stream_t *s        = &chip->s[substream->pstr->stream];
-+      int err=0;
-+
-+      dprintk ("[%s]\n", __FUNCTION__);
-+
-+      switch (command) {
-+              case SNDRV_PCM_TRIGGER_START:
-+                      dprintk ("[%s] command=start(%d)\n", __FUNCTION__, command);
-+                      s->active++;
-+                      omap_clear_dma (s->channel);
-+                      if (s->sid == SNDRV_PCM_STREAM_PLAYBACK)
-+                              tsc2101_playback_callback (s->channel, 32, (void *)s);
-+                      else
-+                              tsc2101_capture_callback  (s->channel, 32, (void *)s);
-+                      break;
-+
-+              case SNDRV_PCM_TRIGGER_STOP:
-+                      dprintk ("[%s] command=stop(%d)\n", __FUNCTION__, command);
-+                      // TODO: be sure that all data has been xfered
-+                      s->active--;
-+                      spin_lock (&s->lock);
-+                      omap_clear_dma (s->channel);
-+                      omap_stop_dma (s->channel);
-+                      spin_unlock (&s->lock);
-+                      break;
-+
-+              case SNDRV_PCM_TRIGGER_SUSPEND:
-+                      dprintk ("[%s] command=suspend(%d)\n", __FUNCTION__, command);
-+              case SNDRV_PCM_TRIGGER_RESUME:
-+                      dprintk ("[%s] command=resume(%d)\n", __FUNCTION__, command);
-+              case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-+                      dprintk ("[%s] command=pause.push(%d)\n", __FUNCTION__, command);
-+              case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-+                      dprintk ("[%s] command=pause.release(%d)\n", __FUNCTION__, command);
-+              default:
-+                      err = -EINVAL;
-+                      break;
-+      } /* switch (command) */
-+
-+      dprintk ("[%s] exit (%d)\n", __FUNCTION__, err);
-+      return err;
-+} /* __tsc2101_trigger */
-+
-+static snd_pcm_uframes_t
-+__tsc2101_pointer (snd_pcm_substream_t *substream) {
-+      snd_card_tsc2101_t *chip   = snd_pcm_substream_chip (substream);
-+      snd_pcm_runtime_t *runtime = substream->runtime;
-+      audio_stream_t *s = &chip->s[substream->pstr->stream];
-+      unsigned long flags;
-+      snd_pcm_uframes_t offset;
-+      dma_addr_t ptr;
-+
-+      dprintk ("[%s]\n", __FUNCTION__);
-+
-+      spin_lock_irqsave (&s->lock, flags);
-+      ptr=omap_get_dma_src_pos (s->channel);
-+      dprintk ("xxxx: [%08lx,%08lx] ptr=%08lx:%08lx\n",
-+                      (unsigned long)runtime->dma_area,
-+                      (unsigned long)runtime->dma_addr,
-+                      (unsigned long)ptr,
-+                      (unsigned long)runtime->buffer_size);
-+      spin_unlock_irqrestore (&s->lock, flags);
-+
-+      offset=bytes_to_frames (runtime, ptr - runtime->dma_addr);
-+      if ((offset >= runtime->buffer_size) || (offset < 0))
-+              offset=0;
-+      dprintk ("[%s] pass:%lu\n", __FUNCTION__, offset);
-+      return offset;
-+} /* __tsc2101_pointer */
-+
-+static snd_pcm_ops_t playback_ops = {
-+      .open      = __tsc2101_open,
-+      .close     = __tsc2101_close,
-+      .ioctl     = snd_pcm_lib_ioctl,
-+      .hw_params = __tsc2101_hw_params,
-+      .hw_free   = __tsc2101_hw_free,
-+      .prepare   = __tsc2101_prepare,
-+      .trigger   = __tsc2101_trigger,
-+      .pointer   = __tsc2101_pointer,
-+};
-+
-+static snd_pcm_ops_t capture_ops = {
-+      .open      = __tsc2101_open,
-+      .close     = __tsc2101_close,
-+      .ioctl     = snd_pcm_lib_ioctl,
-+      .hw_params = __tsc2101_hw_params,
-+      .hw_free   = __tsc2101_hw_free,
-+      .prepare   = __tsc2101_prepare,
-+      .trigger   = __tsc2101_trigger,
-+      .pointer   = __tsc2101_pointer,
-+};
-+
-+static void
-+tsc2101_audio_init (snd_card_tsc2101_t *tsc2101) {
-+      dprintk ("[%s]\n", __FUNCTION__);
-+      omap_set_gpio_dataout (2, 0);
-+      omap_set_gpio_direction (2, 0);
-+
-+      /* initialize mcbsp */
-+      omap_mcbsp_request (AUDIO_MCBSP);
-+      omap_mcbsp_stop (AUDIO_MCBSP);
-+
-+      omap_mcbsp_config (AUDIO_MCBSP, &mcbsp_cfg);
-+      omap_mcbsp_start (AUDIO_MCBSP);
-+
-+      omap_tsc2101_enable ();
-+#if 0
-+      omap_tsc2101_write (
-+                      TSC2101_AUDIO_CODEC_REGISTERS,
-+                      TSC2101_CODEC_POWER_CTRL,
-+                      0x0000);
-+      omap_tsc2101_write (
-+                      TSC2101_AUDIO_CODEC_REGISTERS,
-+                      TSC2101_AUDIO_CTRL_5,
-+                      AC5_DAC2SPK1(3) | AC5_AST2SPK1 | AC5_KCL2SPK1 |
-+                      AC5_DAC2SPK2(3) | AC5_AST2SPK2 | AC5_KCL2SPK2 |
-+                      AC5_HDSCPTC);
-+#else
-+#ifdef DUMP_TSC2101_REGISTERS
-+      dump_tsc2101_reg ();
-+#endif /* DUMP_TSC2101_REGISTERS */
-+
-+      omap_tsc2101_write (2, TSC2101_CODEC_POWER_CTRL, 0x0000);
-+
-+      /*Mute Analog Sidetone */
-+      /*Select MIC_INHED input for headset */
-+      /*Cell Phone In not connected */
-+      omap_tsc2101_write (2, TSC2101_MIXER_PGA_CTRL,
-+                          MPC_ASTMU | MPC_ASTG(0x40) | MPC_MICADC);
-+
-+      /* Set record source */
-+      omap_tsc2101_write (2, TSC2101_MIXER_PGA_CTRL, MPC_MICSEL(0));
-+
-+      /* ADC, DAC, Analog Sidetone, cellphone, buzzer softstepping enabled */
-+      /* 1dB AGC hysteresis */
-+      /* MICes bias 2V */
-+      omap_tsc2101_write (2, TSC2101_AUDIO_CTRL_4, AC4_MB_HED(0));
-+
-+      /* Set codec output volume */
-+      omap_tsc2101_write (2, TSC2101_DAC_GAIN_CTRL, 0x0000);
-+
-+      /* DAC left and right routed to SPK2 */
-+      /* SPK1/2 unmuted */
-+      omap_tsc2101_write (2, TSC2101_AUDIO_CTRL_5,
-+                          AC5_DAC2SPK1(3) | AC5_AST2SPK1 | AC5_KCL2SPK1 |
-+                          AC5_DAC2SPK2(3) | AC5_AST2SPK2 | AC5_KCL2SPK2 |
-+                          AC5_HDSCPTC);
-+
-+      /* OUT8P/N muted, CPOUT muted */
-+
-+      omap_tsc2101_write (2, TSC2101_AUDIO_CTRL_6,
-+                          AC6_MUTLSPK | AC6_MUTSPK2 | AC6_LDSCPTC |
-+                          AC6_VGNDSCPTC);
-+
-+      /* Headset/Hook switch detect disabled */
-+      omap_tsc2101_write (2, TSC2101_AUDIO_CTRL_7, 0x0000);
-+
-+      /* mic input volume control */
-+      omap_tsc2101_write(2, TSC2101_HANDSET_GAIN_CTRL, HNGC_ADPGA_HND(25));
-+#endif
-+
-+#ifdef DUMP_TSC2101_REGISTERS
-+      dump_tsc2101_reg ();
-+#endif /* DUMP_TSC2101_REGISTERS */
-+
-+      __set_samplerate (tsc2101, tsc2101->samplerate);
-+      dprintk ("[%s] pass\n", __FUNCTION__);
-+} /* tsc2101_audio_init */
-+
-+int
-+snd_tsc2101_setup_pcm (snd_card_tsc2101_t *tsc2101) {
-+      snd_pcm_t *pcm=0;
-+      int err=0;
-+
-+      dprintk ("[%s]\n", __FUNCTION__);
-+      if (!tsc2101)
-+              return -EINVAL;
-+      if ((err=snd_pcm_new (tsc2101->card, "TSC2101 PCM", 0, 1, 1, &pcm)) < 0)
-+              return err;
-+
-+      if ((err=snd_pcm_lib_preallocate_pages_for_all (pcm, SNDRV_DMA_TYPE_CONTINUOUS, snd_dma_continuous_data (GFP_KERNEL), 128, 128*1024)) < 0)
-+              return err;
-+
-+      snd_pcm_set_ops (pcm, SNDRV_PCM_STREAM_PLAYBACK, &playback_ops);
-+      snd_pcm_set_ops (pcm, SNDRV_PCM_STREAM_CAPTURE,  &capture_ops);
-+
-+      pcm->private_data=tsc2101;
-+      pcm->info_flags = 0;
-+      strncpy (pcm->name, "TSC2101 PCM", sizeof (pcm->name));
-+
-+      spin_lock_init (&tsc2101->s[SNDRV_PCM_STREAM_PLAYBACK].lock);
-+      tsc2101->s[SNDRV_PCM_STREAM_PLAYBACK].id      = "TSC2101 out";
-+      tsc2101->s[SNDRV_PCM_STREAM_PLAYBACK].sid     = SNDRV_PCM_STREAM_PLAYBACK;
-+      tsc2101->s[SNDRV_PCM_STREAM_PLAYBACK].dev = AUDIO_DMA_TX;
-+      if ((err=omap_request_dma (
-+                                      tsc2101->s[SNDRV_PCM_STREAM_PLAYBACK].dev,
-+                                      tsc2101->s[SNDRV_PCM_STREAM_PLAYBACK].id,
-+                                      tsc2101_playback_callback,
-+                                      (void *)&tsc2101->s[SNDRV_PCM_STREAM_PLAYBACK],
-+                                      &tsc2101->s[SNDRV_PCM_STREAM_PLAYBACK].channel)) < 0)
-+              return err;
-+      dprintk ("TX dev=%u channel=%u\n", tsc2101->s[SNDRV_PCM_STREAM_PLAYBACK].dev, tsc2101->s[SNDRV_PCM_STREAM_PLAYBACK].channel);
-+
-+      spin_lock_init (&tsc2101->s[SNDRV_PCM_STREAM_CAPTURE].lock);
-+      tsc2101->s[SNDRV_PCM_STREAM_CAPTURE].id      = "TSC2101 in";
-+      tsc2101->s[SNDRV_PCM_STREAM_CAPTURE].sid     = SNDRV_PCM_STREAM_CAPTURE;
-+      tsc2101->s[SNDRV_PCM_STREAM_CAPTURE].dev = AUDIO_DMA_RX;
-+      if ((err=omap_request_dma (
-+                                      tsc2101->s[SNDRV_PCM_STREAM_CAPTURE].dev,
-+                                      tsc2101->s[SNDRV_PCM_STREAM_CAPTURE].id,
-+                                      tsc2101_capture_callback,
-+                                      (void *)&tsc2101->s[SNDRV_PCM_STREAM_CAPTURE],
-+                                      &tsc2101->s[SNDRV_PCM_STREAM_CAPTURE].channel)) < 0)
-+              return err;
-+      dprintk ("RX dev=%u channel=%u\n", tsc2101->s[SNDRV_PCM_STREAM_CAPTURE].dev, tsc2101->s[SNDRV_PCM_STREAM_CAPTURE].channel);
-+
-+      tsc2101_audio_init (tsc2101);
-+
-+      tsc2101->pcm=pcm;
-+      dprintk ("[%s] pass\n", __FUNCTION__);
-+      return 0;
-+} /* snd_tsc2101_setup_pcm */
-+
-+void
-+snd_tsc2101_disable_pcm (snd_card_tsc2101_t *tsc2101) {
-+      dprintk ("[%s]\n", __FUNCTION__);
-+      omap_stop_dma (tsc2101->s[SNDRV_PCM_STREAM_PLAYBACK].channel);
-+      omap_free_dma (tsc2101->s[SNDRV_PCM_STREAM_PLAYBACK].channel);
-+      omap_stop_dma (tsc2101->s[SNDRV_PCM_STREAM_CAPTURE].channel);
-+      omap_free_dma (tsc2101->s[SNDRV_PCM_STREAM_CAPTURE].channel);
-+
-+      set_current_state(TASK_INTERRUPTIBLE);
-+      schedule_timeout(2);
-+
-+      omap_mcbsp_stop (AUDIO_MCBSP);
-+      omap_mcbsp_free (AUDIO_MCBSP);
-+
-+      omap_tsc2101_write(TSC2101_AUDIO_CODEC_REGISTERS, TSC2101_CODEC_POWER_CTRL, ~(CPC_SP1PWDN | CPC_SP2PWDN | CPC_BASSBC));
-+      omap_tsc2101_disable ();
-+      dprintk ("[%s] pass\n", __FUNCTION__);
-+} /* snd_tsc2101_disable_pcm */
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/sound/arm/omap-alsa-dma.c bt_kernel/sound/arm/omap-alsa-dma.c
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/sound/arm/omap-alsa-dma.c   2005-10-30 17:44:20.392618150 +0200
-+++ bt_kernel/sound/arm/omap-alsa-dma.c        2005-10-30 16:32:39.609796000 +0200
-@@ -325,9 +325,11 @@
-       int cfn = dma_size / (2 * cen);
-       FN_IN;
-       omap_set_dma_dest_params(channel, 0x05, 0x00,
--                               (OMAP1610_MCBSP1_BASE + 0x806));
--      omap_set_dma_src_params(channel, 0x00, 0x01, dma_ptr);
--      omap_set_dma_transfer_params(channel, dt, cen, cfn, 0x00);
-+                              (OMAP1610_MCBSP1_BASE + 0x806),
-+                              0, 0);
-+      omap_set_dma_src_params(channel, 0x00, 0x01, dma_ptr,
-+                              0, 0);
-+      omap_set_dma_transfer_params(channel, dt, cen, cfn, 0x00, 0, 0);
-       FN_OUT(0);
-       return 0;
- }
-@@ -341,9 +343,10 @@
-       int cfn = dma_size / (2 * cen);
-       FN_IN;
-       omap_set_dma_src_params(channel, 0x05, 0x00,
--                              (OMAP1610_MCBSP1_BASE + 0x802));
--      omap_set_dma_dest_params(channel, 0x00, 0x01, dma_ptr);
--      omap_set_dma_transfer_params(channel, dt, cen, cfn, 0x00);
-+                             (OMAP1610_MCBSP1_BASE + 0x802),
-+                             0, 0);
-+      omap_set_dma_dest_params(channel, 0x00, 0x01, dma_ptr, 0, 0);
-+      omap_set_dma_transfer_params(channel, dt, cen, cfn, 0x00, 0, 0);        
-       FN_OUT(0);
-       return 0;
- }
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/sound/oss/Kconfig bt_kernel/sound/oss/Kconfig
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/sound/oss/Kconfig   2005-10-30 17:44:20.459607487 +0200
-+++ bt_kernel/sound/oss/Kconfig        2005-10-22 03:52:45.687256000 +0300
-@@ -12,7 +12,7 @@
- config SOUND_OMAP_TSC2101
-       tristate "TSC2101 Stereo Codec"
--      depends on SOUND_OMAP && ( MACH_OMAP_H2 || MACH_OMAP_H3 )
-+      depends on SOUND_OMAP && ( MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_H6300)
-       select OMAP_TSC2101
-       select OMAP_UWIRE if ARCH_OMAP
-       ---help---
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/sound/oss/omap-audio-dma-intfc.c bt_kernel/sound/oss/omap-audio-dma-intfc.c
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/sound/oss/omap-audio-dma-intfc.c    2005-10-30 17:44:20.656576134 +0200
-+++ bt_kernel/sound/oss/omap-audio-dma-intfc.c 2005-10-30 16:32:39.609796000 +0200
-@@ -701,9 +701,10 @@
-       int cfn = dma_size / (2 * cen);
-       FN_IN;
-       omap_set_dma_dest_params(channel, 0x05, 0x00,
--                               (OMAP1610_MCBSP1_BASE + 0x806));
--      omap_set_dma_src_params(channel, 0x00, 0x01, dma_ptr);
--      omap_set_dma_transfer_params(channel, dt, cen, cfn, 0x00);
-+                               (OMAP1610_MCBSP1_BASE + 0x806),
-+                               0, 0);
-+      omap_set_dma_src_params(channel, 0x00, 0x01, dma_ptr, 0, 0);
-+      omap_set_dma_transfer_params(channel, dt, cen, cfn, 0x00, 0, 0);
-       FN_OUT(0);
-       return 0;
- }
-@@ -716,9 +717,10 @@
-       int cfn = dma_size / (2 * cen);
-       FN_IN;
-       omap_set_dma_src_params(channel, 0x05, 0x00,
--                              (OMAP1610_MCBSP1_BASE + 0x802));
--      omap_set_dma_dest_params(channel, 0x00, 0x01, dma_ptr);
--      omap_set_dma_transfer_params(channel, dt, cen, cfn, 0x00);
-+                              (OMAP1610_MCBSP1_BASE + 0x802),
-+                              0, 0);
-+      omap_set_dma_dest_params(channel, 0x00, 0x01, dma_ptr, 0, 0);
-+      omap_set_dma_transfer_params(channel, dt, cen, cfn, 0x00, 0, 0);
-       FN_OUT(0);
-       return 0;
- }
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/sound/oss/omap-audio-tsc2101.c bt_kernel/sound/oss/omap-audio-tsc2101.c
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/sound/oss/omap-audio-tsc2101.c      2005-10-30 17:44:20.697569609 +0200
-+++ bt_kernel/sound/oss/omap-audio-tsc2101.c   2005-10-22 03:52:45.687256000 +0300
-@@ -48,7 +48,7 @@
- #include "omap-audio.h"
- #include "omap-audio-dma-intfc.h"
- #include <asm/arch/mcbsp.h>
--#if CONFIG_ARCH_OMAP16XX
-+#if defined (CONFIG_ARCH_OMAP16XX) || defined (CONFIG_MACH_OMAP_H6300)
- #include <../drivers/ssi/omap-uwire.h>
- #include <asm/arch/dsp_common.h>
- #else
-@@ -72,6 +72,8 @@
- #if CONFIG_ARCH_OMAP16XX
- #define PLATFORM_NAME "OMAP16XX"
-+#elif CONFIG_MACH_OMAP_H6300
-+#define PLATFORM_NAME "OMAP15XX"
- #endif
- #if CONFIG_ARCH_OMAP16XX
-@@ -90,7 +92,7 @@
- #define LEAVE_CS                                0x80
- /* Select the McBSP For Audio */
--#if CONFIG_ARCH_OMAP16XX
-+#if defined (CONFIG_ARCH_OMAP16XX) || defined(CONFIG_MACH_OMAP_H6300)
- #define AUDIO_MCBSP                   OMAP_MCBSP1
- #else
- #error "UnSupported Configuration"
-@@ -124,7 +126,7 @@
- /*********** Debug Macros ********/
- /* To Generate a rather shrill tone -test the entire path */
- //#define TONE_GEN
--/* To Generate a tone for each keyclick - test the tsc,spi paths*/
-+///* To Generate a tone for each keyclick - test the tsc,spi paths*/
- //#define TEST_KEYCLICK
- /* To dump the tsc registers for debug */
- //#define TSC_DUMP_REGISTERS
-@@ -215,6 +217,17 @@
- };
- static struct omap_mcbsp_reg_cfg initial_config = {
-+#ifdef CONFIG_MACH_OMAP_H6300
-+      .spcr2 = 0x0005,
-+      .spcr1 = 0x0005,
-+      .rcr2  = 0x8041,
-+      .rcr1  = 0x8041,
-+      .xcr2  = 0x00a1,
-+      .xcr1  = 0x00a1,
-+      .srgr2 = 0xb000,
-+      .srgr1 = 0xb000,
-+      .pcr0  = 0x0081,
-+#else
-       .spcr2 = FREE | FRST | GRST | XRST | XINTM(3),
-       .spcr1 = RINTM(3) | RRST,
-       .rcr2  = RPHASE | RFRLEN2(OMAP_MCBSP_WORD_8) |
-@@ -238,6 +251,7 @@
- #endif                                /* tsc Master defs */
- #endif                                /* platform specific inits */
-+#endif /* CONFIG_MACH_OMAP_H6300 */
- };
- /***************************** MODULES SPECIFIC FUNCTION PROTOTYPES ********************/
-diff -Naur /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/usr/.gitignore bt_kernel/usr/.gitignore
---- /home/lamikr/own/h6340/kernel/linux-2.6.14-rc5/usr/.gitignore      2005-10-20 09:23:05.000000000 +0300
-+++ bt_kernel/usr/.gitignore   1970-01-01 02:00:00.000000000 +0200
-@@ -1,7 +0,0 @@
--#
--# Generated files
--#
--gen_init_cpio
--initramfs_data.cpio
--initramfs_data.cpio.gz
--initramfs_list
diff --git a/packages/linux/linux-h6300-omap1-2.6.14.3/.mtn2git_empty b/packages/linux/linux-h6300-omap1-2.6.14.3/.mtn2git_empty
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/packages/linux/linux-h6300-omap1-2.6.14.3/defconfig b/packages/linux/linux-h6300-omap1-2.6.14.3/defconfig
new file mode 100644 (file)
index 0000000..40f2840
--- /dev/null
@@ -0,0 +1,1568 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.14.1-omap1-h6300
+# Wed Nov 23 00:43:00 2005
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+# CONFIG_CLEAN_COMPILE is not set
+CONFIG_BROKEN=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+CONFIG_ARCH_OMAP=y
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_AAEC2000 is not set
+
+#
+# TI OMAP Implementations
+#
+CONFIG_ARCH_OMAP1=y
+# CONFIG_ARCH_OMAP2 is not set
+
+#
+# OMAP Feature Selections
+#
+# CONFIG_OMAP_RESET_CLOCKS is not set
+# CONFIG_OMAP_BOOT_TAG is not set
+CONFIG_OMAP_MUX=y
+# CONFIG_OMAP_MUX_DEBUG is not set
+CONFIG_OMAP_MUX_WARNINGS=y
+CONFIG_OMAP_MPU_TIMER=y
+# CONFIG_OMAP_32K_TIMER is not set
+CONFIG_OMAP_LL_DEBUG_UART1=y
+# CONFIG_OMAP_LL_DEBUG_UART2 is not set
+# CONFIG_OMAP_LL_DEBUG_UART3 is not set
+CONFIG_OMAP_SERIAL_WAKE=y
+
+#
+# OMAP Core Type
+#
+# CONFIG_ARCH_OMAP730 is not set
+CONFIG_ARCH_OMAP15XX=y
+# CONFIG_ARCH_OMAP16XX is not set
+
+#
+# OMAP Board Type
+#
+# CONFIG_MACH_OMAP_INNOVATOR is not set
+CONFIG_MACH_OMAP_H6300=y
+# CONFIG_MACH_VOICEBLUE is not set
+# CONFIG_MACH_NETSTAR is not set
+# CONFIG_MACH_OMAP_PALMTE is not set
+# CONFIG_MACH_OMAP_GENERIC is not set
+
+#
+# OMAP CPU Speed
+#
+# CONFIG_OMAP_CLOCKS_SET_BY_BOOTLOADER is not set
+CONFIG_OMAP_ARM_168MHZ=y
+CONFIG_OMAP_ARM_150MHZ=y
+CONFIG_OMAP_ARM_120MHZ=y
+CONFIG_OMAP_ARM_60MHZ=y
+CONFIG_OMAP_ARM_30MHZ=y
+CONFIG_OMAP_DSP=y
+CONFIG_OMAP_DSP_MBCMD_VERBOSE=y
+CONFIG_OMAP_DSP_TASK_MULTIOPEN=y
+CONFIG_OMAP_DSP_FBEXPORT=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM925T=y
+CONFIG_CPU_32v4=y
+CONFIG_CPU_ABRT_EV4T=y
+CONFIG_CPU_CACHE_V4WT=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+CONFIG_CPU_DCACHE_WRITETHROUGH=y
+
+#
+# Bus support
+#
+CONFIG_ISA_DMA_API=y
+
+#
+# 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
+#
+
+#
+# Kernel Features
+#
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_NO_IDLE_HZ 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_LEDS=y
+CONFIG_LEDS_TIMER=y
+CONFIG_LEDS_CPU=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=tty0 root=/dev/nfs nfsroot=192.168.2.1:/opt/h6300/rootfs,rsize=8192,wsize=8192 ip=192.168.2.2:192.168.2.1:192.168.2.1:255.0.0.0:ipaq:"
+# CONFIG_XIP_KERNEL is not set
+
+#
+# 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=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+CONFIG_FPE_NWFPE_XP=y
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_AOUT=y
+CONFIG_BINFMT_MISC=y
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+CONFIG_PM=y
+CONFIG_APM=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+CONFIG_IPV6=y
+CONFIG_IPV6_PRIVACY=y
+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
+CONFIG_BRIDGE_NETFILTER=y
+# CONFIG_NETFILTER_NETLINK is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CONNTRACK_MARK=y
+# CONFIG_IP_NF_CONNTRACK_EVENTS is not set
+CONFIG_IP_NF_CT_PROTO_SCTP=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+# CONFIG_IP_NF_NETBIOS_NS is not set
+CONFIG_IP_NF_TFTP=m
+# CONFIG_IP_NF_AMANDA is not set
+# CONFIG_IP_NF_PPTP is not set
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_LIMIT=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_MAC=m
+CONFIG_IP_NF_MATCH_PKTTYPE=m
+# CONFIG_IP_NF_MATCH_MARK is not set
+# CONFIG_IP_NF_MATCH_MULTIPORT is not set
+# CONFIG_IP_NF_MATCH_TOS is not set
+# CONFIG_IP_NF_MATCH_RECENT is not set
+# CONFIG_IP_NF_MATCH_ECN is not set
+# CONFIG_IP_NF_MATCH_DSCP is not set
+# CONFIG_IP_NF_MATCH_AH_ESP is not set
+# CONFIG_IP_NF_MATCH_LENGTH is not set
+# CONFIG_IP_NF_MATCH_TTL is not set
+# CONFIG_IP_NF_MATCH_TCPMSS is not set
+# CONFIG_IP_NF_MATCH_HELPER is not set
+# CONFIG_IP_NF_MATCH_STATE is not set
+# CONFIG_IP_NF_MATCH_CONNTRACK is not set
+# CONFIG_IP_NF_MATCH_OWNER is not set
+# CONFIG_IP_NF_MATCH_PHYSDEV is not set
+# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
+# CONFIG_IP_NF_MATCH_REALM is not set
+# CONFIG_IP_NF_MATCH_SCTP is not set
+# CONFIG_IP_NF_MATCH_DCCP is not set
+# CONFIG_IP_NF_MATCH_COMMENT is not set
+# CONFIG_IP_NF_MATCH_CONNMARK is not set
+# CONFIG_IP_NF_MATCH_CONNBYTES is not set
+# CONFIG_IP_NF_MATCH_HASHLIMIT is not set
+# CONFIG_IP_NF_MATCH_STRING is not set
+# CONFIG_IP_NF_FILTER is not set
+# CONFIG_IP_NF_TARGET_LOG is not set
+# CONFIG_IP_NF_TARGET_ULOG is not set
+# CONFIG_IP_NF_TARGET_TCPMSS is not set
+# CONFIG_IP_NF_TARGET_NFQUEUE is not set
+# CONFIG_IP_NF_NAT is not set
+CONFIG_IP_NF_MANGLE=m
+# CONFIG_IP_NF_TARGET_TOS is not set
+# CONFIG_IP_NF_TARGET_ECN is not set
+# CONFIG_IP_NF_TARGET_DSCP is not set
+# CONFIG_IP_NF_TARGET_MARK is not set
+# CONFIG_IP_NF_TARGET_CLASSIFY is not set
+# CONFIG_IP_NF_TARGET_TTL is not set
+# CONFIG_IP_NF_TARGET_CONNMARK is not set
+# CONFIG_IP_NF_TARGET_CLUSTERIP is not set
+# CONFIG_IP_NF_RAW is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+CONFIG_IP6_NF_QUEUE=m
+CONFIG_IP6_NF_IPTABLES=m
+# CONFIG_IP6_NF_MATCH_LIMIT is not set
+CONFIG_IP6_NF_MATCH_MAC=m
+CONFIG_IP6_NF_MATCH_RT=m
+# CONFIG_IP6_NF_MATCH_OPTS is not set
+# CONFIG_IP6_NF_MATCH_FRAG is not set
+# CONFIG_IP6_NF_MATCH_HL is not set
+# CONFIG_IP6_NF_MATCH_MULTIPORT is not set
+# CONFIG_IP6_NF_MATCH_OWNER is not set
+# CONFIG_IP6_NF_MATCH_MARK is not set
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+# CONFIG_IP6_NF_MATCH_AHESP is not set
+# CONFIG_IP6_NF_MATCH_LENGTH is not set
+# CONFIG_IP6_NF_MATCH_EUI64 is not set
+# CONFIG_IP6_NF_MATCH_PHYSDEV is not set
+CONFIG_IP6_NF_FILTER=m
+# CONFIG_IP6_NF_TARGET_LOG is not set
+# CONFIG_IP6_NF_TARGET_REJECT is not set
+# CONFIG_IP6_NF_TARGET_NFQUEUE is not set
+CONFIG_IP6_NF_MANGLE=m
+# CONFIG_IP6_NF_TARGET_MARK is not set
+# CONFIG_IP6_NF_TARGET_HL is not set
+CONFIG_IP6_NF_RAW=m
+
+#
+# Bridge: Netfilter Configuration
+#
+CONFIG_BRIDGE_NF_EBTABLES=m
+# CONFIG_BRIDGE_EBT_BROUTE is not set
+# CONFIG_BRIDGE_EBT_T_FILTER is not set
+# CONFIG_BRIDGE_EBT_T_NAT is not set
+# CONFIG_BRIDGE_EBT_802_3 is not set
+# CONFIG_BRIDGE_EBT_AMONG is not set
+# CONFIG_BRIDGE_EBT_ARP is not set
+# CONFIG_BRIDGE_EBT_IP is not set
+# CONFIG_BRIDGE_EBT_LIMIT is not set
+# CONFIG_BRIDGE_EBT_MARK is not set
+# CONFIG_BRIDGE_EBT_PKTTYPE is not set
+# CONFIG_BRIDGE_EBT_STP is not set
+# CONFIG_BRIDGE_EBT_VLAN is not set
+# CONFIG_BRIDGE_EBT_ARPREPLY is not set
+# CONFIG_BRIDGE_EBT_DNAT is not set
+# CONFIG_BRIDGE_EBT_MARK_T is not set
+# CONFIG_BRIDGE_EBT_REDIRECT is not set
+# CONFIG_BRIDGE_EBT_SNAT is not set
+# CONFIG_BRIDGE_EBT_LOG is not set
+# CONFIG_BRIDGE_EBT_ULOG is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+CONFIG_BRIDGE=y
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+CONFIG_IRDA_ULTRA=y
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+# CONFIG_IRTTY_SIR 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_NSC_FIR is not set
+# CONFIG_WINBOND_FIR is not set
+CONFIG_OMAP1610_IR=m
+CONFIG_SMC_IRCC_FIR=m
+# CONFIG_ALI_FIR is not set
+# CONFIG_VIA_FIR is not set
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+# CONFIG_BT_SCO is not set
+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_HCIUART_BCSP_TXCRC is not set
+# CONFIG_BT_HCIBCM203X is not set
+# CONFIG_BT_HCIBPA10X is not set
+# CONFIG_BT_HCIBFUSB is not set
+# CONFIG_BT_HCIDTL1 is not set
+# CONFIG_BT_HCIBT3C is not set
+# CONFIG_BT_HCIBLUECARD is not set
+# CONFIG_BT_HCIBTUART is not set
+CONFIG_BT_HCIVHCI=m
+CONFIG_BT_H6300=m
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=m
+CONFIG_MTD_JEDECPROBE=m
+CONFIG_MTD_GEN_PROBE=m
+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=m
+CONFIG_MTD_CFI_AMDSTD=m
+CONFIG_MTD_CFI_AMDSTD_RETRY=1
+CONFIG_MTD_CFI_STAA=m
+CONFIG_MTD_CFI_UTIL=m
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+CONFIG_MTD_ABSENT=m
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+# CONFIG_MTD_XIP is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+CONFIG_MTD_PHYSMAP=m
+CONFIG_MTD_PHYSMAP_START=0x8000000
+CONFIG_MTD_PHYSMAP_LEN=0x4000000
+CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_EDB7312 is not set
+# CONFIG_MTD_IMPA7 is not set
+# CONFIG_MTD_OMAP_NOR is not set
+# CONFIG_MTD_PCMCIA is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+CONFIG_MTD_SLRAM=m
+CONFIG_MTD_PHRAM=m
+CONFIG_MTD_MTDRAM=m
+CONFIG_MTDRAM_TOTAL_SIZE=4096
+CONFIG_MTDRAM_ERASE_SIZE=128
+CONFIG_MTD_BLKMTD=m
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+CONFIG_MTD_DOC2000=m
+CONFIG_MTD_DOC2001=m
+CONFIG_MTD_DOC2001PLUS=m
+CONFIG_MTD_DOCPROBE=m
+CONFIG_MTD_DOCECC=m
+CONFIG_MTD_DOCPROBE_ADVANCED=y
+CONFIG_MTD_DOCPROBE_ADDRESS=0x0000
+CONFIG_MTD_DOCPROBE_HIGH=y
+CONFIG_MTD_DOCPROBE_55AA=y
+
+#
+# NAND Flash Device Drivers
+#
+CONFIG_MTD_NAND=m
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_TOTO is not set
+CONFIG_MTD_NAND_IDS=m
+CONFIG_MTD_NAND_DISKONCHIP=m
+CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED=y
+CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0x0
+# CONFIG_MTD_NAND_DISKONCHIP_PROBE_HIGH is not set
+CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE=y
+# CONFIG_MTD_NAND_NANDSIM is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_SMC91X=y
+# CONFIG_DM9000 is not set
+
+#
+# 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=y
+# 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_AIRO is not set
+# CONFIG_HERMES is not set
+CONFIG_ATMEL=y
+
+#
+# Wireless 802.11b Pcmcia/Cardbus cards support
+#
+# CONFIG_AIRO_CS is not set
+# CONFIG_PCMCIA_ATMEL is not set
+# CONFIG_PCMCIA_WL3501 is not set
+# CONFIG_HOSTAP is not set
+CONFIG_NET_WIRELESS=y
+CONFIG_ACX=m
+# CONFIG_ACX_USB is not set
+CONFIG_ACX_CFI=y
+
+#
+# PCMCIA network device support
+#
+# CONFIG_NET_PCMCIA is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+CONFIG_PPP=y
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=y
+CONFIG_PPP_SYNC_TTY=y
+CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_BSDCOMP=y
+CONFIG_PPPOE=y
+# 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 is not set
+# 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
+
+#
+# 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_OMAP=m
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_SERIAL=y
+# CONFIG_MOUSE_VSXXXAA 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_OMAP=m
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=m
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIO_RAW=y
+# 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=y
+# CONFIG_SERIAL_8250_CONSOLE is not set
+# CONFIG_SERIAL_8250_CS is not set
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+
+#
+# Watchdog Device Drivers
+#
+CONFIG_SOFT_WATCHDOG=m
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_NVRAM=y
+# CONFIG_RTC is not set
+CONFIG_OMAP_RTC=y
+# 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_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+
+#
+# I2C support
+#
+CONFIG_I2C=m
+CONFIG_I2C_CHARDEV=m
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=m
+CONFIG_I2C_ALGOPCF=m
+CONFIG_I2C_ALGOPCA=m
+
+#
+# I2C Hardware Bus support
+#
+CONFIG_I2C_PARPORT_LIGHT=m
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_PCA_ISA is not set
+CONFIG_I2C_OMAP=m
+
+#
+# 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_PCA9535=m
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_TPS65010 is not set
+CONFIG_SENSORS_TLV320AIC23=m
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia Capabilities Port drivers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+CONFIG_FB_SOFT_CURSOR=y
+# CONFIG_FB_MACMODES is not set
+CONFIG_FB_MODE_HELPERS=y
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_OMAP=y
+CONFIG_FB_OMAP_LCDC_INTERNAL=y
+# CONFIG_FB_OMAP_LCDC_EXTERNAL is not set
+CONFIG_FB_OMAP_DMA_TUNE=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_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
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+CONFIG_LOGO_LINUX_VGA16=y
+# 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=y
+CONFIG_LCD_DEVICE=y
+
+#
+# Telephony Support
+#
+CONFIG_PHONE=m
+# CONFIG_PHONE_IXJ is not set
+CONFIG_GSM_H6300=m
+
+#
+# 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_MIXER_OSS is not set
+# CONFIG_SND_PCM_OSS is not set
+# 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_OMAP_AIC23 is not set
+CONFIG_SND_OMAP_TSC2101=m
+
+#
+# USB devices
+#
+# CONFIG_SND_USB_AUDIO is not set
+
+#
+# PCMCIA devices
+#
+
+#
+# Open Sound System
+#
+CONFIG_SOUND_PRIME=m
+CONFIG_SOUND_OMAP=m
+CONFIG_SOUND_OMAP_TSC2101=m
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+# CONFIG_SOUND_OSS is not set
+# CONFIG_SOUND_TVMIXER is not set
+# CONFIG_SOUND_AD1980 is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB=y
+CONFIG_USB_DEBUG=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set
+
+#
+# USB Bluetooth TTY can only be used with disabled Bluetooth subsystem
+#
+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 is not set
+
+#
+# USB Input Devices
+#
+# CONFIG_USB_HID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_ITMTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_AX8817X=y
+CONFIG_USB_NET_CDCETHER=y
+# CONFIG_USB_NET_GL620A is not set
+CONFIG_USB_NET_NET1080=y
+# CONFIG_USB_NET_PLUSB is not set
+# CONFIG_USB_NET_RNDIS_HOST is not set
+# CONFIG_USB_NET_CDC_SUBSET is not set
+CONFIG_USB_NET_ZAURUS=y
+# CONFIG_USB_ZD1201 is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=y
+CONFIG_USB_SERIAL_CONSOLE=y
+CONFIG_USB_SERIAL_GENERIC=y
+# CONFIG_USB_SERIAL_AIRPRIME is not set
+# CONFIG_USB_SERIAL_BELKIN is not set
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+# CONFIG_USB_SERIAL_CP2101 is not set
+# CONFIG_USB_SERIAL_CYPRESS_M8 is not set
+# CONFIG_USB_SERIAL_EMPEG is not set
+# CONFIG_USB_SERIAL_FTDI_SIO is not set
+CONFIG_USB_SERIAL_VISOR=y
+CONFIG_USB_SERIAL_IPAQ=y
+# CONFIG_USB_SERIAL_IR is not set
+# CONFIG_USB_SERIAL_EDGEPORT is not set
+# CONFIG_USB_SERIAL_EDGEPORT_TI is not set
+# CONFIG_USB_SERIAL_GARMIN is not set
+# CONFIG_USB_SERIAL_IPW is not set
+# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
+# CONFIG_USB_SERIAL_KEYSPAN is not set
+# CONFIG_USB_SERIAL_KLSI is not set
+# CONFIG_USB_SERIAL_KOBIL_SCT is not set
+# CONFIG_USB_SERIAL_MCT_U232 is not set
+# CONFIG_USB_SERIAL_PL2303 is not set
+# CONFIG_USB_SERIAL_HP4X is not set
+# CONFIG_USB_SERIAL_SAFE is not set
+# CONFIG_USB_SERIAL_TI is not set
+# CONFIG_USB_SERIAL_CYBERJACK is not set
+# CONFIG_USB_SERIAL_XIRCOM is not set
+# CONFIG_USB_SERIAL_OPTION is not set
+# CONFIG_USB_SERIAL_OMNINET is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_DEBUG_FILES=y
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_PXA2XX is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+CONFIG_USB_GADGET_OMAP=y
+CONFIG_USB_OMAP=y
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+# CONFIG_USB_GADGET_DUALSPEED is not set
+# CONFIG_USB_ZERO is not set
+CONFIG_USB_ETH=y
+# CONFIG_USB_ETH_RNDIS is not set
+# CONFIG_USB_GADGETFS is not set
+# CONFIG_USB_FILE_STORAGE is not set
+# CONFIG_USB_G_SERIAL is not set
+
+#
+# MMC/SD Card support
+#
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BROKEN_RFD=y
+CONFIG_MMC_BULKTRANSFER=y
+CONFIG_MMC_OMAP=y
+# CONFIG_MMC_WBSD is not set
+
+#
+# Synchronous Serial Interfaces (SSI)
+#
+CONFIG_OMAP_UWIRE=y
+CONFIG_OMAP_TSC2101=y
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+# CONFIG_EXT2_FS_XIP is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+CONFIG_ROMFS_FS=y
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_AUTOFS_FS is not set
+CONFIG_AUTOFS4_FS=y
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS_FS=y
+CONFIG_JFFS_FS_VERBOSE=0
+CONFIG_JFFS_PROC_FS=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=4
+CONFIG_JFFS2_FS_WRITEBUFFER=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=y
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII 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 is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOG_BUF_SHIFT=17
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_WAITQ is not set
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+# 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_DES=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_DEFLATE=m
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_REED_SOLOMON=m
+CONFIG_REED_SOLOMON_DEC16=y
diff --git a/packages/linux/linux-h6300-omap1-2.6.14.3/patch-linux-2614-omap2-to-2614_3-omap1-h6300 b/packages/linux/linux-h6300-omap1-2.6.14.3/patch-linux-2614-omap2-to-2614_3-omap1-h6300
new file mode 100644 (file)
index 0000000..e7e442e
--- /dev/null
@@ -0,0 +1,32978 @@
+diff -Naur linux-2.6.14-omap2/arch/arm/configs/omap_h6300_defconfig linux-h6300-omap2-2.6.14.3/arch/arm/configs/omap_h6300_defconfig
+--- linux-2.6.14-omap2/arch/arm/configs/omap_h6300_defconfig   1970-01-01 02:00:00.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/arch/arm/configs/omap_h6300_defconfig   2005-11-11 04:13:42.000000000 +0200
+@@ -0,0 +1,1538 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.14-omap1-h6300
++# Thu Nov 10 05:21:43 2005
++#
++CONFIG_ARM=y
++CONFIG_MMU=y
++CONFIG_UID16=y
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++
++#
++# Code maturity level options
++#
++CONFIG_EXPERIMENTAL=y
++# CONFIG_CLEAN_COMPILE is not set
++CONFIG_BROKEN=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++
++#
++# General setup
++#
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_POSIX_MQUEUE=y
++CONFIG_BSD_PROCESS_ACCT=y
++CONFIG_BSD_PROCESS_ACCT_V3=y
++CONFIG_SYSCTL=y
++# CONFIG_AUDIT is not set
++CONFIG_HOTPLUG=y
++CONFIG_KOBJECT_UEVENT=y
++CONFIG_IKCONFIG=y
++CONFIG_IKCONFIG_PROC=y
++CONFIG_INITRAMFS_SOURCE=""
++CONFIG_EMBEDDED=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_ALL is not set
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_EPOLL=y
++CONFIG_CC_OPTIMIZE_FOR_SIZE=y
++CONFIG_SHMEM=y
++CONFIG_CC_ALIGN_FUNCTIONS=0
++CONFIG_CC_ALIGN_LABELS=0
++CONFIG_CC_ALIGN_LOOPS=0
++CONFIG_CC_ALIGN_JUMPS=0
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++
++#
++# Loadable module support
++#
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++CONFIG_MODULE_FORCE_UNLOAD=y
++CONFIG_OBSOLETE_MODPARM=y
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++
++#
++# System Type
++#
++# CONFIG_ARCH_CLPS7500 is not set
++# CONFIG_ARCH_CLPS711X is not set
++# CONFIG_ARCH_CO285 is not set
++# CONFIG_ARCH_EBSA110 is not set
++# CONFIG_ARCH_CAMELOT is not set
++# CONFIG_ARCH_FOOTBRIDGE is not set
++# CONFIG_ARCH_INTEGRATOR is not set
++# CONFIG_ARCH_IOP3XX is not set
++# CONFIG_ARCH_IXP4XX is not set
++# CONFIG_ARCH_IXP2000 is not set
++# CONFIG_ARCH_L7200 is not set
++# CONFIG_ARCH_PXA is not set
++# CONFIG_ARCH_RPC is not set
++# CONFIG_ARCH_SA1100 is not set
++# CONFIG_ARCH_S3C2410 is not set
++# CONFIG_ARCH_SHARK is not set
++# CONFIG_ARCH_LH7A40X is not set
++CONFIG_ARCH_OMAP=y
++# CONFIG_ARCH_VERSATILE is not set
++# CONFIG_ARCH_IMX is not set
++# CONFIG_ARCH_H720X is not set
++# CONFIG_ARCH_AAEC2000 is not set
++
++#
++# TI OMAP Implementations
++#
++CONFIG_ARCH_OMAP1=y
++# CONFIG_ARCH_OMAP2 is not set
++
++#
++# OMAP Feature Selections
++#
++# CONFIG_OMAP_RESET_CLOCKS is not set
++# CONFIG_OMAP_BOOT_TAG is not set
++CONFIG_OMAP_MUX=y
++# CONFIG_OMAP_MUX_DEBUG is not set
++CONFIG_OMAP_MUX_WARNINGS=y
++CONFIG_OMAP_MPU_TIMER=y
++# CONFIG_OMAP_32K_TIMER is not set
++CONFIG_OMAP_LL_DEBUG_UART1=y
++# CONFIG_OMAP_LL_DEBUG_UART2 is not set
++# CONFIG_OMAP_LL_DEBUG_UART3 is not set
++CONFIG_OMAP_SERIAL_WAKE=y
++
++#
++# OMAP Core Type
++#
++# CONFIG_ARCH_OMAP730 is not set
++CONFIG_ARCH_OMAP15XX=y
++# CONFIG_ARCH_OMAP16XX is not set
++
++#
++# OMAP Board Type
++#
++# CONFIG_MACH_OMAP_INNOVATOR is not set
++CONFIG_MACH_OMAP_H6300=y
++# CONFIG_MACH_VOICEBLUE is not set
++# CONFIG_MACH_NETSTAR is not set
++# CONFIG_MACH_OMAP_PALMTE is not set
++# CONFIG_MACH_OMAP_GENERIC is not set
++
++#
++# OMAP CPU Speed
++#
++# CONFIG_OMAP_CLOCKS_SET_BY_BOOTLOADER is not set
++CONFIG_OMAP_ARM_168MHZ=y
++CONFIG_OMAP_ARM_150MHZ=y
++CONFIG_OMAP_ARM_120MHZ=y
++CONFIG_OMAP_ARM_60MHZ=y
++CONFIG_OMAP_ARM_30MHZ=y
++CONFIG_OMAP_DSP=y
++CONFIG_OMAP_DSP_MBCMD_VERBOSE=y
++CONFIG_OMAP_DSP_TASK_MULTIOPEN=y
++CONFIG_OMAP_DSP_FBEXPORT=y
++
++#
++# Processor Type
++#
++CONFIG_CPU_32=y
++CONFIG_CPU_ARM925T=y
++CONFIG_CPU_32v4=y
++CONFIG_CPU_ABRT_EV4T=y
++CONFIG_CPU_CACHE_V4WT=y
++CONFIG_CPU_CACHE_VIVT=y
++CONFIG_CPU_COPY_V4WB=y
++CONFIG_CPU_TLB_V4WBI=y
++
++#
++# Processor Features
++#
++CONFIG_ARM_THUMB=y
++# CONFIG_CPU_ICACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_DISABLE is not set
++CONFIG_CPU_DCACHE_WRITETHROUGH=y
++
++#
++# Bus support
++#
++CONFIG_ISA_DMA_API=y
++
++#
++# 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
++#
++
++#
++# Kernel Features
++#
++# CONFIG_SMP is not set
++# CONFIG_PREEMPT is not set
++# CONFIG_NO_IDLE_HZ 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_LEDS=y
++CONFIG_LEDS_TIMER=y
++CONFIG_LEDS_CPU=y
++CONFIG_ALIGNMENT_TRAP=y
++
++#
++# Boot options
++#
++CONFIG_ZBOOT_ROM_TEXT=0x0
++CONFIG_ZBOOT_ROM_BSS=0x0
++CONFIG_CMDLINE="console=tty0 root=/dev/nfs nfsroot=192.168.2.1:/opt/h6300/rootfs,rsize=8192,wsize=8192 ip=192.168.2.2:192.168.2.1:192.168.2.1:255.0.0.0:ipaq:"
++# CONFIG_XIP_KERNEL is not set
++
++#
++# 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=y
++CONFIG_CPU_FREQ_GOV_USERSPACE=y
++CONFIG_CPU_FREQ_GOV_ONDEMAND=y
++# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
++
++#
++# Floating point emulation
++#
++
++#
++# At least one emulation must be selected
++#
++CONFIG_FPE_NWFPE=y
++CONFIG_FPE_NWFPE_XP=y
++# CONFIG_FPE_FASTFPE is not set
++
++#
++# Userspace binary formats
++#
++CONFIG_BINFMT_ELF=y
++CONFIG_BINFMT_AOUT=y
++CONFIG_BINFMT_MISC=y
++# CONFIG_ARTHUR is not set
++
++#
++# Power management options
++#
++CONFIG_PM=y
++CONFIG_APM=y
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++CONFIG_XFRM_USER=y
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++CONFIG_IP_PNP_RARP=y
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++CONFIG_INET_AH=m
++CONFIG_INET_ESP=m
++CONFIG_INET_IPCOMP=m
++CONFIG_INET_TUNNEL=m
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_BIC=y
++
++#
++# IP: Virtual Server Configuration
++#
++# CONFIG_IP_VS is not set
++CONFIG_IPV6=y
++CONFIG_IPV6_PRIVACY=y
++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
++CONFIG_BRIDGE_NETFILTER=y
++# CONFIG_NETFILTER_NETLINK is not set
++
++#
++# IP: Netfilter Configuration
++#
++CONFIG_IP_NF_CONNTRACK=m
++CONFIG_IP_NF_CT_ACCT=y
++CONFIG_IP_NF_CONNTRACK_MARK=y
++# CONFIG_IP_NF_CONNTRACK_EVENTS is not set
++CONFIG_IP_NF_CT_PROTO_SCTP=m
++CONFIG_IP_NF_FTP=m
++CONFIG_IP_NF_IRC=m
++# CONFIG_IP_NF_NETBIOS_NS is not set
++CONFIG_IP_NF_TFTP=m
++# CONFIG_IP_NF_AMANDA is not set
++# CONFIG_IP_NF_PPTP is not set
++CONFIG_IP_NF_QUEUE=m
++CONFIG_IP_NF_IPTABLES=m
++CONFIG_IP_NF_MATCH_LIMIT=m
++CONFIG_IP_NF_MATCH_IPRANGE=m
++CONFIG_IP_NF_MATCH_MAC=m
++CONFIG_IP_NF_MATCH_PKTTYPE=m
++# CONFIG_IP_NF_MATCH_MARK is not set
++# CONFIG_IP_NF_MATCH_MULTIPORT is not set
++# CONFIG_IP_NF_MATCH_TOS is not set
++# CONFIG_IP_NF_MATCH_RECENT is not set
++# CONFIG_IP_NF_MATCH_ECN is not set
++# CONFIG_IP_NF_MATCH_DSCP is not set
++# CONFIG_IP_NF_MATCH_AH_ESP is not set
++# CONFIG_IP_NF_MATCH_LENGTH is not set
++# CONFIG_IP_NF_MATCH_TTL is not set
++# CONFIG_IP_NF_MATCH_TCPMSS is not set
++# CONFIG_IP_NF_MATCH_HELPER is not set
++# CONFIG_IP_NF_MATCH_STATE is not set
++# CONFIG_IP_NF_MATCH_CONNTRACK is not set
++# CONFIG_IP_NF_MATCH_OWNER is not set
++# CONFIG_IP_NF_MATCH_PHYSDEV is not set
++# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
++# CONFIG_IP_NF_MATCH_REALM is not set
++# CONFIG_IP_NF_MATCH_SCTP is not set
++# CONFIG_IP_NF_MATCH_DCCP is not set
++# CONFIG_IP_NF_MATCH_COMMENT is not set
++# CONFIG_IP_NF_MATCH_CONNMARK is not set
++# CONFIG_IP_NF_MATCH_CONNBYTES is not set
++# CONFIG_IP_NF_MATCH_HASHLIMIT is not set
++# CONFIG_IP_NF_MATCH_STRING is not set
++# CONFIG_IP_NF_FILTER is not set
++# CONFIG_IP_NF_TARGET_LOG is not set
++# CONFIG_IP_NF_TARGET_ULOG is not set
++# CONFIG_IP_NF_TARGET_TCPMSS is not set
++# CONFIG_IP_NF_TARGET_NFQUEUE is not set
++# CONFIG_IP_NF_NAT is not set
++CONFIG_IP_NF_MANGLE=m
++# CONFIG_IP_NF_TARGET_TOS is not set
++# CONFIG_IP_NF_TARGET_ECN is not set
++# CONFIG_IP_NF_TARGET_DSCP is not set
++# CONFIG_IP_NF_TARGET_MARK is not set
++# CONFIG_IP_NF_TARGET_CLASSIFY is not set
++# CONFIG_IP_NF_TARGET_TTL is not set
++# CONFIG_IP_NF_TARGET_CONNMARK is not set
++# CONFIG_IP_NF_TARGET_CLUSTERIP is not set
++# CONFIG_IP_NF_RAW is not set
++# CONFIG_IP_NF_ARPTABLES is not set
++
++#
++# IPv6: Netfilter Configuration (EXPERIMENTAL)
++#
++CONFIG_IP6_NF_QUEUE=m
++CONFIG_IP6_NF_IPTABLES=m
++# CONFIG_IP6_NF_MATCH_LIMIT is not set
++CONFIG_IP6_NF_MATCH_MAC=m
++CONFIG_IP6_NF_MATCH_RT=m
++# CONFIG_IP6_NF_MATCH_OPTS is not set
++# CONFIG_IP6_NF_MATCH_FRAG is not set
++# CONFIG_IP6_NF_MATCH_HL is not set
++# CONFIG_IP6_NF_MATCH_MULTIPORT is not set
++# CONFIG_IP6_NF_MATCH_OWNER is not set
++# CONFIG_IP6_NF_MATCH_MARK is not set
++CONFIG_IP6_NF_MATCH_IPV6HEADER=m
++# CONFIG_IP6_NF_MATCH_AHESP is not set
++# CONFIG_IP6_NF_MATCH_LENGTH is not set
++# CONFIG_IP6_NF_MATCH_EUI64 is not set
++# CONFIG_IP6_NF_MATCH_PHYSDEV is not set
++CONFIG_IP6_NF_FILTER=m
++# CONFIG_IP6_NF_TARGET_LOG is not set
++# CONFIG_IP6_NF_TARGET_REJECT is not set
++# CONFIG_IP6_NF_TARGET_NFQUEUE is not set
++CONFIG_IP6_NF_MANGLE=m
++# CONFIG_IP6_NF_TARGET_MARK is not set
++# CONFIG_IP6_NF_TARGET_HL is not set
++CONFIG_IP6_NF_RAW=m
++
++#
++# Bridge: Netfilter Configuration
++#
++CONFIG_BRIDGE_NF_EBTABLES=m
++# CONFIG_BRIDGE_EBT_BROUTE is not set
++# CONFIG_BRIDGE_EBT_T_FILTER is not set
++# CONFIG_BRIDGE_EBT_T_NAT is not set
++# CONFIG_BRIDGE_EBT_802_3 is not set
++# CONFIG_BRIDGE_EBT_AMONG is not set
++# CONFIG_BRIDGE_EBT_ARP is not set
++# CONFIG_BRIDGE_EBT_IP is not set
++# CONFIG_BRIDGE_EBT_LIMIT is not set
++# CONFIG_BRIDGE_EBT_MARK is not set
++# CONFIG_BRIDGE_EBT_PKTTYPE is not set
++# CONFIG_BRIDGE_EBT_STP is not set
++# CONFIG_BRIDGE_EBT_VLAN is not set
++# CONFIG_BRIDGE_EBT_ARPREPLY is not set
++# CONFIG_BRIDGE_EBT_DNAT is not set
++# CONFIG_BRIDGE_EBT_MARK_T is not set
++# CONFIG_BRIDGE_EBT_REDIRECT is not set
++# CONFIG_BRIDGE_EBT_SNAT is not set
++# CONFIG_BRIDGE_EBT_LOG is not set
++# CONFIG_BRIDGE_EBT_ULOG is not set
++
++#
++# DCCP Configuration (EXPERIMENTAL)
++#
++# CONFIG_IP_DCCP is not set
++
++#
++# SCTP Configuration (EXPERIMENTAL)
++#
++# CONFIG_IP_SCTP is not set
++# CONFIG_ATM is not set
++CONFIG_BRIDGE=y
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_NET_DIVERT is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++# CONFIG_NET_CLS_ROUTE is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++CONFIG_IRDA=m
++
++#
++# IrDA protocols
++#
++CONFIG_IRLAN=m
++CONFIG_IRNET=m
++CONFIG_IRCOMM=m
++CONFIG_IRDA_ULTRA=y
++
++#
++# IrDA options
++#
++CONFIG_IRDA_CACHE_LAST_LSAP=y
++CONFIG_IRDA_FAST_RR=y
++# CONFIG_IRDA_DEBUG is not set
++
++#
++# Infrared-port device drivers
++#
++
++#
++# SIR device drivers
++#
++# CONFIG_IRTTY_SIR 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_NSC_FIR is not set
++# CONFIG_WINBOND_FIR is not set
++CONFIG_OMAP1610_IR=m
++CONFIG_SMC_IRCC_FIR=m
++# CONFIG_ALI_FIR is not set
++# CONFIG_VIA_FIR is not set
++CONFIG_BT=m
++CONFIG_BT_L2CAP=m
++# CONFIG_BT_SCO is not set
++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_HCIUART_BCSP_TXCRC is not set
++# CONFIG_BT_HCIBCM203X is not set
++# CONFIG_BT_HCIBPA10X is not set
++# CONFIG_BT_HCIBFUSB is not set
++# CONFIG_BT_HCIDTL1 is not set
++# CONFIG_BT_HCIBT3C is not set
++# CONFIG_BT_HCIBLUECARD is not set
++# CONFIG_BT_HCIBTUART is not set
++CONFIG_BT_HCIVHCI=m
++CONFIG_BT_H6300=m
++# CONFIG_IEEE80211 is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++CONFIG_FW_LOADER=y
++# CONFIG_DEBUG_DRIVER is not set
++
++#
++# Memory Technology Devices (MTD)
++#
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++CONFIG_MTD_CONCAT=y
++CONFIG_MTD_PARTITIONS=y
++CONFIG_MTD_REDBOOT_PARTS=y
++CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
++# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
++# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
++# CONFIG_MTD_CMDLINE_PARTS is not set
++# CONFIG_MTD_AFS_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=m
++CONFIG_MTD_JEDECPROBE=m
++CONFIG_MTD_GEN_PROBE=m
++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=m
++CONFIG_MTD_CFI_AMDSTD=m
++CONFIG_MTD_CFI_AMDSTD_RETRY=1
++CONFIG_MTD_CFI_STAA=m
++CONFIG_MTD_CFI_UTIL=m
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++CONFIG_MTD_ABSENT=m
++# CONFIG_MTD_OBSOLETE_CHIPS is not set
++# CONFIG_MTD_XIP is not set
++
++#
++# Mapping drivers for chip access
++#
++CONFIG_MTD_COMPLEX_MAPPINGS=y
++CONFIG_MTD_PHYSMAP=m
++CONFIG_MTD_PHYSMAP_START=0x8000000
++CONFIG_MTD_PHYSMAP_LEN=0x4000000
++CONFIG_MTD_PHYSMAP_BANKWIDTH=2
++# CONFIG_MTD_ARM_INTEGRATOR is not set
++# CONFIG_MTD_EDB7312 is not set
++# CONFIG_MTD_IMPA7 is not set
++# CONFIG_MTD_OMAP_NOR is not set
++# CONFIG_MTD_PCMCIA is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++CONFIG_MTD_SLRAM=m
++CONFIG_MTD_PHRAM=m
++CONFIG_MTD_MTDRAM=m
++CONFIG_MTDRAM_TOTAL_SIZE=4096
++CONFIG_MTDRAM_ERASE_SIZE=128
++CONFIG_MTD_BLKMTD=m
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++CONFIG_MTD_DOC2000=m
++CONFIG_MTD_DOC2001=m
++CONFIG_MTD_DOC2001PLUS=m
++CONFIG_MTD_DOCPROBE=m
++CONFIG_MTD_DOCECC=m
++CONFIG_MTD_DOCPROBE_ADVANCED=y
++CONFIG_MTD_DOCPROBE_ADDRESS=0x0000
++CONFIG_MTD_DOCPROBE_HIGH=y
++CONFIG_MTD_DOCPROBE_55AA=y
++
++#
++# NAND Flash Device Drivers
++#
++CONFIG_MTD_NAND=m
++# CONFIG_MTD_NAND_VERIFY_WRITE is not set
++# CONFIG_MTD_NAND_TOTO is not set
++CONFIG_MTD_NAND_IDS=m
++CONFIG_MTD_NAND_DISKONCHIP=m
++CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED=y
++CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0x0
++# CONFIG_MTD_NAND_DISKONCHIP_PROBE_HIGH is not set
++CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE=y
++# CONFIG_MTD_NAND_NANDSIM is not set
++
++#
++# Parallel port support
++#
++# CONFIG_PARPORT is not set
++
++#
++# Plug and Play support
++#
++
++#
++# Block devices
++#
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++CONFIG_BLK_DEV_CRYPTOLOOP=m
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_UB is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=16384
++CONFIG_BLK_DEV_INITRD=y
++# CONFIG_CDROM_PKTCDVD is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++# CONFIG_ATA_OVER_ETH is not set
++
++#
++# ATA/ATAPI/MFM/RLL support
++#
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++
++#
++# Multi-device support (RAID and LVM)
++#
++# CONFIG_MD is not set
++
++#
++# Fusion MPT device support
++#
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_IEEE1394 is not set
++
++#
++# I2O device support
++#
++
++#
++# Network device support
++#
++CONFIG_NETDEVICES=y
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++
++#
++# PHY device support
++#
++# CONFIG_PHYLIB is not set
++
++#
++# Ethernet (10 or 100Mbit)
++#
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++CONFIG_SMC91X=y
++# CONFIG_DM9000 is not set
++
++#
++# 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=y
++# 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_AIRO is not set
++# CONFIG_HERMES is not set
++CONFIG_ATMEL=y
++
++#
++# Wireless 802.11b Pcmcia/Cardbus cards support
++#
++# CONFIG_AIRO_CS is not set
++# CONFIG_PCMCIA_ATMEL is not set
++# CONFIG_PCMCIA_WL3501 is not set
++# CONFIG_HOSTAP is not set
++CONFIG_NET_WIRELESS=y
++CONFIG_ACX=m
++# CONFIG_ACX_USB is not set
++CONFIG_ACX_CFI=y
++
++#
++# PCMCIA network device support
++#
++# CONFIG_NET_PCMCIA is not set
++
++#
++# Wan interfaces
++#
++# CONFIG_WAN is not set
++CONFIG_PPP=y
++CONFIG_PPP_MULTILINK=y
++CONFIG_PPP_FILTER=y
++CONFIG_PPP_ASYNC=y
++CONFIG_PPP_SYNC_TTY=y
++CONFIG_PPP_DEFLATE=y
++CONFIG_PPP_BSDCOMP=y
++CONFIG_PPPOE=y
++# 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 is not set
++# 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
++
++#
++# 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_OMAP=m
++CONFIG_INPUT_MOUSE=y
++CONFIG_MOUSE_PS2=y
++CONFIG_MOUSE_SERIAL=y
++# CONFIG_MOUSE_VSXXXAA 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_OMAP=m
++CONFIG_INPUT_MISC=y
++CONFIG_INPUT_UINPUT=m
++
++#
++# Hardware I/O ports
++#
++CONFIG_SERIO=y
++CONFIG_SERIO_SERPORT=y
++CONFIG_SERIO_LIBPS2=y
++CONFIG_SERIO_RAW=y
++# 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=y
++# CONFIG_SERIAL_8250_CONSOLE is not set
++# CONFIG_SERIAL_8250_CS is not set
++CONFIG_SERIAL_8250_NR_UARTS=4
++# CONFIG_SERIAL_8250_EXTENDED is not set
++
++#
++# Non-8250 serial port support
++#
++CONFIG_SERIAL_CORE=y
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++
++#
++# IPMI
++#
++# CONFIG_IPMI_HANDLER is not set
++
++#
++# Watchdog Cards
++#
++CONFIG_WATCHDOG=y
++CONFIG_WATCHDOG_NOWAYOUT=y
++
++#
++# Watchdog Device Drivers
++#
++CONFIG_SOFT_WATCHDOG=m
++
++#
++# USB-based Watchdog Cards
++#
++# CONFIG_USBPCWATCHDOG is not set
++CONFIG_NVRAM=y
++# CONFIG_RTC is not set
++CONFIG_OMAP_RTC=y
++# 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_RAW_DRIVER is not set
++
++#
++# TPM devices
++#
++
++#
++# I2C support
++#
++CONFIG_I2C=m
++CONFIG_I2C_CHARDEV=m
++
++#
++# I2C Algorithms
++#
++CONFIG_I2C_ALGOBIT=m
++CONFIG_I2C_ALGOPCF=m
++CONFIG_I2C_ALGOPCA=m
++
++#
++# I2C Hardware Bus support
++#
++CONFIG_I2C_PARPORT_LIGHT=m
++# CONFIG_I2C_STUB is not set
++# CONFIG_I2C_PCA_ISA is not set
++CONFIG_I2C_OMAP=m
++
++#
++# 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_PCA9535=m
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_SENSORS_RTC8564 is not set
++# CONFIG_TPS65010 is not set
++CONFIG_SENSORS_TLV320AIC23=m
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# Hardware Monitoring support
++#
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1026 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ADM9240 is not set
++# CONFIG_SENSORS_ASB100 is not set
++# CONFIG_SENSORS_ATXP1 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_FSCHER is not set
++# CONFIG_SENSORS_FSCPOS is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_GL520SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM63 is not set
++# CONFIG_SENSORS_LM75 is not set
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM87 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83792D is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++
++#
++# Misc devices
++#
++
++#
++# Multimedia Capabilities Port drivers
++#
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++
++#
++# Digital Video Broadcasting Devices
++#
++# CONFIG_DVB is not set
++
++#
++# Graphics support
++#
++CONFIG_FB=y
++# CONFIG_FB_CFB_FILLRECT is not set
++# CONFIG_FB_CFB_COPYAREA is not set
++# CONFIG_FB_CFB_IMAGEBLIT is not set
++CONFIG_FB_SOFT_CURSOR=y
++# CONFIG_FB_MACMODES is not set
++CONFIG_FB_MODE_HELPERS=y
++# CONFIG_FB_TILEBLITTING is not set
++# CONFIG_FB_S1D13XXX is not set
++CONFIG_FB_OMAP=y
++CONFIG_FB_OMAP_LCDC_INTERNAL=y
++# CONFIG_FB_OMAP_LCDC_EXTERNAL is not set
++CONFIG_FB_OMAP_DMA_TUNE=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_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
++
++#
++# Logo configuration
++#
++CONFIG_LOGO=y
++# CONFIG_LOGO_LINUX_MONO is not set
++CONFIG_LOGO_LINUX_VGA16=y
++# 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=y
++CONFIG_LCD_DEVICE=y
++
++#
++# Telephony Support
++#
++CONFIG_PHONE=m
++# CONFIG_PHONE_IXJ is not set
++CONFIG_GSM_H6300=m
++
++#
++# Sound
++#
++CONFIG_SOUND=m
++
++#
++# Advanced Linux Sound Architecture
++#
++# CONFIG_SND is not set
++
++#
++# Open Sound System
++#
++CONFIG_SOUND_PRIME=m
++CONFIG_SOUND_OMAP=m
++CONFIG_SOUND_OMAP_TSC2101=m
++# CONFIG_SOUND_MSNDCLAS is not set
++# CONFIG_SOUND_MSNDPIN is not set
++# CONFIG_SOUND_OSS is not set
++# CONFIG_SOUND_TVMIXER is not set
++# CONFIG_SOUND_AD1980 is not set
++
++#
++# USB support
++#
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB=y
++CONFIG_USB_DEBUG=y
++
++#
++# Miscellaneous USB options
++#
++CONFIG_USB_DEVICEFS=y
++# CONFIG_USB_BANDWIDTH is not set
++# CONFIG_USB_DYNAMIC_MINORS is not set
++# CONFIG_USB_SUSPEND is not set
++# CONFIG_USB_OTG is not set
++
++#
++# USB Host Controller Drivers
++#
++# CONFIG_USB_ISP116X_HCD is not set
++CONFIG_USB_OHCI_HCD=y
++# CONFIG_USB_OHCI_BIG_ENDIAN is not set
++CONFIG_USB_OHCI_LITTLE_ENDIAN=y
++# CONFIG_USB_SL811_HCD is not set
++
++#
++# USB Device Class drivers
++#
++# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set
++
++#
++# USB Bluetooth TTY can only be used with disabled Bluetooth subsystem
++#
++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 is not set
++
++#
++# USB Input Devices
++#
++# CONFIG_USB_HID is not set
++
++#
++# USB HID Boot Protocol drivers
++#
++# CONFIG_USB_KBD is not set
++# CONFIG_USB_MOUSE is not set
++# CONFIG_USB_AIPTEK is not set
++# CONFIG_USB_WACOM is not set
++# CONFIG_USB_ACECAD is not set
++# CONFIG_USB_KBTAB is not set
++# CONFIG_USB_POWERMATE is not set
++# CONFIG_USB_MTOUCH is not set
++# CONFIG_USB_ITMTOUCH is not set
++# CONFIG_USB_EGALAX is not set
++# CONFIG_USB_YEALINK is not set
++# CONFIG_USB_XPAD is not set
++# CONFIG_USB_ATI_REMOTE is not set
++# CONFIG_USB_KEYSPAN_REMOTE is not set
++# CONFIG_USB_APPLETOUCH is not set
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MDC800 is not set
++
++#
++# USB Multimedia devices
++#
++# CONFIG_USB_DABUSB is not set
++
++#
++# Video4Linux support is needed for USB Multimedia device support
++#
++
++#
++# USB Network Adapters
++#
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++CONFIG_USB_USBNET=y
++CONFIG_USB_NET_AX8817X=y
++CONFIG_USB_NET_CDCETHER=y
++# CONFIG_USB_NET_GL620A is not set
++CONFIG_USB_NET_NET1080=y
++# CONFIG_USB_NET_PLUSB is not set
++# CONFIG_USB_NET_RNDIS_HOST is not set
++# CONFIG_USB_NET_CDC_SUBSET is not set
++CONFIG_USB_NET_ZAURUS=y
++# CONFIG_USB_ZD1201 is not set
++CONFIG_USB_MON=y
++
++#
++# USB port drivers
++#
++
++#
++# USB Serial Converter support
++#
++CONFIG_USB_SERIAL=y
++CONFIG_USB_SERIAL_CONSOLE=y
++CONFIG_USB_SERIAL_GENERIC=y
++# CONFIG_USB_SERIAL_AIRPRIME is not set
++# CONFIG_USB_SERIAL_BELKIN is not set
++# CONFIG_USB_SERIAL_WHITEHEAT is not set
++# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
++# CONFIG_USB_SERIAL_CP2101 is not set
++# CONFIG_USB_SERIAL_CYPRESS_M8 is not set
++# CONFIG_USB_SERIAL_EMPEG is not set
++# CONFIG_USB_SERIAL_FTDI_SIO is not set
++CONFIG_USB_SERIAL_VISOR=y
++CONFIG_USB_SERIAL_IPAQ=y
++# CONFIG_USB_SERIAL_IR is not set
++# CONFIG_USB_SERIAL_EDGEPORT is not set
++# CONFIG_USB_SERIAL_EDGEPORT_TI is not set
++# CONFIG_USB_SERIAL_GARMIN is not set
++# CONFIG_USB_SERIAL_IPW is not set
++# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
++# CONFIG_USB_SERIAL_KEYSPAN is not set
++# CONFIG_USB_SERIAL_KLSI is not set
++# CONFIG_USB_SERIAL_KOBIL_SCT is not set
++# CONFIG_USB_SERIAL_MCT_U232 is not set
++# CONFIG_USB_SERIAL_PL2303 is not set
++# CONFIG_USB_SERIAL_HP4X is not set
++# CONFIG_USB_SERIAL_SAFE is not set
++# CONFIG_USB_SERIAL_TI is not set
++# CONFIG_USB_SERIAL_CYBERJACK is not set
++# CONFIG_USB_SERIAL_XIRCOM is not set
++# CONFIG_USB_SERIAL_OPTION is not set
++# CONFIG_USB_SERIAL_OMNINET is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_EMI62 is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_AUERSWALD is not set
++# CONFIG_USB_RIO500 is not set
++# CONFIG_USB_LEGOTOWER is not set
++# CONFIG_USB_LCD is not set
++# CONFIG_USB_LED is not set
++# CONFIG_USB_CYTHERM is not set
++# CONFIG_USB_PHIDGETKIT is not set
++# CONFIG_USB_PHIDGETSERVO is not set
++# CONFIG_USB_IDMOUSE is not set
++# CONFIG_USB_LD is not set
++# CONFIG_USB_TEST is not set
++
++#
++# USB DSL modem support
++#
++
++#
++# USB Gadget Support
++#
++CONFIG_USB_GADGET=y
++CONFIG_USB_GADGET_DEBUG_FILES=y
++CONFIG_USB_GADGET_SELECTED=y
++# CONFIG_USB_GADGET_NET2280 is not set
++# CONFIG_USB_GADGET_PXA2XX is not set
++# CONFIG_USB_GADGET_GOKU is not set
++# CONFIG_USB_GADGET_LH7A40X is not set
++CONFIG_USB_GADGET_OMAP=y
++CONFIG_USB_OMAP=y
++# CONFIG_USB_GADGET_DUMMY_HCD is not set
++# CONFIG_USB_GADGET_DUALSPEED is not set
++# CONFIG_USB_ZERO is not set
++CONFIG_USB_ETH=y
++# CONFIG_USB_ETH_RNDIS is not set
++# CONFIG_USB_GADGETFS is not set
++# CONFIG_USB_FILE_STORAGE is not set
++# CONFIG_USB_G_SERIAL is not set
++
++#
++# MMC/SD Card support
++#
++CONFIG_MMC=y
++# CONFIG_MMC_DEBUG is not set
++CONFIG_MMC_BLOCK=y
++CONFIG_MMC_BLOCK_BROKEN_RFD=y
++CONFIG_MMC_BULKTRANSFER=y
++CONFIG_MMC_OMAP=y
++# CONFIG_MMC_WBSD is not set
++
++#
++# Synchronous Serial Interfaces (SSI)
++#
++CONFIG_OMAP_UWIRE=y
++CONFIG_OMAP_TSC2101=y
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++CONFIG_EXT2_FS_XATTR=y
++CONFIG_EXT2_FS_POSIX_ACL=y
++CONFIG_EXT2_FS_SECURITY=y
++# CONFIG_EXT2_FS_XIP is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_JBD is not set
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++CONFIG_FS_POSIX_ACL=y
++# CONFIG_XFS_FS is not set
++# CONFIG_MINIX_FS is not set
++CONFIG_ROMFS_FS=y
++CONFIG_INOTIFY=y
++# CONFIG_QUOTA is not set
++# CONFIG_DNOTIFY is not set
++# CONFIG_AUTOFS_FS is not set
++CONFIG_AUTOFS4_FS=y
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=y
++CONFIG_MSDOS_FS=y
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_HUGETLBFS is not set
++# CONFIG_HUGETLB_PAGE is not set
++CONFIG_RAMFS=y
++# CONFIG_RELAYFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_JFFS_FS=y
++CONFIG_JFFS_FS_VERBOSE=0
++CONFIG_JFFS_PROC_FS=y
++CONFIG_JFFS2_FS=y
++CONFIG_JFFS2_FS_DEBUG=4
++CONFIG_JFFS2_FS_WRITEBUFFER=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=y
++# CONFIG_VXFS_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++
++#
++# Network File Systems
++#
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++CONFIG_NFS_V4=y
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++CONFIG_SUNRPC_GSS=y
++CONFIG_RPCSEC_GSS_KRB5=y
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++# CONFIG_9P_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_BSD_DISKLABEL is not set
++# CONFIG_MINIX_SUBPARTITION is not set
++# CONFIG_SOLARIS_X86_PARTITION is not set
++# CONFIG_UNIXWARE_DISKLABEL is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++
++#
++# Native Language Support
++#
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="utf8"
++CONFIG_NLS_CODEPAGE_437=y
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++# CONFIG_NLS_CODEPAGE_850 is not set
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++# CONFIG_NLS_CODEPAGE_936 is not set
++# CONFIG_NLS_CODEPAGE_950 is not set
++# CONFIG_NLS_CODEPAGE_932 is not set
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
++# CONFIG_NLS_ASCII 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 is not set
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_DEBUG_KERNEL=y
++CONFIG_MAGIC_SYSRQ=y
++CONFIG_LOG_BUF_SHIFT=17
++CONFIG_DETECT_SOFTLOCKUP=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_DEBUG_SLAB is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_KOBJECT is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_DEBUG_FS is not set
++CONFIG_FRAME_POINTER=y
++# CONFIG_DEBUG_USER is not set
++# CONFIG_DEBUG_WAITQ is not set
++CONFIG_DEBUG_ERRORS=y
++CONFIG_DEBUG_LL=y
++# CONFIG_DEBUG_ICEDCC is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++
++#
++# Cryptographic options
++#
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_HMAC=y
++# 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_DES=y
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++CONFIG_CRYPTO_DEFLATE=m
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_TEST is not set
++
++#
++# Hardware crypto devices
++#
++
++#
++# Library routines
++#
++CONFIG_CRC_CCITT=y
++# CONFIG_CRC16 is not set
++CONFIG_CRC32=y
++CONFIG_LIBCRC32C=y
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
++CONFIG_REED_SOLOMON=m
++CONFIG_REED_SOLOMON_DEC16=y
+diff -Naur linux-2.6.14-omap2/arch/arm/Kconfig linux-h6300-omap2-2.6.14.3/arch/arm/Kconfig
+--- linux-2.6.14-omap2/arch/arm/Kconfig        2005-12-02 01:53:31.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/arch/arm/Kconfig        2005-10-14 18:55:31.000000000 +0300
+@@ -725,6 +725,8 @@
+ source "drivers/video/Kconfig"
++source "drivers/telephony/Kconfig"
++
+ source "sound/Kconfig"
+ source "drivers/usb/Kconfig"
+diff -Naur linux-2.6.14-omap2/arch/arm/mach-omap1/board-h6300.c linux-h6300-omap2-2.6.14.3/arch/arm/mach-omap1/board-h6300.c
+--- linux-2.6.14-omap2/arch/arm/mach-omap1/board-h6300.c       1970-01-01 02:00:00.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/arch/arm/mach-omap1/board-h6300.c       2005-10-22 03:52:45.000000000 +0300
+@@ -0,0 +1,317 @@
++/*
++ * Modified from board-h6300.c
++ *
++ * Code for generic OMAP board. Should work on many OMAP systems where
++ * the device drivers take care of all the necessary hardware initialization.
++ * Do not put any board specific code to this file; create a new machine
++ * type if you need custom low-level initializations.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/device.h>
++#include <linux/delay.h>
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/partitions.h>
++
++#include <asm/hardware.h>
++#include <asm/mach-types.h>
++#include <asm/mach/arch.h>
++#include <asm/mach/flash.h>
++#include <asm/mach/map.h>
++
++#include <asm/arch/gpio.h>
++
++#include <asm/arch/tc.h>
++#include <asm/arch/usb.h>
++
++#include <asm/arch/common.h>
++
++#include <asm/arch/h6300_uart_info.h>
++
++/*
++ * Bluetooth - Relies on h6300_bt module,
++ * so make the calls indirectly through pointers. Requires that the
++ * h6300_bt bluetooth module be loaded before any attempt to use
++ * bluetooth (obviously).
++ */
++
++static struct h6300_uart_funcs bt_funcs;
++static struct h6300_uart_funcs gsm_funcs;
++
++static void
++h6300_bt_configure(struct uart_omap_port *up, int enable)
++{
++      printk(KERN_NOTICE "board-h6300.c, h6300_bt_configure() started\n");
++      if (bt_funcs.configure != NULL)
++              bt_funcs.configure(up, enable);
++      printk(KERN_NOTICE "board-h6300.c, h6300_bt_configure() done\n");
++}
++
++static void
++h6300_bt_set_txrx(struct uart_omap_port *up, int txrx)
++{
++      printk(KERN_NOTICE "board-h6300.c, h6300_bt_set_txrx() started\n");
++      if (bt_funcs.set_txrx != NULL)
++      {
++              printk(KERN_NOTICE "board-h6300.c, h6300_bt_set_txrx(), bt_funcs.set_txrx != NULL\n");
++              bt_funcs.set_txrx(up, txrx);
++      }
++      printk(KERN_NOTICE "board-h6300.c, h6300_bt_set_txrx() done\n");
++}
++
++static int
++h6300_bt_get_txrx(struct uart_omap_port *up)
++{
++      int     retVal;
++      
++      printk(KERN_NOTICE "board-h6300.c, h6300_bt_get_txrx() started\n");
++      if (bt_funcs.get_txrx != NULL)
++      {
++              retVal  = bt_funcs.get_txrx(up);
++              printk(KERN_NOTICE "board-h6300.c, h6300_bt_get_txrx(), bt_funcs.get_trx != null, done, retVal %d\n", retVal);
++              return retVal;
++      }
++      else
++      {
++              printk(KERN_NOTICE "board-h6300.c, h6300_bt_get_txrx() done, returning 0\n");
++              return 0;
++      }
++}
++
++static struct platform_omap_serial_funcs h6300_omap_bt_funcs = {
++      .configure      = h6300_bt_configure,
++      .set_txrx       = h6300_bt_set_txrx,
++      .get_txrx       = h6300_bt_get_txrx,
++};
++
++struct platform_device btuart_device = {
++      .name   = "h6300_bt",
++      .id     = 1,
++};
++EXPORT_SYMBOL(btuart_device);
++
++static void
++h6300_gsm_configure(struct uart_omap_port *up, int enable)
++{
++      printk(KERN_NOTICE "board-h6300.c, h6300_gsm_configure() started\n");
++      if (gsm_funcs.configure != NULL)
++              gsm_funcs.configure(up, enable);
++      printk(KERN_NOTICE "board-h6300.c, h6300_gsm_configure() done\n");
++}
++
++static void
++h6300_gsm_set_txrx(struct uart_omap_port *up, int txrx)
++{
++      printk(KERN_NOTICE "board-h6300.c, h6300_gsm_set_txrx() started\n");
++      if (bt_funcs.set_txrx != NULL)
++      {
++              printk(KERN_NOTICE "board-h6300.c, h6300_gsm_set_txrx(), bt_funcs.set_txrx != NULL\n");
++              gsm_funcs.set_txrx(up, txrx);
++      }
++      printk(KERN_NOTICE "board-h6300.c, h6300_gsm_set_txrx() done\n");
++}
++
++static int
++h6300_gsm_get_txrx(struct uart_omap_port *up)
++{
++      int     retVal;
++      
++      printk(KERN_NOTICE "board-h6300.c, h6300_gsm_get_txrx() started\n");
++      if (bt_funcs.get_txrx != NULL)
++      {
++              retVal  = gsm_funcs.get_txrx(up);
++              printk(KERN_NOTICE "board-h6300.c, h6300_gsm_get_txrx(), bt_funcs.get_trx != null, done, retVal %d\n", retVal);
++              return retVal;
++      }
++      else
++      {
++              printk(KERN_NOTICE "board-h6300.c, h6300_gsm_get_txrx() done, returning 0\n");
++              return 0;
++      }
++}
++
++static struct platform_omap_serial_funcs h6300_omap_gsm_funcs = {
++      .configure      = h6300_gsm_configure,
++      .set_txrx       = h6300_gsm_set_txrx,
++      .get_txrx       = h6300_gsm_get_txrx,
++};
++
++struct platform_device gsmuart_device = {
++      .name   = "h6300_gsm",
++      .id     = 1,
++};
++EXPORT_SYMBOL(gsmuart_device);
++
++#if 0
++static struct mtd_partition h6300_partitions[] = {
++      /* bootloader (U-Boot, etc) in first sector */
++      {
++            .name             = "bootloader",
++            .offset           = 0,
++            .size             = SZ_128K,
++            .mask_flags       = MTD_WRITEABLE, /* force read-only */
++      },
++      /* bootloader params in the next sector */
++      {
++            .name             = "params",
++            .offset           = MTDPART_OFS_APPEND,
++            .size             = SZ_128K,
++            .mask_flags       = 0,
++      },
++      /* kernel */
++      {
++            .name             = "kernel",
++            .offset           = MTDPART_OFS_APPEND,
++            .size             = SZ_2M,
++            .mask_flags       = 0
++      },
++      /* rest of flash1 is a file system */
++      {
++            .name             = "rootfs",
++            .offset           = MTDPART_OFS_APPEND,
++            .size             = SZ_16M - SZ_2M - 2 * SZ_128K,
++            .mask_flags       = 0
++      },
++      /* file system */
++      {
++            .name             = "filesystem",
++            .offset           = MTDPART_OFS_APPEND,
++            .size             = MTDPART_SIZ_FULL,
++            .mask_flags       = 0
++      }
++};
++
++static struct flash_platform_data h6300_flash_data = {
++      .map_name       = "cfi_probe",
++      .width          = 2,
++      .parts          = h6300_partitions,
++      .nr_parts       = ARRAY_SIZE(h6300_partitions),
++};
++
++static struct resource h6300_flash_resource = {
++      .start          = OMAP_CS0_PHYS,
++      .end            = OMAP_CS0_PHYS + SZ_32M - 1,
++      .flags          = IORESOURCE_MEM,
++};
++
++static struct platform_device h6300_flash_device = {
++      .name   = "omapflash",
++      .id             = 0,
++      .dev    = {
++              .platform_data  = &h6300_flash_data,
++      },
++      .num_resources  = 1,
++      .resource       = &h6300_flash_resource,
++};
++#endif
++
++static struct resource h6300_wlan_resource[] = {
++        [0] = {
++                .start          = OMAP_CS1_PHYS,
++                .end            = OMAP_CS1_PHYS + SZ_32M -1,
++                .flags          = IORESOURCE_MEM,
++        },
++
++        [1] = {
++                .start  = OMAP_GPIO_IRQ(11),
++                .end    = OMAP_GPIO_IRQ(11),
++                .flags  = IORESOURCE_IRQ,
++        },
++};
++
++static struct platform_device h6300_wlan_device = {
++        .name           = "tnetw1100b",
++        .id             = 0,
++        .num_resources  = 2,
++        .resource       = h6300_wlan_resource,
++};
++
++static struct platform_device *h6300_devices[] __initdata = {
++      &btuart_device,
++      &gsmuart_device,
++      &h6300_wlan_device,
++      //&h6300_flash_device,
++};
++
++static void __init h6300_init_irq(void)
++{
++      omap_init_irq();
++      omap_gpio_init();
++
++      omap_request_gpio (2);
++      omap_set_gpio_direction (2, 0);
++      omap_set_gpio_dataout (2, 1);
++}
++
++/* assume no Mini-AB port */
++
++static struct omap_usb_config h6300_usb_config __initdata = {
++      .hmc_mode       = 0,
++      .register_dev   = 1,
++      .pins[0]        = 0,
++};
++
++static struct omap_lcd_config h6300_lcd_config __initdata = {
++      .panel_name     = "h6300",
++      .ctrl_name      = "internal",
++};
++
++static struct omap_mmc_config h6300_mmc_config __initdata = {
++      .mmc [0] = {
++              .enabled        = 1,
++              .wire4          = 1,
++              .wp_pin         = OMAP_GPIO_IRQ(13),
++              .power_pin      = -1,   /* FPGA F3 UIO42 */
++              .switch_pin     = -1,   /* FPGA F4 UIO43 */
++      },
++};
++
++static struct omap_uart_config h6300_uart_config __initdata = {
++      .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)),
++};
++
++static struct omap_board_config_kernel h6300_config[] = {
++      { OMAP_TAG_USB, &h6300_usb_config },
++      { OMAP_TAG_MMC, &h6300_mmc_config },
++      { OMAP_TAG_UART,        &h6300_uart_config },
++      { OMAP_TAG_LCD, &h6300_lcd_config },
++};
++
++static void __init h6300_init(void)
++{
++      int ret;
++      
++      ret = platform_add_devices(h6300_devices, ARRAY_SIZE(h6300_devices));
++      if (ret) 
++      {
++              printk(KERN_WARNING "Unable to add h6300 platform devices like bluetooth");
++      }
++      omap_board_config               = h6300_config;
++      omap_board_config_size  = ARRAY_SIZE(h6300_config);
++      omap_serial_init();
++}
++
++static void __init h6300_map_io(void)
++{
++      omap_map_common_io();
++      
++      btuart_device.dev.platform_data = &h6300_omap_bt_funcs;
++      gsmuart_device.dev.platform_data        = &h6300_omap_gsm_funcs;
++}
++
++MACHINE_START(H6300, "HP iPAQ H6300")
++      /* MAINTAINER("Everett Coleman II <gcc80x86@fuzzyneural.net>") */
++      .phys_ram       = 0x10000000,
++      .phys_io        = 0xfff00000,
++      .io_pg_offst    = ((0xfef00000) >> 18) & 0xfffc,
++      .boot_params    = 0x10000100,
++      .map_io         = h6300_map_io,
++      .init_irq       = h6300_init_irq,
++      .init_machine   = h6300_init,
++      .timer          = &omap_timer,
++MACHINE_END
+diff -Naur linux-2.6.14-omap2/arch/arm/mach-omap1/Kconfig linux-h6300-omap2-2.6.14.3/arch/arm/mach-omap1/Kconfig
+--- linux-2.6.14-omap2/arch/arm/mach-omap1/Kconfig     2005-12-02 01:53:31.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/arch/arm/mach-omap1/Kconfig     2005-10-22 03:52:45.000000000 +0300
+@@ -26,6 +26,12 @@
+           TI OMAP 1510 or 1610 Innovator board support. Say Y here if you
+           have such a board.
++config MACH_OMAP_H6300
++      bool "HP IPaq H6300"
++      depends on ARCH_OMAP1 && ARCH_OMAP15XX
++      help
++                      HP IPaq H6300 series.
++
+ config MACH_OMAP_H2
+       bool "TI H2 Support"
+       depends on ARCH_OMAP1 && ARCH_OMAP16XX
+diff -Naur linux-2.6.14-omap2/arch/arm/mach-omap1/Makefile linux-h6300-omap2-2.6.14.3/arch/arm/mach-omap1/Makefile
+--- linux-2.6.14-omap2/arch/arm/mach-omap1/Makefile    2005-12-02 01:53:31.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/arch/arm/mach-omap1/Makefile    2005-10-22 03:52:45.000000000 +0300
+@@ -15,7 +15,8 @@
+ obj-$(CONFIG_MACH_OMAP_H3)            += board-h3.o
+ obj-$(CONFIG_MACH_VOICEBLUE)          += board-voiceblue.o
+ obj-$(CONFIG_MACH_NETSTAR)            += board-netstar.o
+-obj-$(CONFIG_MACH_OMAP_PALMTE)                += board-palmte.o
++obj-$(CONFIG_MACH_OMAP_PALMTE)        += board-palmte.o
++obj-$(CONFIG_MACH_OMAP_H6300)         += board-h6300.o
+ ifeq ($(CONFIG_ARCH_OMAP15XX),y)
+ # Innovator-1510 FPGA
+diff -Naur linux-2.6.14-omap2/arch/arm/mach-omap1/mux.c linux-h6300-omap2-2.6.14.3/arch/arm/mach-omap1/mux.c
+--- linux-2.6.14-omap2/arch/arm/mach-omap1/mux.c       2005-12-02 01:53:32.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/arch/arm/mach-omap1/mux.c       2005-11-11 04:13:42.000000000 +0200
+@@ -196,6 +196,13 @@
+ MUX_CFG("P15_1610_UWIRE_CS3",  8,   12,    1,   1,  22,   0,    1,     1,  1)
+ MUX_CFG("N15_1610_UWIRE_CS1",  7,   18,    2,   1,  14,   0,   NA,     0,  1)
++/* OMAP-1510 uWire */
++MUX_CFG("P15_1510_UWIRE_CS3",  8,   12,    1,  NA,   0,   0,  NA,  0,  1)
++MUX_CFG("N14_1510_UWIRE_CS0",  8,    9,    1,  NA,   0,   0,  NA,  0,  1)
++MUX_CFG("V19_1510_UWIRE_SCLK", 8,    6,    0,  NA,   0,   0,  NA,  0,  1)
++MUX_CFG("W21_1510_UWIRE_SDO",  8,    3,    0,  NA,   0,   0,  NA,  0,  1)
++MUX_CFG("U18_1510_UWIRE_SDI",  8,    0,    0,   1,  18,   0,  NA,  0,  1)
++
+ /* OMAP-1610 Flash */
+ MUX_CFG("L3_1610_FLASH_CS2B_OE",10,    6,    1,        NA,   0,   0,   NA,     0,  1)
+ MUX_CFG("M8_1610_FLASH_CS2B_WE",10,    3,    1,        NA,   0,   0,   NA,     0,  1)
+@@ -258,6 +265,7 @@
+ MUX_CFG("T20_1610_LOW_PWR",    7,   12,    1,   NA,   0,   0,   NA,    0,  0)
+ /* MCLK Settings */
++MUX_CFG("R10_1510_MCLK_ON",    B,   18,    0,   2,   22,   1,   NA,    1,  1)
+ MUX_CFG("V5_1710_MCLK_ON",     B,   15,    0,   NA,   0,   0,   NA,    0,  0)
+ MUX_CFG("V5_1710_MCLK_OFF",    B,   15,    6,   NA,   0,   0,   NA,    0,  0)
+ MUX_CFG("R10_1610_MCLK_ON",    B,   18,    0,   NA,  22,   0,   NA,    1,  0)
+diff -Naur linux-2.6.14-omap2/arch/arm/plat-omap/dma.c linux-h6300-omap2-2.6.14.3/arch/arm/plat-omap/dma.c
+--- linux-2.6.14-omap2/arch/arm/plat-omap/dma.c        2005-12-02 01:53:32.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/arch/arm/plat-omap/dma.c        2005-11-11 04:13:42.000000000 +0200
+@@ -30,6 +30,7 @@
+ #include <asm/hardware.h>
+ #include <asm/dma.h>
+ #include <asm/io.h>
++#include <asm/mach-types.h>
+ #include <asm/arch/tc.h>
+@@ -1086,6 +1087,10 @@
+       }
+       if (omap_dma_in_1510_mode()) {
++              u16 l = omap_readw(OMAP1510_DMA_LCD_CTRL);
++              l &= ~(1 << 6);
++              omap_writew (l, OMAP1510_DMA_LCD_CTRL);
++
+               omap_writew(top >> 16, OMAP1510_DMA_LCD_TOP_F1_U);
+               omap_writew(top, OMAP1510_DMA_LCD_TOP_F1_L);
+               omap_writew(bottom >> 16, OMAP1510_DMA_LCD_BOT_F1_U);
+diff -Naur linux-2.6.14-omap2/arch/arm/tools/mach-types linux-h6300-omap2-2.6.14.3/arch/arm/tools/mach-types
+--- linux-2.6.14-omap2/arch/arm/tools/mach-types       2005-10-28 03:02:08.000000000 +0300
++++ linux-h6300-omap2-2.6.14.3/arch/arm/tools/mach-types       2005-10-22 03:52:45.000000000 +0300
+@@ -576,7 +576,7 @@
+ s3c2460                       MACH_S3C2460            S3C2460                 560
+ pdm                   MACH_PDM                PDM                     561
+ h4700                 MACH_H4700              H4700                   562
+-h6300                 MACH_H6300              H6300                   563
++h6300                 MACH_OMAP_H6300         H6300                   563
+ rz1700                        MACH_RZ1700             RZ1700                  564
+ a716                  MACH_A716               A716                    565
+ estk2440a             MACH_ESTK2440A          ESTK2440A               566
+diff -Naur linux-2.6.14-omap2/arch/i386/kernel/cpu/mtrr/main.c linux-h6300-omap2-2.6.14.3/arch/i386/kernel/cpu/mtrr/main.c
+--- linux-2.6.14-omap2/arch/i386/kernel/cpu/mtrr/main.c        2005-10-28 03:02:08.000000000 +0300
++++ linux-h6300-omap2-2.6.14.3/arch/i386/kernel/cpu/mtrr/main.c        2005-12-02 01:34:34.000000000 +0200
+@@ -626,6 +626,14 @@
+               if (cpuid_eax(0x80000000) >= 0x80000008) {
+                       u32 phys_addr;
+                       phys_addr = cpuid_eax(0x80000008) & 0xff;
++                      /* CPUID workaround for Intel 0F33/0F34 CPU */
++                      if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
++                          boot_cpu_data.x86 == 0xF &&
++                          boot_cpu_data.x86_model == 0x3 &&
++                          (boot_cpu_data.x86_mask == 0x3 ||
++                           boot_cpu_data.x86_mask == 0x4))
++                              phys_addr = 36;
++
+                       size_or_mask = ~((1 << (phys_addr - PAGE_SHIFT)) - 1);
+                       size_and_mask = ~size_or_mask & 0xfff00000;
+               } else if (boot_cpu_data.x86_vendor == X86_VENDOR_CENTAUR &&
+diff -Naur linux-2.6.14-omap2/arch/ppc64/Kconfig linux-h6300-omap2-2.6.14.3/arch/ppc64/Kconfig
+--- linux-2.6.14-omap2/arch/ppc64/Kconfig      2005-10-28 03:02:08.000000000 +0300
++++ linux-h6300-omap2-2.6.14.3/arch/ppc64/Kconfig      2005-12-02 01:34:35.000000000 +0200
+@@ -234,6 +234,10 @@
+         This option enables hardware multithreading on RS64 cpus.
+         pSeries systems p620 and p660 have such a cpu type.
++config NUMA
++      bool "NUMA support"
++      default y if DISCONTIGMEM || SPARSEMEM
++
+ config ARCH_SELECT_MEMORY_MODEL
+       def_bool y
+@@ -249,9 +253,6 @@
+       def_bool y
+       depends on ARCH_DISCONTIGMEM_ENABLE
+-config ARCH_FLATMEM_ENABLE
+-      def_bool y
+-
+ config ARCH_SPARSEMEM_ENABLE
+       def_bool y
+       depends on ARCH_DISCONTIGMEM_ENABLE
+@@ -274,10 +275,6 @@
+       def_bool y
+       depends on NEED_MULTIPLE_NODES
+-config NUMA
+-      bool "NUMA support"
+-      default y if DISCONTIGMEM || SPARSEMEM
+-
+ config SCHED_SMT
+       bool "SMT (Hyperthreading) scheduler support"
+       depends on SMP
+diff -Naur linux-2.6.14-omap2/arch/s390/appldata/appldata_base.c linux-h6300-omap2-2.6.14.3/arch/s390/appldata/appldata_base.c
+--- linux-2.6.14-omap2/arch/s390/appldata/appldata_base.c      2005-10-28 03:02:08.000000000 +0300
++++ linux-h6300-omap2-2.6.14.3/arch/s390/appldata/appldata_base.c      2005-11-23 01:44:02.000000000 +0200
+@@ -592,12 +592,15 @@
+  */
+ void appldata_unregister_ops(struct appldata_ops *ops)
+ {
++      void *table;
+       spin_lock(&appldata_ops_lock);
+-      unregister_sysctl_table(ops->sysctl_header);
+       list_del(&ops->list);
+-      kfree(ops->ctl_table);
++      /* at that point any incoming access will fail */
++      table = ops->ctl_table;
+       ops->ctl_table = NULL;
+       spin_unlock(&appldata_ops_lock);
++      unregister_sysctl_table(ops->sysctl_header);
++      kfree(table);
+       P_INFO("%s-ops unregistered!\n", ops->name);
+ }
+ /********************** module-ops management <END> **************************/
+diff -Naur linux-2.6.14-omap2/arch/x86_64/kernel/setup.c linux-h6300-omap2-2.6.14.3/arch/x86_64/kernel/setup.c
+--- linux-2.6.14-omap2/arch/x86_64/kernel/setup.c      2005-10-28 03:02:08.000000000 +0300
++++ linux-h6300-omap2-2.6.14.3/arch/x86_64/kernel/setup.c      2005-12-02 01:34:35.000000000 +0200
+@@ -993,6 +993,11 @@
+               unsigned eax = cpuid_eax(0x80000008);
+               c->x86_virt_bits = (eax >> 8) & 0xff;
+               c->x86_phys_bits = eax & 0xff;
++              /* CPUID workaround for Intel 0F34 CPU */
++              if (c->x86_vendor == X86_VENDOR_INTEL &&
++                  c->x86 == 0xF && c->x86_model == 0x3 &&
++                  c->x86_mask == 0x4)
++                      c->x86_phys_bits = 36;
+       }
+       if (c->x86 == 15)
+diff -Naur linux-2.6.14-omap2/drivers/block/cfq-iosched.c linux-h6300-omap2-2.6.14.3/drivers/block/cfq-iosched.c
+--- linux-2.6.14-omap2/drivers/block/cfq-iosched.c     2005-10-28 03:02:08.000000000 +0300
++++ linux-h6300-omap2-2.6.14.3/drivers/block/cfq-iosched.c     2005-11-23 01:44:02.000000000 +0200
+@@ -2260,10 +2260,8 @@
+       if (!atomic_dec_and_test(&cfqd->ref))
+               return;
+-      blk_put_queue(q);
+-
+       cfq_shutdown_timer_wq(cfqd);
+-      q->elevator->elevator_data = NULL;
++      blk_put_queue(q);
+       mempool_destroy(cfqd->crq_pool);
+       kfree(cfqd->crq_hash);
+diff -Naur linux-2.6.14-omap2/drivers/block/pktcdvd.c linux-h6300-omap2-2.6.14.3/drivers/block/pktcdvd.c
+--- linux-2.6.14-omap2/drivers/block/pktcdvd.c 2005-10-28 03:02:08.000000000 +0300
++++ linux-h6300-omap2-2.6.14.3/drivers/block/pktcdvd.c 2005-12-02 01:34:35.000000000 +0200
+@@ -1191,7 +1191,7 @@
+       struct packet_data *pkt;
+       int i;
+-      for (i = 0; i <= PACKET_NUM_STATES; i++)
++      for (i = 0; i < PACKET_NUM_STATES; i++)
+               states[i] = 0;
+       spin_lock(&pd->cdrw.active_list_lock);
+diff -Naur linux-2.6.14-omap2/drivers/bluetooth/Kconfig linux-h6300-omap2-2.6.14.3/drivers/bluetooth/Kconfig
+--- linux-2.6.14-omap2/drivers/bluetooth/Kconfig       2005-10-28 03:02:08.000000000 +0300
++++ linux-h6300-omap2-2.6.14.3/drivers/bluetooth/Kconfig       2005-10-04 00:58:34.000000000 +0300
+@@ -163,6 +163,16 @@
+         Say Y here to compile support for virtual HCI devices into the
+         kernel or say M to compile it as module (hci_vhci).
++        
++config BT_H6300
++      tristate "H6300 BRF6100 BT DRIVER"
++      help
++        Bluetooth H6300 BRF6100 driver.
++        This driver provides the firmware loading mechanism for the BRF6100
++        bt hardware in iPAQ h6300.
++
++        Say Y here to compile support for BRF6100 BT devices into the
++        kernel or say M to compile it as module (h6300_BT).     
+ endmenu
+diff -Naur linux-2.6.14-omap2/drivers/bluetooth/Makefile linux-h6300-omap2-2.6.14.3/drivers/bluetooth/Makefile
+--- linux-2.6.14-omap2/drivers/bluetooth/Makefile      2005-10-28 03:02:08.000000000 +0300
++++ linux-h6300-omap2-2.6.14.3/drivers/bluetooth/Makefile      2005-09-28 01:04:13.000000000 +0300
+@@ -10,10 +10,11 @@
+ obj-$(CONFIG_BT_HCIBFUSB)     += bfusb.o
+ obj-$(CONFIG_BT_HCIDTL1)      += dtl1_cs.o
+ obj-$(CONFIG_BT_HCIBT3C)      += bt3c_cs.o
+-obj-$(CONFIG_BT_HCIBLUECARD)  += bluecard_cs.o
++obj-$(CONFIG_BT_HCIBLUECARD)+= bluecard_cs.o
+ obj-$(CONFIG_BT_HCIBTUART)    += btuart_cs.o
++obj-$(CONFIG_BT_H6300)                += omap/
+-hci_uart-y                            := hci_ldisc.o
++hci_uart-y                                                    := hci_ldisc.o
+ hci_uart-$(CONFIG_BT_HCIUART_H4)      += hci_h4.o
+ hci_uart-$(CONFIG_BT_HCIUART_BCSP)    += hci_bcsp.o
+-hci_uart-objs                         := $(hci_uart-y)
++hci_uart-objs                                         := $(hci_uart-y)
+diff -Naur linux-2.6.14-omap2/drivers/bluetooth/omap/h6300_bt_brf6100.c linux-h6300-omap2-2.6.14.3/drivers/bluetooth/omap/h6300_bt_brf6100.c
+--- linux-2.6.14-omap2/drivers/bluetooth/omap/h6300_bt_brf6100.c       1970-01-01 02:00:00.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/drivers/bluetooth/omap/h6300_bt_brf6100.c       2005-12-02 00:45:30.000000000 +0200
+@@ -0,0 +1,153 @@
++/* 
++ * Bluetooth interface driver for TI BRF6100 on h6300
++ * 
++ * Copyright (C) 2005 Mika Laitio <lamikr@cc.jyu.fi>
++ * Ideas taken from the brf6150 bt driver made by Todd Blumer for the pxa hx4700.
++ * 
++ * This program is free software; you can 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/delay.h>
++#include <linux/device.h>
++
++#include <asm/hardware.h>
++#include <asm/arch/gpio.h>
++
++#include <asm/arch/h6300_uart_info.h>
++#include "h6300_bt_led.h"
++
++static void
++h6300_bt_configure(struct uart_omap_port *up, int enable)
++{
++      printk(KERN_NOTICE "h6300_bt_brf6100.c h6300_bt_configure() started, enable = %d\n", enable);
++      
++      // printk( KERN_NOTICE "h6300 configure bluetooth: %d\n", enable );
++      if (enable == 0) {
++              omap_set_gpio_dataout(GPIO_N_BT_RST, 1);        // turn off gpio, note 1 == off for negative gpios
++              mdelay(5);
++              h6300_clear_led(INDEX_BT_LED);
++      }
++      else if (enable == 1) {
++              omap_set_gpio_dataout(GPIO_N_BT_RST, 1);        // turn on gpio, note 0 == on for negative gpios
++              mdelay(5);                              
++      }
++      else if (enable == 2) {
++              /*
++               * BRF6150's RTS goes low when firmware is ready
++               * so check for CTS=1 (nCTS=0 -> CTS=1). Typical 150ms
++               */
++/*            
++              int tries = 0; 
++              do 
++              {
++                      mdelay(10);
++              } 
++              while ((BTMSR & MSR_CTS) == 0 && tries++ < 50);
++*/                            
++              h6300_set_led(INDEX_BT_LED, 16, 16);
++      }
++      printk(KERN_NOTICE "h6300_bt_brf6100.c h6300_bt_configure() done\n");
++}
++
++static void
++h6300_bt_set_txrx(struct uart_omap_port *up, int txrx)
++{
++      printk(KERN_NOTICE "h6300_bt_brf6100.c h6300_bt_set_txrx(), txrx = %d done\n", txrx);
++      /* do nothing */
++}
++
++static int
++h6300_bt_get_txrx(struct uart_omap_port *up)
++{
++      printk(KERN_NOTICE "h6300_bt_brf6100.c h6300_bt_get_txrx() done\n");
++      /* do nothing */
++      return 0;
++}
++
++static int
++h6300_bt_probe(struct device *dev)
++{
++      struct h6300_uart_funcs *funcs = (struct h6300_uart_funcs *)dev->platform_data;
++
++      omap_request_gpio(GPIO_BT_PWR_EN);              // ask bt_power_en gpio, remember to release in remove_function
++      omap_set_gpio_direction(GPIO_BT_PWR_EN, 1);     // set gpio direction to be output
++      omap_set_gpio_dataout(GPIO_BT_PWR_EN, 1);       // turn on gpio
++
++      mdelay(200);
++
++      omap_request_gpio(GPIO_N_BT_RST);               // ask bt_reset gpio, remember to release in remove_function
++      omap_set_gpio_direction(GPIO_N_BT_RST, 1);      // set gpio direction to be output
++      omap_set_gpio_dataout(GPIO_N_BT_RST, 0);        // turn on gpio, note 0 == on for negative gpios
++      
++      /* configure bluetooth UART */
++      //h6300_gpio_mode(GPIO_NR_H6300_BT_RXD_MD);
++      //h6300_gpio_mode(GPIO_NR_H6300_BT_TXD_MD);
++      //h6300_gpio_mode(GPIO_NR_H6300_BT_UART_CTS_MD);
++      //h6300_gpio_mode(GPIO_NR_H6300_BT_UART_RTS_MD);
++
++      funcs->configure        = h6300_bt_configure;
++      funcs->set_txrx         = h6300_bt_set_txrx;
++      funcs->get_txrx         = h6300_bt_get_txrx;
++
++      /* Make sure the LED is off */
++      h6300_clear_led(INDEX_BT_LED);
++      
++      printk(KERN_NOTICE "h6300_bt_brf6100.c h6300_bt_probe() done\n");       
++
++      return 0;
++}
++
++static int
++h6300_bt_remove(struct device *dev)
++{
++      struct h6300_uart_funcs *funcs = (struct h6300_uart_funcs *)dev->platform_data;
++      
++      printk(KERN_NOTICE "h6300_bt_brf6100.c h6300_bt_remove() started\n");   
++      
++      omap_free_gpio(GPIO_BT_PWR_EN);
++      omap_free_gpio(GPIO_N_BT_RST);
++
++      funcs->configure        = NULL;
++      funcs->set_txrx         = NULL;
++      funcs->get_txrx         = NULL;
++
++      /* Make sure the LED is off */
++      h6300_clear_led(INDEX_BT_LED);
++      
++      printk(KERN_NOTICE "h6300_bt_brf6100.c, h6300_bt_remove() done\n");
++
++      return 0;
++}
++
++static struct device_driver bt_driver = {
++      .name     = "h6300_bt",
++      .bus      = &platform_bus_type,
++      .probe    = h6300_bt_probe,
++      .remove   = h6300_bt_remove,
++};
++
++static int __init
++h6300_bt_init(void)
++{
++      printk(KERN_NOTICE "h6300 Bluetooth Driver init()\n");
++      return driver_register(&bt_driver);
++}
++
++static void __exit
++h6300_bt_exit(void)
++{
++      printk(KERN_NOTICE "h6300 Bluetooth Driver exit()\n");
++      driver_unregister(&bt_driver);
++}
++
++module_init(h6300_bt_init);
++module_exit(h6300_bt_exit);
++
++MODULE_AUTHOR("Mika Laitio, <lamikr@cc.jyu.fi>");
++MODULE_DESCRIPTION("iPAQ h6300 BRF6100 Bluetooth driver.");
++MODULE_LICENSE("GPL");
++
+diff -Naur linux-2.6.14-omap2/drivers/bluetooth/omap/h6300_bt_led.c linux-h6300-omap2-2.6.14.3/drivers/bluetooth/omap/h6300_bt_led.c
+--- linux-2.6.14-omap2/drivers/bluetooth/omap/h6300_bt_led.c   1970-01-01 02:00:00.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/drivers/bluetooth/omap/h6300_bt_led.c   2005-10-06 02:34:39.000000000 +0300
+@@ -0,0 +1,41 @@
++/* 
++ * Bluetooth interface driver helper for controlling bluetooth leds available in iPAQ h6300.
++ * 
++ * Copyright (C) 2005 Mika Laitio  <lamikr@cc.jyu.fi>
++ * Ideas from the brf6150 bt driver made by Todd Blumer for the pxa hx4700.
++ * 
++ * This program is free software; you can 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/delay.h>
++#include <linux/device.h>
++
++#include <asm/hardware.h>
++#include <asm/arch/gpio.h>
++
++/* 
++ * Low level access for disabling h6300 bt led.
++ *
++ * TODO: implement for h6300 
++ */
++void h6300_clear_led(int led_num)
++{
++      printk(KERN_NOTICE "h6300_bt_led.c h6300_clear_led() done\n");
++      //hx4700_set_led(led_num, 0, 16);
++}
++EXPORT_SYMBOL(h6300_clear_led);
++
++/* 
++ * Low level access for setting up the bt led.
++ *
++ * TODO: implement for h6300 
++ */
++void h6300_set_led(int led_num, int duty_time, int cycle_time)
++{
++      printk(KERN_NOTICE "h6300_bt_led.c h6300_set_led() done\n");
++}
++EXPORT_SYMBOL(h6300_set_led);
+diff -Naur linux-2.6.14-omap2/drivers/bluetooth/omap/h6300_bt_led.h linux-h6300-omap2-2.6.14.3/drivers/bluetooth/omap/h6300_bt_led.h
+--- linux-2.6.14-omap2/drivers/bluetooth/omap/h6300_bt_led.h   1970-01-01 02:00:00.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/drivers/bluetooth/omap/h6300_bt_led.h   2005-10-06 02:34:39.000000000 +0300
+@@ -0,0 +1,9 @@
++#ifndef H6300_BT_LED_H_
++#define H6300_BT_LED_H_
++
++#define INDEX_BT_LED  2
++
++void h6300_clear_led(int led_num);
++void h6300_set_led(int led_num, int duty_time, int cycle_time);
++
++#endif /*H6300_BT_LED_H_*/
+diff -Naur linux-2.6.14-omap2/drivers/bluetooth/omap/Makefile linux-h6300-omap2-2.6.14.3/drivers/bluetooth/omap/Makefile
+--- linux-2.6.14-omap2/drivers/bluetooth/omap/Makefile 1970-01-01 02:00:00.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/drivers/bluetooth/omap/Makefile 2005-10-06 02:34:39.000000000 +0300
+@@ -0,0 +1,6 @@
++#
++# Makefile for the Linux iPAQ H6300 BRF6100 Bluetooth device drivers.
++#
++
++h6300_bt-objs                         := h6300_bt_led.o h6300_bt_brf6100.o
++obj-$(CONFIG_BT_H6300)                += h6300_bt.o
+diff -Naur linux-2.6.14-omap2/drivers/char/rtc.c linux-h6300-omap2-2.6.14.3/drivers/char/rtc.c
+--- linux-2.6.14-omap2/drivers/char/rtc.c      2005-10-28 03:02:08.000000000 +0300
++++ linux-h6300-omap2-2.6.14.3/drivers/char/rtc.c      2005-12-02 01:34:35.000000000 +0200
+@@ -149,8 +149,22 @@
+ #ifdef RTC_IRQ
+ static void rtc_dropped_irq(unsigned long data);
+-static void set_rtc_irq_bit(unsigned char bit);
+-static void mask_rtc_irq_bit(unsigned char bit);
++static void set_rtc_irq_bit_locked(unsigned char bit);
++static void mask_rtc_irq_bit_locked(unsigned char bit);
++
++static inline void set_rtc_irq_bit(unsigned char bit)
++{
++      spin_lock_irq(&rtc_lock);
++      set_rtc_irq_bit_locked(bit);
++      spin_unlock_irq(&rtc_lock);
++}
++
++static void mask_rtc_irq_bit(unsigned char bit)
++{
++      spin_lock_irq(&rtc_lock);
++      mask_rtc_irq_bit_locked(bit);
++      spin_unlock_irq(&rtc_lock);
++}
+ #endif
+ static int rtc_proc_open(struct inode *inode, struct file *file);
+@@ -401,18 +415,19 @@
+       }
+       case RTC_PIE_OFF:       /* Mask periodic int. enab. bit */
+       {
+-              mask_rtc_irq_bit(RTC_PIE);
++              unsigned long flags; /* can be called from isr via rtc_control() */
++              spin_lock_irqsave (&rtc_lock, flags);
++              mask_rtc_irq_bit_locked(RTC_PIE);
+               if (rtc_status & RTC_TIMER_ON) {
+-                      spin_lock_irq (&rtc_lock);
+                       rtc_status &= ~RTC_TIMER_ON;
+                       del_timer(&rtc_irq_timer);
+-                      spin_unlock_irq (&rtc_lock);
+               }
++              spin_unlock_irqrestore (&rtc_lock, flags);
+               return 0;
+       }
+       case RTC_PIE_ON:        /* Allow periodic ints          */
+       {
+-
++              unsigned long flags; /* can be called from isr via rtc_control() */
+               /*
+                * We don't really want Joe User enabling more
+                * than 64Hz of interrupts on a multi-user machine.
+@@ -421,14 +436,14 @@
+                       (!capable(CAP_SYS_RESOURCE)))
+                       return -EACCES;
++              spin_lock_irqsave (&rtc_lock, flags);
+               if (!(rtc_status & RTC_TIMER_ON)) {
+-                      spin_lock_irq (&rtc_lock);
+                       rtc_irq_timer.expires = jiffies + HZ/rtc_freq + 2*HZ/100;
+                       add_timer(&rtc_irq_timer);
+                       rtc_status |= RTC_TIMER_ON;
+-                      spin_unlock_irq (&rtc_lock);
+               }
+-              set_rtc_irq_bit(RTC_PIE);
++              set_rtc_irq_bit_locked(RTC_PIE);
++              spin_unlock_irqrestore (&rtc_lock, flags);
+               return 0;
+       }
+       case RTC_UIE_OFF:       /* Mask ints from RTC updates.  */
+@@ -609,6 +624,7 @@
+       {
+               int tmp = 0;
+               unsigned char val;
++              unsigned long flags; /* can be called from isr via rtc_control() */
+               /* 
+                * The max we can do is 8192Hz.
+@@ -631,9 +647,9 @@
+               if (arg != (1<<tmp))
+                       return -EINVAL;
+-              spin_lock_irq(&rtc_lock);
++              spin_lock_irqsave(&rtc_lock, flags);
+               if (hpet_set_periodic_freq(arg)) {
+-                      spin_unlock_irq(&rtc_lock);
++                      spin_unlock_irqrestore(&rtc_lock, flags);
+                       return 0;
+               }
+               rtc_freq = arg;
+@@ -641,7 +657,7 @@
+               val = CMOS_READ(RTC_FREQ_SELECT) & 0xf0;
+               val |= (16 - tmp);
+               CMOS_WRITE(val, RTC_FREQ_SELECT);
+-              spin_unlock_irq(&rtc_lock);
++              spin_unlock_irqrestore(&rtc_lock, flags);
+               return 0;
+       }
+ #endif
+@@ -844,12 +860,15 @@
+ #ifndef RTC_IRQ
+       return -EIO;
+ #else
+-      spin_lock_irq(&rtc_task_lock);
++      unsigned long flags;
++      if (cmd != RTC_PIE_ON && cmd != RTC_PIE_OFF && cmd != RTC_IRQP_SET)
++              return -EINVAL;
++      spin_lock_irqsave(&rtc_task_lock, flags);
+       if (rtc_callback != task) {
+-              spin_unlock_irq(&rtc_task_lock);
++              spin_unlock_irqrestore(&rtc_task_lock, flags);
+               return -ENXIO;
+       }
+-      spin_unlock_irq(&rtc_task_lock);
++      spin_unlock_irqrestore(&rtc_task_lock, flags);
+       return rtc_do_ioctl(cmd, arg, 1);
+ #endif
+ }
+@@ -1306,40 +1325,32 @@
+  * meddles with the interrupt enable/disable bits.
+  */
+-static void mask_rtc_irq_bit(unsigned char bit)
++static void mask_rtc_irq_bit_locked(unsigned char bit)
+ {
+       unsigned char val;
+-      spin_lock_irq(&rtc_lock);
+-      if (hpet_mask_rtc_irq_bit(bit)) {
+-              spin_unlock_irq(&rtc_lock);
++      if (hpet_mask_rtc_irq_bit(bit))
+               return;
+-      }
+       val = CMOS_READ(RTC_CONTROL);
+       val &=  ~bit;
+       CMOS_WRITE(val, RTC_CONTROL);
+       CMOS_READ(RTC_INTR_FLAGS);
+       rtc_irq_data = 0;
+-      spin_unlock_irq(&rtc_lock);
+ }
+-static void set_rtc_irq_bit(unsigned char bit)
++static void set_rtc_irq_bit_locked(unsigned char bit)
+ {
+       unsigned char val;
+-      spin_lock_irq(&rtc_lock);
+-      if (hpet_set_rtc_irq_bit(bit)) {
+-              spin_unlock_irq(&rtc_lock);
++      if (hpet_set_rtc_irq_bit(bit))
+               return;
+-      }
+       val = CMOS_READ(RTC_CONTROL);
+       val |= bit;
+       CMOS_WRITE(val, RTC_CONTROL);
+       CMOS_READ(RTC_INTR_FLAGS);
+       rtc_irq_data = 0;
+-      spin_unlock_irq(&rtc_lock);
+ }
+ #endif
+diff -Naur linux-2.6.14-omap2/drivers/hwmon/it87.c linux-h6300-omap2-2.6.14.3/drivers/hwmon/it87.c
+--- linux-2.6.14-omap2/drivers/hwmon/it87.c    2005-10-28 03:02:08.000000000 +0300
++++ linux-h6300-omap2-2.6.14.3/drivers/hwmon/it87.c    2005-12-02 01:34:35.000000000 +0200
+@@ -522,8 +522,15 @@
+       struct i2c_client *client = to_i2c_client(dev);
+       struct it87_data *data = i2c_get_clientdata(client);
+       int val = simple_strtol(buf, NULL, 10);
++      u8 reg = it87_read_value(client, IT87_REG_FAN_DIV);
+       down(&data->update_lock);
++      switch (nr) {
++      case 0: data->fan_div[nr] = reg & 0x07; break;
++      case 1: data->fan_div[nr] = (reg >> 3) & 0x07; break;
++      case 2: data->fan_div[nr] = (reg & 0x40) ? 3 : 1; break;
++      }
++
+       data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
+       it87_write_value(client, IT87_REG_FAN_MIN(nr), data->fan_min[nr]);
+       up(&data->update_lock);
+diff -Naur linux-2.6.14-omap2/drivers/hwmon/lm78.c linux-h6300-omap2-2.6.14.3/drivers/hwmon/lm78.c
+--- linux-2.6.14-omap2/drivers/hwmon/lm78.c    2005-10-28 03:02:08.000000000 +0300
++++ linux-h6300-omap2-2.6.14.3/drivers/hwmon/lm78.c    2005-12-02 01:34:35.000000000 +0200
+@@ -451,7 +451,7 @@
+ static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf)
+ {
+       struct lm78_data *data = lm78_update_device(dev);
+-      return sprintf(buf, "%d\n", vid_from_reg(82, data->vid));
++      return sprintf(buf, "%d\n", vid_from_reg(data->vid, 82));
+ }
+ static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
+diff -Naur linux-2.6.14-omap2/drivers/hwmon/w83627hf.c linux-h6300-omap2-2.6.14.3/drivers/hwmon/w83627hf.c
+--- linux-2.6.14-omap2/drivers/hwmon/w83627hf.c        2005-10-28 03:02:08.000000000 +0300
++++ linux-h6300-omap2-2.6.14.3/drivers/hwmon/w83627hf.c        2005-12-02 01:34:35.000000000 +0200
+@@ -454,7 +454,9 @@
+               (w83627thf == data->type || w83637hf == data->type))
+               /* use VRM9 calculation */
+-              data->in_min[0] = (u8)(((val * 100) - 70000 + 244) / 488);
++              data->in_min[0] =
++                      SENSORS_LIMIT(((val * 100) - 70000 + 244) / 488, 0,
++                                      255);
+       else
+               /* use VRM8 (standard) calculation */
+               data->in_min[0] = IN_TO_REG(val);
+@@ -479,7 +481,9 @@
+               (w83627thf == data->type || w83637hf == data->type))
+               
+               /* use VRM9 calculation */
+-              data->in_max[0] = (u8)(((val * 100) - 70000 + 244) / 488);
++              data->in_max[0] =
++                      SENSORS_LIMIT(((val * 100) - 70000 + 244) / 488, 0,
++                                      255);
+       else
+               /* use VRM8 (standard) calculation */
+               data->in_max[0] = IN_TO_REG(val);
+diff -Naur linux-2.6.14-omap2/drivers/i2c/busses/i2c-omap.c linux-h6300-omap2-2.6.14.3/drivers/i2c/busses/i2c-omap.c
+--- linux-2.6.14-omap2/drivers/i2c/busses/i2c-omap.c   2005-12-02 01:53:32.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/drivers/i2c/busses/i2c-omap.c   2005-10-20 20:53:33.000000000 +0300
+@@ -124,10 +124,10 @@
+ /* I2C System Configuration Register (OMAP_I2C_SYSC): */
+ #define OMAP_I2C_SYSC_SRST            (1 << 1)        /* Soft Reset */
++#undef        I2C_OMAP_DEBUG
+ /* ------- debugging ---------------------------------------------------*/
+-#define I2C_OMAP_DEBUG
+-#ifdef I2c_OMAP_DEBUG
++#ifdef I2C_OMAP_DEBUG
+ static int i2c_debug;
+ module_param(i2c_debug, int, 0);
+diff -Naur linux-2.6.14-omap2/drivers/i2c/chips/Kconfig linux-h6300-omap2-2.6.14.3/drivers/i2c/chips/Kconfig
+--- linux-2.6.14-omap2/drivers/i2c/chips/Kconfig       2005-12-02 01:53:32.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/drivers/i2c/chips/Kconfig       2005-10-14 18:55:31.000000000 +0300
+@@ -56,6 +56,16 @@
+         This driver can also be built as a module.  If so, the module
+         will be called pca9539.
++config PCA9535
++        tristate "Philips PCA9535 16-bit I/O port"
++        depends on I2C 
++        help
++          If you say yes here you get support for the Philips PCA9535
++          16-bit I/O port.
++      
++          This driver can also be built as a module.  If so, the module
++          will be called pca9539.
++
+ config SENSORS_PCF8591
+       tristate "Philips PCF8591"
+       depends on I2C && EXPERIMENTAL
+diff -Naur linux-2.6.14-omap2/drivers/i2c/chips/Makefile linux-h6300-omap2-2.6.14.3/drivers/i2c/chips/Makefile
+--- linux-2.6.14-omap2/drivers/i2c/chips/Makefile      2005-12-02 01:53:32.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/drivers/i2c/chips/Makefile      2005-10-14 18:55:31.000000000 +0300
+@@ -16,6 +16,7 @@
+ obj-$(CONFIG_SENSORS_TLV320AIC23) += tlv320aic23.o
+ obj-$(CONFIG_GPIOEXPANDER_OMAP)       += gpio_expander_omap.o
+ obj-$(CONFIG_MENELAUS)                += menelaus.o
++obj-$(CONFIG_PCA9535)                 += pca9535.o
+ ifeq ($(CONFIG_I2C_DEBUG_CHIP),y)
+ EXTRA_CFLAGS += -DDEBUG
+diff -Naur linux-2.6.14-omap2/drivers/i2c/chips/pca9535.c linux-h6300-omap2-2.6.14.3/drivers/i2c/chips/pca9535.c
+--- linux-2.6.14-omap2/drivers/i2c/chips/pca9535.c     1970-01-01 02:00:00.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/drivers/i2c/chips/pca9535.c     2005-10-25 22:23:21.000000000 +0300
+@@ -0,0 +1,414 @@
++/*
++    Driver for Philips PCA9535 16-bit low power I/O port with interrupt
++
++    This program is free software; you can redistribute it and/or modify
++    it under the terms of the GNU General Public License as published by
++    the Free Software Foundation; either version 2 of the License, or
++    (at your option) any later version.
++    
++    This program is distributed in the hope that it will be useful,
++    but WITHOUT ANY WARRANTY; without even the implied warranty of
++    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++    GNU General Public License for more details.
++
++    You should have received a copy of the GNU General Public License
++    along with this program; if not, write to the Free Software
++    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++    
++    Copyright (C) 2005 Husam Senussi
++    Framework based on Pawel Kolodziejski's pca9535 driver in 
++    handheld.org's 2.6.13 kernel. Driver updated by Mika Laitio.
++*/
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/slab.h>
++#include <linux/i2c.h>
++#include <linux/hwmon-sysfs.h>
++#include <linux/hwmon.h>
++#include <linux/err.h>
++
++#include <asm/arch/pca9535.h>
++#include <linux/delay.h>
++
++#include <linux/interrupt.h>
++#include <asm/mach-types.h>
++#include <asm/irq.h>
++#include <asm/mach/arch.h>
++#include <asm/hardware.h>
++
++EXPORT_SYMBOL(pca9535_gpio_read);
++EXPORT_SYMBOL(pca9535_gpio_write);
++EXPORT_SYMBOL(pca9535_gpio_direction);
++
++static int pca9535_attach_adapter(struct i2c_adapter *adapter);
++static int pca9535_detach_client(struct i2c_client *client);
++static int pca9535_attach(struct i2c_adapter *adapter, int address, int zero_or_minus_one);
++static u32 pca9535_read_reg(struct i2c_client *client, u8 regaddr);
++static void pca9535_write_reg(struct i2c_client *client, u8 regaddr, u16 param);
++
++enum pca9535_cmd
++{
++        PCA9535_INPUT_0         = 0,
++        PCA9535_INPUT_1         = 1,
++        PCA9535_OUTPUT_0        = 2,
++        PCA9535_OUTPUT_1        = 3,
++        PCA9535_INVERT_0        = 4,
++        PCA9535_INVERT_1        = 5,
++        PCA9535_DIRECTION_0     = 6,
++        PCA9535_DIRECTION_1     = 7,
++};
++
++struct pca9535_data {
++      struct semaphore  lock;
++        struct i2c_client client;
++};
++
++static struct i2c_driver pca9535_driver = {
++      .owner                  = THIS_MODULE,
++      .name                   = "pca9535",
++      .flags                  = I2C_DF_NOTIFY,
++      .attach_adapter         = pca9535_attach_adapter,
++      .detach_client          = pca9535_detach_client,
++};
++
++static struct i2c_client   *pca9535_i2c_client = NULL;
++static struct pca9535_data pca9535_inited;
++
++static unsigned short normal_i2c[] = { 0x20, I2C_CLIENT_END };
++
++#define DRIVER_VERSION  "20 OCT 2005"
++#define DRIVER_NAME     "PCA9535"
++
++/* 
++ * sysfs callback function.
++ */ 
++static ssize_t pca9535_show(struct device *dev, struct device_attribute *attr,
++                            char *buf)
++{
++        struct sensor_device_attribute *psa = to_sensor_dev_attr(attr);
++        struct i2c_client *client = to_i2c_client(dev);
++        return sprintf(buf, "%02X\n", (pca9535_read_reg(client, psa->index) >> 8));
++}
++
++/* 
++ * sysfs callback function.
++ */ 
++static ssize_t pca9535_store(struct device *dev, struct device_attribute *attr,
++                             const char *buf, size_t count)
++{
++        struct sensor_device_attribute *psa = to_sensor_dev_attr(attr);
++        struct i2c_client *client = to_i2c_client(dev);
++        unsigned long val = simple_strtoul(buf, NULL, 0);
++      unsigned long old = pca9535_read_reg(client, psa->index);
++
++        if (val > 0xff)
++                return -EINVAL;
++      
++      val = (old & 0xff) | (val << 8);
++        pca9535_write_reg(client, psa->index, val);
++        return count;
++}
++
++#define PCA9535_ENTRY_RO(name, cmd_idx) \
++        static SENSOR_DEVICE_ATTR(name, S_IRUGO, pca9535_show, NULL, cmd_idx)
++
++#define PCA9535_ENTRY_RW(name, cmd_idx) \
++        static SENSOR_DEVICE_ATTR(name, S_IRUGO | S_IWUSR, pca9535_show, \
++                                  pca9535_store, cmd_idx)
++
++PCA9535_ENTRY_RO(input0, PCA9535_INPUT_0);
++PCA9535_ENTRY_RO(input1, PCA9535_INPUT_1);
++PCA9535_ENTRY_RW(output0, PCA9535_OUTPUT_0);
++PCA9535_ENTRY_RW(output1, PCA9535_OUTPUT_1);
++PCA9535_ENTRY_RW(invert0, PCA9535_INVERT_0);
++PCA9535_ENTRY_RW(invert1, PCA9535_INVERT_1);
++PCA9535_ENTRY_RW(direction0, PCA9535_DIRECTION_0);
++PCA9535_ENTRY_RW(direction1, PCA9535_DIRECTION_1);
++
++static struct attribute *pca9535_attributes[] = {
++        &sensor_dev_attr_input0.dev_attr.attr,
++        &sensor_dev_attr_input1.dev_attr.attr,
++        &sensor_dev_attr_output0.dev_attr.attr,
++        &sensor_dev_attr_output1.dev_attr.attr,
++        &sensor_dev_attr_invert0.dev_attr.attr,
++        &sensor_dev_attr_invert1.dev_attr.attr,
++        &sensor_dev_attr_direction0.dev_attr.attr,
++        &sensor_dev_attr_direction1.dev_attr.attr,
++        NULL
++};
++
++static struct attribute_group pca9535_defattr_group = {
++        .attrs = pca9535_attributes,
++};
++//End of sysfs management code. 
++
++I2C_CLIENT_INSMOD;
++
++u32 pca9535_read_input(void)
++{
++      return pca9535_read_reg(pca9535_i2c_client, 0);
++}
++EXPORT_SYMBOL(pca9535_read_input);
++
++void pca9535_write_output(u16 param)
++{
++      pca9535_write_reg(pca9535_i2c_client, 2, param);
++}
++EXPORT_SYMBOL(pca9535_write_output);
++
++void pca9535_set_dir(u16 param)
++{
++      pca9535_write_reg(pca9535_i2c_client, 6, param);
++}
++EXPORT_SYMBOL(pca9535_set_dir);
++
++static int pca9535_attach_adapter(struct i2c_adapter *adapter)
++{
++      return i2c_probe(adapter, &addr_data, pca9535_attach);
++}
++
++static int pca9535_attach(struct i2c_adapter *adapter, int address, int zero_or_minus_one)
++{
++      struct i2c_client *new_client;
++      int err = 0;
++
++      printk("pca9535_attach() started\n");
++      new_client = &(pca9535_inited.client);
++      i2c_set_clientdata(new_client, 0);
++      new_client->addr = address;
++      new_client->adapter = adapter;
++      new_client->driver = &pca9535_driver;
++      new_client->flags = I2C_CLIENT_ALLOW_USE;
++      strcpy(new_client->name, DRIVER_NAME);
++
++      if ((err = i2c_attach_client(new_client)))
++              goto exit_free;
++
++      pca9535_i2c_client = new_client;
++      
++      init_MUTEX(&pca9535_inited.lock);
++      i2c_set_clientdata(pca9535_i2c_client, &pca9535_inited);
++      
++      sysfs_create_group(&pca9535_i2c_client->dev.kobj, &pca9535_defattr_group);
++      
++      printk("pca9535_attach() ok\n");
++      return 0;
++
++exit_free:
++      printk("pca9535_attach() failed, error code = %d\n", err);
++      return err;
++}
++
++static int pca9535_detach_client(struct i2c_client *client)
++{
++      int err;
++
++      if ((err = i2c_detach_client(client))) {
++              dev_err(&client->dev, "Client deregistration failed, client not detached.\n");
++              return err;
++      }
++      pca9535_i2c_client = NULL;
++
++      return 0;
++}
++
++static int __init pca9535_init(void)
++{
++      return i2c_add_driver(&pca9535_driver);
++}
++
++static void __exit pca9535_exit(void)
++{
++        i2c_del_driver(&pca9535_driver);
++}
++
++/* 
++ * Reads the value of GPIO available via I2C.
++ */
++int pca9535_gpio_read(int gpio){
++      unsigned char reg = 0;
++      unsigned long val = 0;
++
++      printk("9535_gpio_read() called\n");
++      if(!pca9535_i2c_client)
++              return -ENODEV;
++
++      if(gpio < GPIO0 || gpio > GPIO17)
++              return -EINVAL;
++
++      if(gpio >= GPIO0 && gpio <= GPIO7){
++              reg      = PCA9535_INPUT_0;
++              gpio    -= GPIO0;
++      }else if(gpio >= GPIO8 && gpio <= GPIO17){
++              reg      = PCA9535_INPUT_1;
++                gpio    -= GPIO8;
++      }
++
++      down(&pca9535_inited.lock);
++
++      // Read the existing values first
++      val = pca9535_read_reg(pca9535_i2c_client, reg) >> 8;
++      val = (val >> gpio) & 0x01;
++
++      up(&pca9535_inited.lock);
++
++      return val;
++}
++
++/* 
++ * Set the value of I2C GPIO.
++ */
++int pca9535_gpio_write(int gpio, unsigned char value){
++      unsigned char in_reg  = 0;
++        unsigned char out_reg = 0;
++        unsigned long val = 0;
++      unsigned long old = 0;
++      int           ret = 0;
++
++        if(!pca9535_i2c_client)
++                return -ENODEV;
++
++        if(gpio < GPIO0 || gpio > GPIO17)
++                return -EINVAL;
++
++        if(gpio >= GPIO0 && gpio <= GPIO7){
++                in_reg   = PCA9535_INPUT_0;
++                out_reg  = PCA9535_OUTPUT_0;
++                gpio    -= GPIO0;
++        }else if(gpio >= GPIO8 && gpio <= GPIO17){
++                in_reg   = PCA9535_INPUT_1;
++                out_reg  = PCA9535_OUTPUT_1;
++                gpio    -= GPIO8;
++        }
++
++      down(&pca9535_inited.lock);
++
++        // Read the existing values first
++        val = pca9535_read_reg(pca9535_i2c_client, in_reg);
++      old = val >> 8;
++
++      switch(value){
++      case LOW:
++              old |= (1 << gpio);
++              break;
++      case HI:
++              old &= ~(1 << gpio);
++              break;
++      default:
++              ret = -EINVAL;
++              goto error;
++      }
++
++      val = (val & 0xff) | (old << 8);        
++
++      // write the values back to the register
++      pca9535_write_reg(pca9535_i2c_client, out_reg, val);
++error:
++
++      up(&pca9535_inited.lock);
++      return ret;
++}
++
++/*
++ * Set the direction of I2C GPIO.
++ */ 
++int pca9535_gpio_direction(int gpio, unsigned char direction){
++        unsigned char reg = 0;
++        unsigned long val = 0;
++      unsigned long old = 0;
++        int           ret = 0;
++
++        if(!pca9535_i2c_client)
++                return -ENODEV;
++
++        if(gpio < GPIO0 || gpio > GPIO17)
++                return -EINVAL;
++
++        if(gpio >= GPIO0 && gpio <= GPIO7){
++                reg            = PCA9535_DIRECTION_0;
++                gpio    -= GPIO0;
++        }else if(gpio >= GPIO8 && gpio <= GPIO17){
++                reg            = PCA9535_DIRECTION_1;
++                gpio    -= GPIO8;
++        }
++
++        down(&pca9535_inited.lock);
++
++        // Read the existing values first
++        old = pca9535_read_reg(pca9535_i2c_client, reg);
++      val = old >> 8;
++
++        switch(direction){
++        case GPIO_INPUT: 
++                val |= (1 << gpio);
++                break;
++        case GPIO_OUTPUT: 
++                val &= ~(1 << gpio);
++                break;
++        default:
++                ret = -EINVAL;
++                goto error;
++        }
++
++      val = (old & 0xff) | (val << 8);
++
++        // write the values back to the register
++        pca9535_write_reg(pca9535_i2c_client, reg, val);
++error:
++
++        up(&pca9535_inited.lock);
++        return ret;
++}
++
++static u32 pca9535_read_reg(struct i2c_client *client, u8 regaddr)
++{
++      char buffer[3];
++      int r;
++      u32 data;
++
++      buffer[0] = regaddr;
++      buffer[1] = 0;
++      buffer[2] = 0;
++
++      r = i2c_master_send(client, buffer, 1);
++      if (r != 1) {
++              printk(KERN_ERR "pca9535: read failed, status %d\n", r);
++              return 0xffffffff;
++      }
++
++      r = i2c_master_recv(client, buffer, 3);
++      if (r != 3) {
++              printk(KERN_ERR "pca9535: read failed, status %d\n", r);
++              return 0xffffffff;
++      }
++
++      data = buffer[1];
++      data |= buffer[2] << 8;
++      //printk(KERN_ERR "%s: reading %x in %x\n", __FUNCTION__, data, regaddr);
++
++      return data;
++}
++
++static void pca9535_write_reg(struct i2c_client *client, u8 regaddr, u16 data)
++{
++      char buffer[3];
++      int r;
++
++      //printk(KERN_ERR "%s: writing %x in %x\n", __FUNCTION__, data, regaddr);
++      buffer[0] = regaddr;
++      buffer[1] = data >> 8;
++      buffer[2] = data & 0xff;
++
++      r = i2c_master_send(client, buffer, 3);
++      if (r != 3) {
++              printk(KERN_ERR "pca9535: write failed, status %d\n", r);
++      }
++}
++
++MODULE_AUTHOR("Husam Senussi <husamsenussi@gmail.com>");
++MODULE_DESCRIPTION("PCA9535 driver");
++MODULE_LICENSE("GPL");
++
++module_init(pca9535_init);
++module_exit(pca9535_exit);
+diff -Naur linux-2.6.14-omap2/drivers/input/keyboard/omap-keypad.c linux-h6300-omap2-2.6.14.3/drivers/input/keyboard/omap-keypad.c
+--- linux-2.6.14-omap2/drivers/input/keyboard/omap-keypad.c    2005-12-02 01:53:33.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/drivers/input/keyboard/omap-keypad.c    2005-11-04 03:06:04.000000000 +0200
+@@ -5,10 +5,11 @@
+  *
+  * Copyright (C) 2003 Nokia Corporation
+  * Written by Timo Teräs <ext-timo.teras@nokia.com>
++ * iPAQ h6300 key and joypad support added by Mika Laitio. (2005)
+  *
+  * Added support for H2 & H3 Keypad
+  * Copyright (C) 2004 Texas Instruments
+- *
++ * 
+  * This program is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License as published by
+  * the Free Software Foundation; either version 2 of the License, or
+@@ -40,6 +41,7 @@
+ #include <asm/arch/mux.h>
+ #undef NEW_BOARD_LEARNING_MODE
++//#define NEW_BOARD_LEARNING_MODE 1
+ static void omap_kp_tasklet(unsigned long);
+ static void omap_kp_timer(unsigned long);
+@@ -48,6 +50,8 @@
+ static unsigned char keypad_state[8];
+ static unsigned int keypad_irq = INT_KEYBOARD;
++static int prevJoypadKeycodePressEmulated;
++
+ static struct timer_list kp_timer;
+ DECLARE_TASKLET_DISABLED(kp_tasklet, omap_kp_tasklet, 0);
+@@ -165,6 +169,47 @@
+       0
+ };
++#define _h6300_KEY_CALENDAR   67      // xmodmap 75 aka F9
++#define _H6300_KEY_TELEPHONE  68      // xmodmap 76 aka F10
++#define _H6300_KEY_HOMEPAGE   87      // xmodmap 87 aka Num_Lock
++#define _H6300_KEY_MAIL               88      // xmodmap 88 aka Scroll_Lock
++
++/*
++ * Following 5 keypad events are not really sent to userspace. 
++ * Instead if the good combination of them is sent, then that is send.
++ * (up, right, down, left, enter)
++ */
++#define       _H6300_JOYPAD_UP_RIGHT          1       // 00001
++#define _H6300_JOYPAD_DOWN_RIGHT      2       // 00010
++#define _h6300_JOYPAD_DOWN_LEFT               4       // 00100
++#define _h6300_JOYPAD_UP_LEFT         8       // 01000
++#define _H6300_JOYPAD_KEY_OK          16      // 10000
++
++static int h6300_keymap[] = {
++      KEY(2, 0, _h6300_KEY_CALENDAR),         // address button in the bottom left    
++      KEY(2, 3, _H6300_KEY_TELEPHONE),        // start call button in the bottom
++      KEY(3, 1, _H6300_KEY_HOMEPAGE),         // stop call button in the bottom
++      KEY(3, 4, _H6300_KEY_MAIL),             // messaging button in the bottom right
++
++      KEY(0, 0, KEY_VOLUMEUP),        // volume up button in the right side
++      KEY(0, 1, KEY_VOLUMEDOWN),      // volume down button in the right side
++      KEY(3, 2, KEY_RECORD),          // record button in the left side
++      
++      KEY(1, 0, _h6300_JOYPAD_UP_LEFT),       
++      KEY(1, 1, _h6300_JOYPAD_DOWN_LEFT),     
++      KEY(1, 2, _H6300_JOYPAD_KEY_OK),                
++      KEY(1, 3, _H6300_JOYPAD_DOWN_RIGHT),
++      KEY(1, 4, _H6300_JOYPAD_UP_RIGHT),      
++      
++      KEY(5, 0, KEY_RIGHT),
++      KEY(5, 1, KEY_DOWN),
++      KEY(5, 2, KEY_LEFT),            
++      KEY(5, 3, KEY_UP),
++      KEY(5, 4, KEY_ENTER),
++
++      0
++};
++
+ static int *keymap;
+ static irqreturn_t omap_kp_interrupt(int irq, void *dev_id,
+@@ -191,7 +236,8 @@
+       for (col = 0; col < 8; col++) {
+               omap_writew(~(1 << col) & 0xff, OMAP_MPUIO_BASE + OMAP_MPUIO_KBC);
+-              if (machine_is_omap_osk() || machine_is_omap_h2() || machine_is_omap_h3()) {
++              if (machine_is_omap_osk() || machine_is_omap_h2() || machine_is_omap_h3()  || machine_is_h6300()) {
++                      // makes keyboard act a little bit slower
+                       udelay(9);
+               } else {
+                       udelay(4);
+@@ -214,26 +260,34 @@
+       return -1;
+ }
++int is_key_down(unsigned char new_state[],
++              int col,
++              int row)
++{
++      return (new_state[col] & (1 << row)) ? 1 : 0;
++}
++
+ static void omap_kp_tasklet(unsigned long data)
+ {
+       unsigned char new_state[8], changed, key_down = 0;
+       int col, row;
+       int spurious = 0;
++      int report_key, report_col, report_row, joypad_checked; // joypad specific variables
+       /* check for any changes */
+       omap_kp_scan_keypad(new_state);
+-
+       /* check for changes and print those */
++      joypad_checked  = 0;
+       for (col = 0; col < 8; col++) {
+               changed = new_state[col] ^ keypad_state[col];
+               key_down |= new_state[col];
+               if (changed == 0)
+                       continue;
+-
++                      
+               for (row = 0; row < 8; row++) {
+                       int key;
+                       if (!(changed & (1 << row)))
+-                              continue;
++                              continue;                               
+ #ifdef NEW_BOARD_LEARNING_MODE
+                       printk(KERN_INFO "omap-keypad: key %d-%d %s\n", col, row, (new_state[col] & (1 << row)) ? "pressed" : "released");
+ #else
+@@ -245,9 +299,173 @@
+                               spurious = 1;
+                               continue;
+                       }
+-
+-                      input_report_key(&omap_kp_dev, key,
+-                                       new_state[col] & (1 << row));
++                      if (machine_is_h6300() && 
++                         ((col == 1) || (col == 5)))
++                      {
++                              if (col == 5)
++                              {
++                                      continue;
++                              }
++                              if ((joypad_checked == 0) &&
++                                  ((key == _H6300_JOYPAD_KEY_OK) ||
++                                   (key == _h6300_JOYPAD_UP_LEFT) ||
++                                   (key == _H6300_JOYPAD_UP_RIGHT) ||
++                                   (key == _H6300_JOYPAD_DOWN_RIGHT) ||
++                                   (key == _h6300_JOYPAD_DOWN_LEFT)))
++                              {
++                                      if (is_key_down(new_state, col, row))
++                                      {
++                                              /*
++                                               * only enter pressed
++                                               * 1 0 0 _H6300_JOYPAD_KEY_OK 0 0
++                                               * --> 100100 == 36
++                                               */
++                                               if (new_state[1] == 36)
++                                               {
++                                                      joypad_checked  = 1;
++                                                      prevJoypadKeycodePressEmulated  = KEY_ENTER;
++                                                      new_state[5]    = 48;   //110000
++                                                      report_key      = prevJoypadKeycodePressEmulated;
++                                                      report_col      = 5;
++                                                      report_row      = 4;
++                                                      input_report_key(&omap_kp_dev,
++                                                                      report_key,
++                                                                      new_state[report_col] & (1 << report_row));                                                     
++                                               }                                              
++                                              /*
++                                               * enter, up_left and up_right sensors pressed.
++                                               * 1 _H6300_JOYPAD_UP_RIGHT 0 _H6300_JOYPAD_KEY_OK 0 _h6300_JOYPAD_UP_LEFT
++                                               * --> 110101 == 53
++                                               * OR
++                                               * 1 KEY_UP_RIGHT 0 0 0 _h6300_JOYPAD_UP_LEFT
++                                               * --> 110001 == 42
++                                               * --> move to up
++                                               */
++                                              else if ((new_state[1] == 53) ||
++                                                       (new_state[1] == 49))
++                                              {
++                                                      joypad_checked  = 1;
++                                                      prevJoypadKeycodePressEmulated  = KEY_UP;
++                                                      new_state[5]    = 40;   //101000
++                                                      report_key      = prevJoypadKeycodePressEmulated;
++                                                      report_col      = 5;
++                                                      report_row      = 3;
++                                                      input_report_key(&omap_kp_dev,
++                                                                      report_key,
++                                                                      new_state[report_col] & (1 << report_row));
++                                              }
++                                              /*
++                                               * enter, down_left and down_right sensors pressed
++                                               * --> 101110 == 46
++                                               * OR
++                                               * down_left and down_right
++                                               * -->101010 == 42
++                                               * --> move to down
++                                               */
++                                              else if ((new_state[1] == 46) ||
++                                                       (new_state[1] == 42))
++                                              {
++                                                      joypad_checked  = 1;
++                                                      prevJoypadKeycodePressEmulated  = KEY_DOWN;
++                                                      new_state[5]    = 34;   //100010
++                                                      report_key      = prevJoypadKeycodePressEmulated;
++                                                      report_col      = 5;
++                                                      report_row      = 1;
++                                                      input_report_key(&omap_kp_dev,
++                                                                      report_key,
++                                                                      new_state[report_col] & (1 << report_row));
++                                              }                                                                                               
++                                              /*
++                                               * enter, up_right and down_right sensors pressed
++                                               * --> 111100 == 60
++                                               * or
++                                               * down_right and up_right
++                                               * --> 111000 == 56
++                                               * --> move to right
++                                               */
++                                              else if ((new_state[1] == 60) ||
++                                                       (new_state[1] == 56))
++                                              {
++                                                      joypad_checked  = 1;
++                                                      prevJoypadKeycodePressEmulated  = KEY_RIGHT;
++                                                      new_state[5]    = 33;   //100001
++                                                      report_key      = prevJoypadKeycodePressEmulated;
++                                                      report_col      = 5;
++                                                      report_row      = 0;
++                                                      input_report_key(&omap_kp_dev,
++                                                                      report_key,
++                                                                      new_state[report_col] & (1 << report_row));
++                                              }
++                                              /*
++                                               * enter, up_left and down_left sensors pressed
++                                               * --> 100111 == 39
++                                               * or up_left and down_left
++                                               * --> 100011 == 35
++                                               * --> move to left
++                                               */
++                                              else if ((new_state[1] == 39) ||
++                                                       (new_state[1] == 35))
++                                              {
++                                                      joypad_checked  = 1;
++                                                      prevJoypadKeycodePressEmulated  = KEY_LEFT;
++                                                      new_state[5]    = 36;   //100100
++                                                      report_key      = prevJoypadKeycodePressEmulated;
++                                                      report_col      = 5;
++                                                      report_row      = 2;
++                                                      input_report_key(&omap_kp_dev,
++                                                                      report_key,
++                                                                      new_state[report_col] & (1 << report_row));
++                                              }
++                                              else
++                                              {
++                                                      //printk("missed new_state = %d\n", new_state[1]);
++                                              }
++                                      }
++                                      else
++                                      {
++                                              if (prevJoypadKeycodePressEmulated != 0)
++                                              {
++                                                      // report key up event
++                                                      joypad_checked  = 1;
++                                                      new_state[5]    = 32;   //100000
++                                                      report_key      = prevJoypadKeycodePressEmulated;
++                                                      report_col      = 5;
++                                                      switch(prevJoypadKeycodePressEmulated)
++                                                      {
++                                                              case KEY_RIGHT:
++                                                                      report_row      = 0;
++                                                                      break;
++                                                              case KEY_DOWN:
++                                                                      report_row      = 1;
++                                                                      break;
++                                                              case KEY_LEFT:
++                                                                      report_row      = 2;
++                                                                      break;
++                                                              case KEY_UP:
++                                                                      report_row      = 3;
++                                                                      break;
++                                                              case KEY_ENTER:
++                                                                      report_row      = 4;
++                                                                      break;
++                                                              default:
++                                                                      printk(KERN_WARNING "Unknown iPAQ h6300 column 1 key = %d released. This should newer happen!\n",
++                                                                              key);
++                                                                      report_row      = 0;
++                                                      }
++                                                      input_report_key(&omap_kp_dev,
++                                                                      report_key,
++                                                                      new_state[report_col] & (1 << report_row));
++                                                      prevJoypadKeycodePressEmulated  = 0;                                                            
++                                              }
++                                      }
++                              }
++                      }
++                      else
++                      {
++                              input_report_key(&omap_kp_dev, 
++                                              key,
++                                              new_state[col] & (1 << row));
++                      }
+ #endif
+               }
+       }
+@@ -285,7 +503,12 @@
+       } else if (machine_is_omap_perseus2()) {
+               keymap = p2_keymap;
+               keypad_irq = INT_730_MPUIO_KEYPAD;
++      } else if (machine_is_h6300()) {
++              keymap = h6300_keymap;
++              // set keyboard to send repeated key events if key is hold down
++              set_bit(EV_REP, omap_kp_dev.evbit);
+       } else {
++              printk("omap_keypad.c, keyMap = test_keymap\n");
+               keymap = test_keymap;
+       }
+@@ -305,7 +528,7 @@
+       omap_kp_dev.name = "omap-keypad";
+       input_register_device(&omap_kp_dev);
+-      if (machine_is_omap_h2() || machine_is_omap_h3()) {
++      if (machine_is_omap_h2() || machine_is_omap_h3() || machine_is_h6300()) {
+               omap_cfg_reg(F18_1610_KBC0);
+               omap_cfg_reg(D20_1610_KBC1);
+               omap_cfg_reg(D19_1610_KBC2);
+@@ -335,6 +558,7 @@
+               omap_writew(0xff, OMAP_MPUIO_BASE + OMAP_MPUIO_GPIO_DEBOUNCING);
+       }
++      prevJoypadKeycodePressEmulated          = 0;
+       /* scan current status and enable interrupt */
+       omap_kp_scan_keypad(keypad_state);
+diff -Naur linux-2.6.14-omap2/drivers/input/touchscreen/omap/Makefile linux-h6300-omap2-2.6.14.3/drivers/input/touchscreen/omap/Makefile
+--- linux-2.6.14-omap2/drivers/input/touchscreen/omap/Makefile 2005-12-02 01:53:33.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/drivers/input/touchscreen/omap/Makefile 2005-10-22 03:52:45.000000000 +0300
+@@ -8,5 +8,6 @@
+ objs-$(CONFIG_ARCH_OMAP16XX)$(CONFIG_MACH_OMAP_H3) += ts_hx.o
+ objs-$(CONFIG_ARCH_OMAP15XX)$(CONFIG_MACH_OMAP_INNOVATOR) += ts_inn1510.o
+ objs-$(CONFIG_ARCH_OMAP16XX)$(CONFIG_MACH_OMAP_OSK) += ts_osk.o
++objs-$(CONFIG_ARCH_OMAP15XX)$(CONFIG_MACH_OMAP_H6300) += ts_hx.o
+ omapts-objs := omap_ts.o $(objs-yy)
+diff -Naur linux-2.6.14-omap2/drivers/input/touchscreen/omap/omap_ts.c linux-h6300-omap2-2.6.14.3/drivers/input/touchscreen/omap/omap_ts.c
+--- linux-2.6.14-omap2/drivers/input/touchscreen/omap/omap_ts.c        2005-12-02 01:53:33.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/drivers/input/touchscreen/omap/omap_ts.c        2005-10-22 03:52:45.000000000 +0300
+@@ -46,7 +46,7 @@
+ #define OMAP_TS_NAME  "omap_ts"
+ static struct ts_device *__initdata ts_devs[] = {
+-#if defined(CONFIG_MACH_OMAP_H2) || defined(CONFIG_MACH_OMAP_H3)
++#if defined(CONFIG_MACH_OMAP_H2) || defined(CONFIG_MACH_OMAP_H3) || defined(CONFIG_MACH_OMAP_H6300)
+       &hx_ts,
+ #endif
+ #ifdef CONFIG_MACH_OMAP_OSK
+diff -Naur linux-2.6.14-omap2/drivers/input/touchscreen/omap/ts_hx.c linux-h6300-omap2-2.6.14.3/drivers/input/touchscreen/omap/ts_hx.c
+--- linux-2.6.14-omap2/drivers/input/touchscreen/omap/ts_hx.c  2005-12-02 01:53:33.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/drivers/input/touchscreen/omap/ts_hx.c  2005-09-28 02:45:59.000000000 +0300
+@@ -33,6 +33,7 @@
+ #include <asm/arch/mux.h>
+ #include <asm/arch/hardware.h>
+ #include <asm/hardware/tsc2101.h>
++#include <linux/delay.h>
+ #include "../drivers/ssi/omap-tsc2101.h"
+ #include "omap_ts.h"
+@@ -88,14 +89,19 @@
+       } else if (machine_is_omap_h3()) {
+               gpio = H3_GPIO_NUM;
+               omap_cfg_reg(W19_1610_GPIO48);
++      } else if (machine_is_h6300 ()) {
++              gpio = 2;
++              omap_cfg_reg(M14_1510_GPIO2);   
+       } else
+               return -ENODEV;
+       ts->irq = OMAP_GPIO_IRQ(gpio);
+-      if (omap_request_gpio(gpio) != 0) {
+-              printk(KERN_ERR "hX_ts_init.c: Could not reserve GPIO!\n");
+-              return -EINVAL;
+-      };
++      if (!machine_is_h6300 ()){
++              if (omap_request_gpio(gpio) != 0) {
++                      printk(KERN_ERR "hX_ts_init.c: Could not reserve GPIO!\n");
++                      return -EINVAL;
++              };
++      }
+       omap_set_gpio_direction(gpio, 1);
+       set_irq_type(ts->irq, IRQT_FALLING);
+@@ -180,5 +186,7 @@
+               omap_free_gpio(H2_GPIO_NUM);
+       else if (machine_is_omap_h3())
+               omap_free_gpio(H3_GPIO_NUM);
++      else if (machine_is_h6300())
++              omap_free_gpio(2);
+ }
+ #endif
+diff -Naur linux-2.6.14-omap2/drivers/isdn/hardware/eicon/os_4bri.c linux-h6300-omap2-2.6.14.3/drivers/isdn/hardware/eicon/os_4bri.c
+--- linux-2.6.14-omap2/drivers/isdn/hardware/eicon/os_4bri.c   2005-10-28 03:02:08.000000000 +0300
++++ linux-h6300-omap2-2.6.14.3/drivers/isdn/hardware/eicon/os_4bri.c   2005-12-02 01:34:35.000000000 +0200
+@@ -16,6 +16,7 @@
+ #include "diva_pci.h"
+ #include "mi_pc.h"
+ #include "dsrv4bri.h"
++#include "helpers.h"
+ static void *diva_xdiLoadFileFile = NULL;
+ static dword diva_xdiLoadFileLength = 0;
+@@ -815,7 +816,7 @@
+       return (ret);
+ }
+-void *xdiLoadFile(char *FileName, unsigned long *FileLength,
++void *xdiLoadFile(char *FileName, dword *FileLength,
+                 unsigned long lim)
+ {
+       void *ret = diva_xdiLoadFileFile;
+diff -Naur linux-2.6.14-omap2/drivers/mmc/mmc.c linux-h6300-omap2-2.6.14.3/drivers/mmc/mmc.c
+--- linux-2.6.14-omap2/drivers/mmc/mmc.c       2005-12-02 01:53:33.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/drivers/mmc/mmc.c       2005-11-05 00:46:08.000000000 +0200
+@@ -495,6 +495,7 @@
+               case 2: /* MMC v2.0 - v2.2 */
+               case 3: /* MMC v3.1 - v3.3 */
++              case 4: /* MMC v4 */
+                       card->cid.manfid        = UNSTUFF_BITS(resp, 120, 8);
+                       card->cid.oemid         = UNSTUFF_BITS(resp, 104, 16);
+                       card->cid.prod_name[0]  = UNSTUFF_BITS(resp, 96, 8);
+diff -Naur linux-2.6.14-omap2/drivers/net/wan/hdlc_cisco.c linux-h6300-omap2-2.6.14.3/drivers/net/wan/hdlc_cisco.c
+--- linux-2.6.14-omap2/drivers/net/wan/hdlc_cisco.c    2005-10-28 03:02:08.000000000 +0300
++++ linux-h6300-omap2-2.6.14.3/drivers/net/wan/hdlc_cisco.c    2005-12-02 01:34:35.000000000 +0200
+@@ -192,7 +192,9 @@
+                                              "uptime %ud%uh%um%us)\n",
+                                              dev->name, days, hrs,
+                                              min, sec);
++#if 0
+                                       netif_carrier_on(dev);
++#endif
+                                       hdlc->state.cisco.up = 1;
+                               }
+                       }
+@@ -225,7 +227,9 @@
+                      hdlc->state.cisco.settings.timeout * HZ)) {
+               hdlc->state.cisco.up = 0;
+               printk(KERN_INFO "%s: Link down\n", dev->name);
++#if 0
+               netif_carrier_off(dev);
++#endif
+       }
+       cisco_keepalive_send(dev, CISCO_KEEPALIVE_REQ,
+@@ -261,8 +265,10 @@
+ {
+       hdlc_device *hdlc = dev_to_hdlc(dev);
+       del_timer_sync(&hdlc->state.cisco.timer);
++#if 0
+       if (netif_carrier_ok(dev))
+               netif_carrier_off(dev);
++#endif
+       hdlc->state.cisco.up = 0;
+       hdlc->state.cisco.request_sent = 0;
+ }
+diff -Naur linux-2.6.14-omap2/drivers/net/wan/hdlc_fr.c linux-h6300-omap2-2.6.14.3/drivers/net/wan/hdlc_fr.c
+--- linux-2.6.14-omap2/drivers/net/wan/hdlc_fr.c       2005-10-28 03:02:08.000000000 +0300
++++ linux-h6300-omap2-2.6.14.3/drivers/net/wan/hdlc_fr.c       2005-12-02 01:34:35.000000000 +0200
+@@ -545,8 +545,10 @@
+       hdlc->state.fr.reliable = reliable;
+       if (reliable) {
++#if 0
+               if (!netif_carrier_ok(dev))
+                       netif_carrier_on(dev);
++#endif
+               hdlc->state.fr.n391cnt = 0; /* Request full status */
+               hdlc->state.fr.dce_changed = 1;
+@@ -560,8 +562,10 @@
+                       }
+               }
+       } else {
++#if 0
+               if (netif_carrier_ok(dev))
+                       netif_carrier_off(dev);
++#endif
+               while (pvc) {           /* Deactivate all PVCs */
+                       pvc_carrier(0, pvc);
+diff -Naur linux-2.6.14-omap2/drivers/net/wan/hdlc_generic.c linux-h6300-omap2-2.6.14.3/drivers/net/wan/hdlc_generic.c
+--- linux-2.6.14-omap2/drivers/net/wan/hdlc_generic.c  2005-10-28 03:02:08.000000000 +0300
++++ linux-h6300-omap2-2.6.14.3/drivers/net/wan/hdlc_generic.c  2005-12-02 01:34:35.000000000 +0200
+@@ -79,11 +79,13 @@
+       hdlc_device *hdlc = dev_to_hdlc(dev);
+       if (hdlc->proto.start)
+               return hdlc->proto.start(dev);
++#if 0
+ #ifdef DEBUG_LINK
+       if (netif_carrier_ok(dev))
+               printk(KERN_ERR "hdlc_set_carrier_on(): already on\n");
+ #endif
+       netif_carrier_on(dev);
++#endif
+ }
+@@ -94,11 +96,13 @@
+       if (hdlc->proto.stop)
+               return hdlc->proto.stop(dev);
++#if 0
+ #ifdef DEBUG_LINK
+       if (!netif_carrier_ok(dev))
+               printk(KERN_ERR "hdlc_set_carrier_off(): already off\n");
+ #endif
+       netif_carrier_off(dev);
++#endif
+ }
+@@ -294,8 +298,10 @@
+       if (result != 0)
+               return -EIO;
++#if 0
+       if (netif_carrier_ok(dev))
+               netif_carrier_off(dev); /* no carrier until DCD goes up */
++#endif
+       return 0;
+ }
+diff -Naur linux-2.6.14-omap2/drivers/net/wireless/airo.c linux-h6300-omap2-2.6.14.3/drivers/net/wireless/airo.c
+--- linux-2.6.14-omap2/drivers/net/wireless/airo.c     2005-10-28 03:02:08.000000000 +0300
++++ linux-h6300-omap2-2.6.14.3/drivers/net/wireless/airo.c     2005-11-23 01:44:02.000000000 +0200
+@@ -46,6 +46,8 @@
+ #include <linux/pci.h>
+ #include <asm/uaccess.h>
++#include "airo.h"
++
+ #ifdef CONFIG_PCI
+ static struct pci_device_id card_ids[] = {
+       { 0x14b9, 1, PCI_ANY_ID, PCI_ANY_ID, },
+diff -Naur linux-2.6.14-omap2/drivers/net/wireless/airo_cs.c linux-h6300-omap2-2.6.14.3/drivers/net/wireless/airo_cs.c
+--- linux-2.6.14-omap2/drivers/net/wireless/airo_cs.c  2005-10-28 03:02:08.000000000 +0300
++++ linux-h6300-omap2-2.6.14.3/drivers/net/wireless/airo_cs.c  2005-11-23 01:44:02.000000000 +0200
+@@ -42,6 +42,8 @@
+ #include <asm/io.h>
+ #include <asm/system.h>
++#include "airo.h"
++
+ /*
+    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
+@@ -78,10 +80,6 @@
+    event handler. 
+ */
+-struct net_device *init_airo_card( int, int, int, struct device * );
+-void stop_airo_card( struct net_device *, int );
+-int reset_airo_card( struct net_device * );
+-
+ static void airo_config(dev_link_t *link);
+ static void airo_release(dev_link_t *link);
+ static int airo_event(event_t event, int priority,
+diff -Naur linux-2.6.14-omap2/drivers/net/wireless/airo.h linux-h6300-omap2-2.6.14.3/drivers/net/wireless/airo.h
+--- linux-2.6.14-omap2/drivers/net/wireless/airo.h     1970-01-01 02:00:00.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/drivers/net/wireless/airo.h     2005-11-23 01:44:02.000000000 +0200
+@@ -0,0 +1,9 @@
++#ifndef _AIRO_H_
++#define _AIRO_H_
++
++struct net_device *init_airo_card(unsigned short irq, int port, int is_pcmcia,
++                                struct device *dmdev);
++int reset_airo_card(struct net_device *dev);
++void stop_airo_card(struct net_device *dev, int freeres);
++
++#endif  /*  _AIRO_H_  */
+diff -Naur linux-2.6.14-omap2/drivers/net/wireless/Kconfig linux-h6300-omap2-2.6.14.3/drivers/net/wireless/Kconfig
+--- linux-2.6.14-omap2/drivers/net/wireless/Kconfig    2005-10-28 03:02:08.000000000 +0300
++++ linux-h6300-omap2-2.6.14.3/drivers/net/wireless/Kconfig    2005-10-22 03:52:45.000000000 +0300
+@@ -483,5 +483,7 @@
+       depends on NET_RADIO && (ISA || PCI || PPC_PMAC || PCMCIA)
+       default y
++source "drivers/net/wireless/tiacx/Kconfig"
++
+ endmenu
+diff -Naur linux-2.6.14-omap2/drivers/net/wireless/Makefile linux-h6300-omap2-2.6.14.3/drivers/net/wireless/Makefile
+--- linux-2.6.14-omap2/drivers/net/wireless/Makefile   2005-10-28 03:02:08.000000000 +0300
++++ linux-h6300-omap2-2.6.14.3/drivers/net/wireless/Makefile   2005-10-14 18:55:31.000000000 +0300
+@@ -39,3 +39,4 @@
+ # 16-bit wireless PCMCIA client drivers
+ obj-$(CONFIG_PCMCIA_RAYCS)    += ray_cs.o
+ obj-$(CONFIG_PCMCIA_WL3501)   += wl3501_cs.o
++obj-$(CONFIG_ACX)             += tiacx/
+diff -Naur linux-2.6.14-omap2/drivers/net/wireless/prism54/islpci_eth.c linux-h6300-omap2-2.6.14.3/drivers/net/wireless/prism54/islpci_eth.c
+--- linux-2.6.14-omap2/drivers/net/wireless/prism54/islpci_eth.c       2005-10-28 03:02:08.000000000 +0300
++++ linux-h6300-omap2-2.6.14.3/drivers/net/wireless/prism54/islpci_eth.c       2005-11-23 01:44:02.000000000 +0200
+@@ -97,12 +97,6 @@
+       /* lock the driver code */
+       spin_lock_irqsave(&priv->slock, flags);
+-      /* determine the amount of fragments needed to store the frame */
+-
+-      frame_size = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;
+-      if (init_wds)
+-              frame_size += 6;
+-
+       /* check whether the destination queue has enough fragments for the frame */
+       curr_frag = le32_to_cpu(cb->driver_curr_frag[ISL38XX_CB_TX_DATA_LQ]);
+       if (unlikely(curr_frag - priv->free_data_tx >= ISL38XX_CB_TX_QSIZE)) {
+@@ -213,6 +207,7 @@
+       /* store the skb address for future freeing  */
+       priv->data_low_tx[index] = skb;
+       /* set the proper fragment start address and size information */
++      frame_size = skb->len;
+       fragment->size = cpu_to_le16(frame_size);
+       fragment->flags = cpu_to_le16(0);       /* set to 1 if more fragments */
+       fragment->address = cpu_to_le32(pci_map_address);
+diff -Naur linux-2.6.14-omap2/drivers/net/wireless/tiacx/acx_config.h linux-h6300-omap2-2.6.14.3/drivers/net/wireless/tiacx/acx_config.h
+--- linux-2.6.14-omap2/drivers/net/wireless/tiacx/acx_config.h 1970-01-01 02:00:00.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/drivers/net/wireless/tiacx/acx_config.h 2005-09-28 23:54:23.000000000 +0300
+@@ -0,0 +1,44 @@
++/* temporary hack until proper Kconfig integration */
++#define CONFIG_ACX_PCI 1
++#define CONFIG_ACX_USB 1
++
++#define WLAN_RELEASE "v0.3.10"
++
++/* 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 2
++
++/* assume 32bit I/O width
++ * (16bit is also compatible with Compact Flash) */
++#define ACX_IO_WIDTH 16
++
++/* 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
++
++/* set to 1 if you want to have 1 driver per card instead of 1 single driver
++ * managing all cards (of a particular bus type) in your system
++ * Useful e.g. if you need to reinitialize single cards from time to time
++ * LINUX 2.4.X ONLY!! (pci_for_each_dev()) Feel free to implement 2.6.x
++ * compatibility... */
++#define SEPARATE_DRIVER_INSTANCES 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
+diff -Naur linux-2.6.14-omap2/drivers/net/wireless/tiacx/acx_func.h linux-h6300-omap2-2.6.14.3/drivers/net/wireless/tiacx/acx_func.h
+--- linux-2.6.14-omap2/drivers/net/wireless/tiacx/acx_func.h   1970-01-01 02:00:00.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/drivers/net/wireless/tiacx/acx_func.h   2005-09-28 23:54:23.000000000 +0300
+@@ -0,0 +1,660 @@
++/***********************************************************************
++** 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 acxlog() 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 acxlog(), 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 acxlog(chan, args...) \
++      do { \
++              if (acx_debug & (chan)) \
++                      printk(args); \
++      } while (0)
++#define printk_ratelimited(args...) printk(args)
++
++#else /* Non-debug build: */
++
++#define acxlog(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-entended 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;
++}
++
++
++/***********************************************************************
++** LOCKING
++** We have priv->sem and priv->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. priv->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 inder lock
++**
++** 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(wlandevice_t *priv, const char* where);
++void acx_unlock_debug(wlandevice_t *priv, const char* where);
++void acx_down_debug(wlandevice_t *priv, const char* where);
++void acx_up_debug(wlandevice_t *priv, const char* where);
++void acx_lock_unhold(void);
++void acx_sem_unhold(void);
++
++static inline void
++acx_lock_helper(wlandevice_t *priv, unsigned long *fp, const char* where)
++{
++      acx_lock_debug(priv, where);
++      spin_lock_irqsave(&priv->lock, *fp);
++}
++static inline void
++acx_unlock_helper(wlandevice_t *priv, unsigned long *fp, const char* where)
++{
++      acx_unlock_debug(priv, where);
++      spin_unlock_irqrestore(&priv->lock, *fp);
++}
++static inline void
++acx_down_helper(wlandevice_t *priv, const char* where)
++{
++      acx_down_debug(priv, where);
++}
++static inline void
++acx_up_helper(wlandevice_t *priv, const char* where)
++{
++      acx_up_debug(priv, where);
++}
++#define acx_lock(priv, flags) acx_lock_helper(priv, &(flags), __FILE__ ":" STRING(__LINE__))
++#define acx_unlock(priv, flags)       acx_unlock_helper(priv, &(flags), __FILE__ ":" STRING(__LINE__))
++#define acx_sem_lock(priv)    acx_down_helper(priv, __FILE__ ":" STRING(__LINE__))
++#define acx_sem_unlock(priv)  acx_up_helper(priv, __FILE__ ":" STRING(__LINE__))
++
++#elif defined(DO_LOCKING)
++
++#define acx_lock(priv, flags) spin_lock_irqsave(&priv->lock, flags)
++#define acx_unlock(priv, flags)       spin_unlock_irqrestore(&priv->lock, flags)
++#define acx_sem_lock(priv)    down(&priv->sem)
++#define acx_sem_unlock(priv)  up(&priv->sem)
++#define acx_lock_unhold()     ((void)0)
++#define acx_sem_unhold()      ((void)0)
++
++#else /* no locking! :( */
++
++#define acx_lock(priv, flags) ((void)0)
++#define acx_unlock(priv, flags)       ((void)0)
++#define acx_sem_lock(priv)    ((void)0)
++#define acx_sem_unlock(priv)  ((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 -> acx_l_clean_tx_desc -> acx_wake_queue
++** Review carefully all callsites */
++static inline void
++acx_stop_queue(netdevice_t *dev, const char *msg)
++{
++      if(netif_queue_stopped(dev))
++              return;
++
++      netif_stop_queue(dev);
++      if (msg)
++              acxlog(L_BUFT, "tx: stop queue %s\n", msg);
++}
++
++static inline int
++acx_queue_stopped(netdevice_t *dev)
++{
++      return netif_queue_stopped(dev);
++}
++
++static inline void
++acx_start_queue(netdevice_t *dev, const char *msg)
++{
++      netif_start_queue(dev);
++      if (msg)
++              acxlog(L_BUFT, "tx: start queue %s\n", msg);
++}
++
++static inline void
++acx_wake_queue(netdevice_t *dev, const char *msg)
++{
++      netif_wake_queue(dev);
++      if (msg)
++              acxlog(L_BUFT, "tx: wake queue %s\n", msg);
++}
++
++static inline void
++acx_carrier_off(netdevice_t *dev, const char *msg)
++{
++      netif_carrier_off(dev);
++      if (msg)
++              acxlog(L_BUFT, "tx: carrier off %s\n", msg);
++}
++
++static inline void
++acx_carrier_on(netdevice_t *dev, const char *msg)
++{
++      netif_carrier_on(dev);
++      if (msg)
++              acxlog(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(wlandevice_t *priv, 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(wlandevice_t *priv, unsigned cmd, void *param, unsigned len, unsigned timeout, const char* cmdstr);
++int acxusb_s_issue_cmd_timeo_debug(wlandevice_t *priv, unsigned cmd, void *param, unsigned len, unsigned timeout, const char* cmdstr);
++static inline int
++acx_s_issue_cmd_timeo_debug(wlandevice_t *priv, unsigned cmd, void *param, unsigned len, unsigned timeout, const char* cmdstr)
++{
++#if defined(CONFIG_ACX_CFI)
++      return acxpci_s_issue_cmd_timeo_debug(priv, cmd, param, len, timeout, cmdstr);
++#else
++      if (IS_PCI(priv))
++              return acxpci_s_issue_cmd_timeo_debug(priv, cmd, param, len, timeout, cmdstr);
++      return acxusb_s_issue_cmd_timeo_debug(priv, cmd, param, len, timeout, cmdstr);
++#endif
++}
++#define acx_s_issue_cmd(priv,cmd,param,len) \
++      acx_s_issue_cmd_timeo_debug(priv,cmd,param,len,ACX_CMD_TIMEOUT_DEFAULT,#cmd)
++#define acx_s_issue_cmd_timeo(priv,cmd,param,len,timeo) \
++      acx_s_issue_cmd_timeo_debug(priv,cmd,param,len,timeo,#cmd)
++int acx_s_configure_debug(wlandevice_t *priv, void *pdr, int type, const char* str);
++#define acx_s_configure(priv,pdr,type) \
++      acx_s_configure_debug(priv,pdr,type,#type)
++int acx_s_interrogate_debug(wlandevice_t *priv, void *pdr, int type, const char* str);
++#define acx_s_interrogate(priv,pdr,type) \
++      acx_s_interrogate_debug(priv,pdr,type,#type)
++
++#else
++
++int acxpci_s_issue_cmd_timeo(wlandevice_t *priv, unsigned cmd, void *param, unsigned len, unsigned timeout);
++int acxusb_s_issue_cmd_timeo(wlandevice_t *priv, unsigned cmd, void *param, unsigned len, unsigned timeout);
++static inline int
++acx_s_issue_cmd_timeo(wlandevice_t *priv, unsigned cmd,       void *param, unsigned len, unsigned timeout)
++{
++      if (IS_PCI(priv))
++              return acxpci_s_issue_cmd_timeo(priv, cmd, param, len, timeout);
++      return acxusb_s_issue_cmd_timeo(priv, cmd, param, len, timeout);
++}
++static inline int
++acx_s_issue_cmd(wlandevice_t *priv, unsigned cmd, void *param, unsigned len)
++{
++      if (IS_PCI(priv))
++              return acxpci_s_issue_cmd_timeo(priv, cmd, param, len, ACX_CMD_TIMEOUT_DEFAULT);
++      return acxusb_s_issue_cmd_timeo(priv, cmd, param, len, ACX_CMD_TIMEOUT_DEFAULT);
++}
++int acx_s_configure(wlandevice_t *priv, void *pdr, int type);
++int acx_s_interrogate(wlandevice_t *priv, void *pdr, int type);
++
++#endif
++
++void acx_s_cmd_start_scan(wlandevice_t *priv);
++
++
++/***********************************************************************
++** Ioctls
++*/
++int
++acx111pci_ioctl_info(
++      struct net_device *dev,
++      struct iw_request_info *info,
++      struct iw_param *vwrq,
++      char *extra);
++int
++acx100pci_ioctl_set_phy_amp_bias(
++      struct net_device *dev,
++      struct iw_request_info *info,
++      struct iw_param *vwrq,
++      char *extra);
++
++
++/***********************************************************************
++** Unsorted yet :)
++*/
++int acxpci_s_read_phy_reg(wlandevice_t *priv, u32 reg, u8 *charbuf);
++int acxusb_s_read_phy_reg(wlandevice_t *priv, u32 reg, u8 *charbuf);
++static inline int
++acx_s_read_phy_reg(wlandevice_t *priv, u32 reg, u8 *charbuf)
++{
++#if defined(CONFIG_ACX_CFI)
++      return acxpci_s_read_phy_reg(priv, reg, charbuf);
++#else
++      if (IS_PCI(priv))
++              return acxpci_s_read_phy_reg(priv, reg, charbuf);
++      return acxusb_s_read_phy_reg(priv, reg, charbuf);
++#endif
++}
++
++int acxpci_s_write_phy_reg(wlandevice_t *priv, u32 reg, u8 value);
++int acxusb_s_write_phy_reg(wlandevice_t *priv, u32 reg, u8 value);
++static inline int
++acx_s_write_phy_reg(wlandevice_t *priv, u32 reg, u8 value)
++{
++#if defined(CONFIG_ACX_CFI)
++      return acxpci_s_write_phy_reg(priv, reg, value);
++#else
++      if (IS_PCI(priv))
++              return acxpci_s_write_phy_reg(priv, reg, value);
++      return acxusb_s_write_phy_reg(priv, reg, value);
++#endif
++}
++
++void acx_s_msleep(int ms);
++int acx_s_init_mac(netdevice_t *dev);
++void acx_set_reg_domain(wlandevice_t *priv, unsigned char reg_dom_id);
++void acx_set_timer(wlandevice_t *priv, int timeout_us);
++void acx_update_capabilities(wlandevice_t *priv);
++int acx_read_eeprom_offset(wlandevice_t *priv, u32 addr, u8 *charbuf);
++void acx_s_start(wlandevice_t *priv);
++#if USE_FW_LOADER_26
++firmware_image_t *acx_s_read_fw(struct device *dev, const char *file, u32 *size);
++#else
++firmware_image_t *acx_s_read_fw(const char *file, u32 *size);
++#define acx_s_read_fw(dev, file, size) acx_s_read_fw(file, size)
++#endif
++void acx_s_initialize_rx_config(wlandevice_t *priv);
++void acx_s_update_card_settings(wlandevice_t *priv, int get_all, int set_all);
++void acx_init_task_scheduler(wlandevice_t *priv);
++void acx_schedule_after_interrupt_task(wlandevice_t *priv, unsigned int set_flag);
++int acx_s_upload_radio(wlandevice_t *priv);
++void acx_read_configoption(wlandevice_t *priv);
++int acx_proc_register_entries(const struct net_device *dev);
++int acx_proc_unregister_entries(const struct net_device *dev);
++void acx_l_update_ratevector(wlandevice_t *priv);
++
++int acx_e_ioctl_old(netdevice_t *dev, struct ifreq *ifr, int cmd);
++
++client_t *acx_l_sta_list_get(wlandevice_t *priv, const u8 *address);
++void acx_l_sta_list_del(wlandevice_t *priv, client_t *clt);
++
++int acx_l_transmit_disassoc(wlandevice_t *priv, client_t *clt);
++void acx_i_timer(unsigned long a);
++int acx_s_complete_scan(wlandevice_t *priv);
++
++static inline wlan_hdr_t*
++acx_get_wlan_hdr(wlandevice_t *priv, const rxbuffer_t *rxbuf)
++{
++      if (!(priv->rx_config_1 & RX_CFG1_INCLUDE_PHY_HDR))
++              return (wlan_hdr_t*)&rxbuf->hdr_a3;
++
++      /* take into account phy header in front of packet */
++      if (IS_ACX111(priv))
++              return (wlan_hdr_t*)((u8*)&rxbuf->hdr_a3 + 8);
++
++      return (wlan_hdr_t*)((u8*)&rxbuf->hdr_a3 + 4);
++}
++
++struct sk_buff *acx_rxbuf_to_ether(struct wlandevice *priv, rxbuffer_t *rxbuf);
++
++void acx_l_power_led(wlandevice_t *priv, int enable);
++
++unsigned int acx_l_clean_tx_desc(wlandevice_t *priv);
++void acx_l_clean_tx_desc_emergency(wlandevice_t *priv);
++
++u8 acx_signal_determine_quality(u8 signal, u8 noise);
++
++void acx_l_process_rxbuf(wlandevice_t *priv, rxbuffer_t *rxbuf);
++void acx_l_process_rx_desc(wlandevice_t *priv);
++
++tx_t* acxpci_l_alloc_tx(wlandevice_t *priv);
++tx_t* acxusb_l_alloc_tx(wlandevice_t *priv);
++static inline tx_t*
++acx_l_alloc_tx(wlandevice_t *priv)
++{
++#if defined(CONFIG_ACX_CFI)
++      return acxpci_l_alloc_tx(priv);
++#else
++      if (IS_PCI(priv))
++              return acxpci_l_alloc_tx(priv);
++      return acxusb_l_alloc_tx(priv);
++#endif
++}
++
++void* acxpci_l_get_txbuf(wlandevice_t *priv, tx_t *tx_opaque);
++void* acxusb_l_get_txbuf(wlandevice_t *priv, tx_t *tx_opaque);
++static inline void*
++acx_l_get_txbuf(wlandevice_t *priv, tx_t *tx_opaque)
++{
++#if defined(CONFIG_ACX_CFI)
++      return acxpci_l_get_txbuf(priv, tx_opaque);
++#else
++      if (IS_PCI(priv))
++              return acxpci_l_get_txbuf(priv, tx_opaque);
++      return acxusb_l_get_txbuf(priv, tx_opaque);
++#endif
++}
++
++void acxpci_l_tx_data(wlandevice_t *priv, tx_t *tx_opaque, int len);
++void acxusb_l_tx_data(wlandevice_t *priv, tx_t *tx_opaque, int len);
++static inline void
++acx_l_tx_data(wlandevice_t *priv, tx_t *tx_opaque, int len)
++{
++#if defined(CONFIG_ACX_CFI)
++      acxpci_l_tx_data(priv, tx_opaque, len);
++#else
++      if (IS_PCI(priv))
++              acxpci_l_tx_data(priv, tx_opaque, len);
++      else
++              acxusb_l_tx_data(priv, tx_opaque, len);
++#endif
++}
++
++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 acx100usb_l_tx_data(wlandevice_t *priv, struct txdesc *desc);
++int acx_s_set_defaults(wlandevice_t *priv);
++void acx_init_mboxes(wlandevice_t *priv);
++
++int acx_l_ether_to_txbuf(wlandevice_t *priv, void *txbuf, const struct sk_buff *skb);
++
++#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, netdevice_t *dev);
++void acx_free_desc_queues(wlandevice_t *priv);
++
++int acx_s_create_hostdesc_queues(wlandevice_t *priv);
++void acx_create_desc_queues(wlandevice_t *priv, u32 tx_queue_start, u32 rx_queue_start);
++
++int acx100_s_init_wep(wlandevice_t *priv);
++int acx100_s_init_packet_templates(wlandevice_t *priv);
++int acx111_s_init_packet_templates(wlandevice_t *priv);
++
++void great_inquisitor(wlandevice_t *priv);
++
++char* acxpci_s_proc_diag_output(char *p, wlandevice_t *priv);
++int acx_proc_eeprom_output(char *p, wlandevice_t *priv);
++void acx_set_interrupt_mask(wlandevice_t *priv);
++int acx100_s_set_tx_level(wlandevice_t *priv, u8 level_dbm);
++
++#if defined(CONFIG_ACX_CFI)
++int __init acxcfi_e_init_module(void);
++#else
++int __init acxpci_e_init_module(void);
++int __init acxusb_e_init_module(void);
++#endif
++
++#if defined(CONFIG_ACX_CFI)
++void __exit acxcfi_e_cleanup_module(void);
++#else
++void __exit acxpci_e_cleanup_module(void);
++void __exit acxusb_e_cleanup_module(void);
++#endif
+diff -Naur linux-2.6.14-omap2/drivers/net/wireless/tiacx/acx.h linux-h6300-omap2-2.6.14.3/drivers/net/wireless/tiacx/acx.h
+--- linux-2.6.14-omap2/drivers/net/wireless/tiacx/acx.h        1970-01-01 02:00:00.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/drivers/net/wireless/tiacx/acx.h        2005-09-28 23:54:23.000000000 +0300
+@@ -0,0 +1,6 @@
++#include "acx_config.h"
++#include "wlan_compat.h"
++#include "wlan_hdr.h"
++#include "wlan_mgmt.h"
++#include "acx_struct.h"
++#include "acx_func.h"
+diff -Naur linux-2.6.14-omap2/drivers/net/wireless/tiacx/acx_struct.h linux-h6300-omap2-2.6.14.3/drivers/net/wireless/tiacx/acx_struct.h
+--- linux-2.6.14-omap2/drivers/net/wireless/tiacx/acx_struct.h 1970-01-01 02:00:00.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/drivers/net/wireless/tiacx/acx_struct.h 2005-10-29 22:02:44.000000000 +0300
+@@ -0,0 +1,1966 @@
++/***********************************************************************
++** 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 wlandevice wlandevice_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 __WLAN_ATTRIB_PACK__
++
++#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) */
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,41)
++#include <linux/workqueue.h>
++/* #define NEWER_KERNELS_ONLY 1 */
++#define USE_WORKER_TASKS
++#define WORK_STRUCT struct work_struct
++#define SCHEDULE_WORK schedule_work
++#define FLUSH_SCHEDULED_WORK flush_scheduled_work
++
++#else
++#include <linux/tqueue.h>
++#define USE_QUEUE_TASKS
++#define WORK_STRUCT struct tq_struct
++#define SCHEDULE_WORK schedule_task
++#define INIT_WORK(work, func, ndev) \
++      do { \
++              (work)->routine = (func); \
++              (work)->data = (ndev); \
++      } while (0)
++#define FLUSH_SCHEDULED_WORK flush_scheduled_tasks
++
++#endif
++
++
++/*============================================================================*
++ * Constants                                                                  *
++ *============================================================================*/
++#define OK    0
++#define NOT_OK        1
++
++/* The supported chip models */
++#define CHIPTYPE_ACX100               1
++#define CHIPTYPE_ACX111               2
++
++#define IS_ACX100(priv)       ((priv)->chip_type == CHIPTYPE_ACX100)
++#define IS_ACX111(priv)       ((priv)->chip_type == CHIPTYPE_ACX111)
++
++/* Supported interfaces */
++#define DEVTYPE_PCI           0
++#define DEVTYPE_USB           1
++
++#if defined(CONFIG_ACX_PCI)
++ #if !defined(CONFIG_ACX_USB)
++  #define IS_PCI(priv)        1
++ #else
++  #define IS_PCI(priv)        ((priv)->dev_type == DEVTYPE_PCI)
++ #endif
++#else
++ #define IS_PCI(priv) 0
++#endif
++
++#if defined(CONFIG_ACX_USB)
++ #if !defined(CONFIG_ACX_PCI)
++  #define IS_USB(priv)        1
++ #else
++  #define IS_USB(priv)        ((priv)->dev_type == DEVTYPE_USB)
++ #endif
++#else
++ #define IS_USB(priv) 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
++
++/* 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 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_TEST                       0x17
++#define ACX1xx_CMD_RADIOINIT          0x18
++#define ACX111_CMD_RADIOCALIB         0x19
++
++/* '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
++*/
++/* BTW, 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
++*/
++#define RX_CNT 32
++#define TX_CNT 32
++
++/* we clean up txdescs when we have N free txdesc: */
++#define TX_START_CLEAN (TX_CNT - (TX_CNT/4))
++#define TX_EMERG_CLEAN 2
++/* we stop queue if we have less than N free txbufs: */
++#define TX_STOP_QUEUE 3
++/* we start queue if we have more than N free txbufs: */
++#define TX_START_QUEUE 6
++
++/***********************************************************************
++** 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);
++DEF_IE(1xx_IE_QUEUE_CONFIG            ,0x0003, 0x1c);
++DEF_IE(100_IE_BLOCK_SIZE              ,0x0004, 0x02);
++DEF_IE(1xx_IE_MEMORY_CONFIG_OPTIONS   ,0x0005, 0x14);
++DEF_IE(1xx_IE_RATE_FALLBACK           ,0x0006, 0x01);
++DEF_IE(100_IE_WEP_OPTIONS             ,0x0007, 0x03);
++DEF_IE(111_IE_RADIO_BAND              ,0x0007, -1);
++DEF_IE(1xx_IE_MEMORY_MAP              ,0x0008, 0x28); /* huh? */
++DEF_IE(100_IE_SSID                    ,0x0008, 0x20); /* huh? */
++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(100_IE_UNKNOWN_0C              ,0x000c, -1);   /* very small implementation in FW150! */
++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);
++DEF_IE(1xx_IE_FIRMWARE_STATISTICS     ,0x0013, 0x9c);
++DEF_IE(1xx_IE_FEATURE_CONFIG          ,0x0015, 0x08);
++DEF_IE(111_IE_KEY_CHOOSE              ,0x0016, 0x04); /* for rekeying. really len=4?? */
++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 */
++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(1xx_IE_DOT11_SHORT_RETRY_LIMIT ,0x1005, 0x01);
++DEF_IE(1xx_IE_DOT11_LONG_RETRY_LIMIT  ,0x1006, 0x01);
++DEF_IE(100_IE_DOT11_WEP_DEFAULT_KEY_WRITE     ,0x1007, 0x20); /* configure default keys */
++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.
++////#ifdef ACX_PCI
++////DEF_IE(1xx_IE_DOT11_CURRENT_ANTENNA       ,0x100b, 0x01);
++////#else
++DEF_IE(1xx_IE_DOT11_CURRENT_ANTENNA   ,0x100b, 0x02);
++////#endif
++DEF_IE(1xx_IE_DOT11_UNKNOWN_100C      ,0x100c, -1);   /* mapped to cfgInvalid in FW150 */
++DEF_IE(1xx_IE_DOT11_TX_POWER_LEVEL    ,0x100d, 0x01);
++////#ifdef ACX_PCI
++////DEF_IE(1xx_IE_DOT11_CURRENT_CCA_MODE      ,0x100e, 0x01);
++////#else
++DEF_IE(1xx_IE_DOT11_CURRENT_CCA_MODE  ,0x100e, 0x02);
++////#endif
++//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 */
++DEF_IE(100_IE_DOT11_UNKNOWN_1011      ,0x1011, -1);   /* mapped to cfgInvalid in FW150 */
++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 IBBS Beacons
++ * 0000 3c00 0000 0000 ESS Beacons
++ * 0000 2700 0000 0000 Probe requests
++ * --vda
++ */
++typedef struct phy_hdr {
++      u8      unknown[4] ACX_PACKED;
++      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 PHY_HDR(rxbuf) ((phy_hdr_t*)&rxbuf->hdr_a3)
++#define RXBUF_BYTES_RCVD(rxbuf) (le16_to_cpu(rxbuf->mac_cnt_rcvd) & 0xfff)
++#define RXBUF_BYTES_USED(rxbuf) \
++              ((le16_to_cpu(rxbuf->mac_cnt_rcvd) & 0xfff) + RXBUF_HDRSIZE)
++/*
++mac_cnt_rcvd:
++    12 bits: length of frame from control field to last byte of FCS
++    4 bits: reserved
++
++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 ACX_PACKED;        /* only 12 bits are len! (0xfff) */
++      u8      mac_cnt_mblks ACX_PACKED;
++      u8      mac_status ACX_PACKED;
++      u8      phy_stat_baseband ACX_PACKED;   /* bit 0x80: used LNA (Low-Noise Amplifier) */
++      u8      phy_plcp_signal ACX_PACKED;
++      u8      phy_level ACX_PACKED;           /* PHY stat */
++      u8      phy_snr ACX_PACKED;             /* PHY stat */
++      u32     time ACX_PACKED;                /* 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 ACX_PACKED;
++      /* maximally sized data part of wlan packet */
++      u8      data_a3[WLAN_A4FR_MAXLEN_WEP_FCS - WLAN_HDR_A3_LEN] ACX_PACKED;
++      /* can add hdr/data_a4 if needed */
++} rxbuffer_t;
++
++
++/*--- Firmware statistics ----------------------------------------------------*/
++typedef struct fw_stats {
++      u32     val0x0 ACX_PACKED;              /* hdr; */
++      u32     tx_desc_of ACX_PACKED;
++      u32     rx_oom ACX_PACKED;
++      u32     rx_hdr_of ACX_PACKED;
++      u32     rx_hdr_use_next ACX_PACKED;
++      u32     rx_dropped_frame ACX_PACKED;
++      u32     rx_frame_ptr_err ACX_PACKED;
++      u32     rx_xfr_hint_trig ACX_PACKED;
++
++      u32     rx_dma_req ACX_PACKED;
++      u32     rx_dma_err ACX_PACKED;
++      u32     tx_dma_req ACX_PACKED;
++      u32     tx_dma_err ACX_PACKED;
++
++      u32     cmd_cplt ACX_PACKED;
++      u32     fiq ACX_PACKED;
++      u32     rx_hdrs ACX_PACKED;
++      u32     rx_cmplt ACX_PACKED;
++      u32     rx_mem_of ACX_PACKED;
++      u32     rx_rdys ACX_PACKED;
++      u32     irqs ACX_PACKED;
++      u32     acx_trans_procs ACX_PACKED;
++      u32     decrypt_done ACX_PACKED;
++      u32     dma_0_done ACX_PACKED;
++      u32     dma_1_done ACX_PACKED;
++      u32     tx_exch_complet ACX_PACKED;
++      u32     commands ACX_PACKED;
++      u32     acx_rx_procs ACX_PACKED;
++      u32     hw_pm_mode_changes ACX_PACKED;
++      u32     host_acks ACX_PACKED;
++      u32     pci_pm ACX_PACKED;
++      u32     acm_wakeups ACX_PACKED;
++
++      u32     wep_key_count ACX_PACKED;
++      u32     wep_default_key_count ACX_PACKED;
++      u32     dot11_def_key_mib ACX_PACKED;
++      u32     wep_key_not_found ACX_PACKED;
++      u32     wep_decrypt_fail ACX_PACKED;
++} fw_stats_t;
++
++/* Firmware version struct */
++
++typedef struct fw_ver {
++      u16     cmd ACX_PACKED;
++      u16     size ACX_PACKED;
++      char    fw_id[20] ACX_PACKED;
++      u32     hw_id ACX_PACKED;
++} fw_ver_t;
++
++#define FW_ID_SIZE 20
++
++
++/*--- 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 -----------------------------------------------------*/
++/* priv->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 {
++      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      used;                   /* misnamed, more like 'status' */
++      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_INIT           (DESC_CTL_HOSTOWN | DESC_CTL_RECLAIM | \
++                               DESC_CTL_AUTODMA | DESC_CTL_FIRSTFRAG)
++#define       DESC_CTL_DONE           (DESC_CTL_ACXDONE | DESC_CTL_HOSTOWN)
++
++#define DESC_CTL_HOSTOWN_STR  "80"
++#define       DESC_CTL_DONE_STR       "C0"
++/* 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 ACX_PACKED;   /* pointer to next txdesc */
++      acx_ptr HostMemPtr ACX_PACKED;                  /* 0x04 */
++      acx_ptr AcxMemPtr ACX_PACKED;                   /* 0x08 */
++      u32     tx_time ACX_PACKED;                     /* 0x0c */
++      u16     total_length ACX_PACKED;                /* 0x10 */
++      u16     Reserved ACX_PACKED;                    /* 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] ACX_PACKED;
++
++      u8      Ctl_8 ACX_PACKED;                       /* 0x24, 8bit value */
++      u8      Ctl2_8 ACX_PACKED;                      /* 0x25, 8bit value */
++      u8      error ACX_PACKED;                       /* 0x26 */
++      u8      ack_failures ACX_PACKED;                /* 0x27 */
++      u8      rts_failures ACX_PACKED;                /* 0x28 */
++      u8      rts_ok ACX_PACKED;                      /* 0x29 */
++      union {
++              struct {
++                      u8      rate ACX_PACKED;        /* 0x2a */
++                      u8      queue_ctrl ACX_PACKED;  /* 0x2b */
++              } r1 ACX_PACKED;
++              struct {
++                      u16     rate111 ACX_PACKED;     /* 0x2a */
++              } r2 ACX_PACKED;
++      } u ACX_PACKED;
++      u32     queue_info ACX_PACKED;                  /* 0x2c (acx100, reserved on acx111) */
++};            /* 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 ACX_PACKED;                   /* 0x00 */
++      acx_ptr HostMemPtr ACX_PACKED;                  /* 0x04 */
++      acx_ptr ACXMemPtr ACX_PACKED;                   /* 0x08 */
++      u32     rx_time ACX_PACKED;                     /* 0x0c */
++      u16     total_length ACX_PACKED;                /* 0x10 */
++      u16     WEP_length ACX_PACKED;                  /* 0x12 */
++      u32     WEP_ofs ACX_PACKED;                     /* 0x14 */
++
++/* the following 16 bytes do not change when acx100 owns the descriptor */
++      u8      driverWorkspace[16] ACX_PACKED;         /* 0x18 */
++
++      u8      Ctl_8 ACX_PACKED;
++      u8      rate ACX_PACKED;
++      u8      error ACX_PACKED;
++      u8      SNR ACX_PACKED;                         /* Signal-to-Noise Ratio */
++      u8      RxLevel ACX_PACKED;
++      u8      queue_ctrl ACX_PACKED;
++      u16     unknown ACX_PACKED;
++      u32     unknown2 ACX_PACKED;
++};            /* size 52 = 0x34 */
++
++#ifdef ACX_PCI
++
++/* 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_HW_SLAVE_REG_ADDR,
++        IO_ACX_HW_SLAVE_REG_DATA,
++        IO_ACX_HW_SLAVE_REG_CTRL,
++
++      IO_ACX_SLV_MEM_ADDR,
++      IO_ACX_SLV_MEM_DATA,
++      IO_ACX_SLV_MEM_CTL,
++      IO_ACX_SLV_END_CTL,
++      IO_ACX_CHIPID,
++
++      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_IN,
++        IO_ACX_GPIO_OUT,
++        IO_ACX_GPIO_PD,
++        IO_ACX_GPIO_CFG,
++
++      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,
++
++      IO_ACX_HI_CTRL,
++      IO_ACX_LPWR_MGR,
++
++      IO_ACX_PCI_ARB_CFG,
++};
++/* ***** 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 ACX_PACKED;                    /* 0x00 [u8 *] */
++      u16     data_offset ACX_PACKED;                 /* 0x04 */
++      u16     reserved ACX_PACKED;                    /* 0x06 */
++      u16     Ctl_16 ACX_PACKED;      /* 16bit value, endianness!! */
++      u16     length ACX_PACKED;                      /* 0x0a */
++      acx_ptr desc_phy_next ACX_PACKED;               /* 0x0c [txhostdesc *] */
++      acx_ptr pNext ACX_PACKED;                       /* 0x10 [txhostdesc *] */
++      u32     Status ACX_PACKED;                      /* 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 ACX_PACKED;                    /* 0x00 [rxbuffer_t *] */
++      u16     data_offset ACX_PACKED;                 /* 0x04 */
++      u16     reserved ACX_PACKED;                    /* 0x06 */
++      u16     Ctl_16 ACX_PACKED;                      /* 0x08; 16bit value, endianness!! */
++      u16     length ACX_PACKED;                      /* 0x0a */
++      acx_ptr desc_phy_next ACX_PACKED;               /* 0x0c [rxhostdesc_t *] */
++      acx_ptr pNext ACX_PACKED;                       /* 0x10 [rxhostdesc_t *] */
++      u32     Status ACX_PACKED;                      /* 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
++
++/* Buffer size for fw upload */
++#define ACX100_USB_RWMEM_MAXLEN       2048
++
++/* Should be sent to the ctrlout endpoint */
++#define ACX100_USB_ENBULKIN   6
++
++/* The number of bulk URBs to use */
++#define ACX100_USB_NUM_BULK_URBS 8
++
++/* 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
++
++/* Used for usb_txbuffer.desc field */
++#define USB_TXBUF_TXDESC      0xA
++/* Used for usb_txbuffer.hostData field */
++#define USB_TXBUF_HD_ISDATA     0x10000
++#define USB_TXBUF_HD_DIRECTED   0x20000
++#define USB_TXBUF_HD_BROADCAST  0x40000
++/* Size of header (everything up to data[]) */
++#define USB_TXBUF_HDRSIZE     14
++typedef struct usb_txbuffer {
++      u16     desc ACX_PACKED;
++      u16     MPDUlen ACX_PACKED;
++      u8      index ACX_PACKED;
++      u8      txRate ACX_PACKED;
++      u32     hostData ACX_PACKED;
++      u8      ctrl1 ACX_PACKED;
++      u8      ctrl2 ACX_PACKED;
++      u16     dataLength ACX_PACKED;
++      /* wlan packet content is placed here: */
++      u8      data[WLAN_A4FR_MAXLEN_WEP_FCS] ACX_PACKED;
++} usb_txbuffer_t;
++
++typedef struct {
++      void    *device;
++      int     number;
++} acx_usb_bulk_context_t;
++
++typedef struct usb_tx {
++      unsigned        busy:1;
++      struct urb      *urb;
++      wlandevice_t    *priv;
++      client_t        *txc;
++      /* actual USB bulk output data block is here: */
++      usb_txbuffer_t  bulkout;
++} usb_tx_t;
++
++#endif /* ACX_USB */
++
++
++/*============================================================================*
++ * Main acx per-device data structure (netdev_priv(dev))                      *
++ *============================================================================*/
++#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 wlandevice {
++      /*** Device chain ***/
++      struct wlandevice       *next;          /* link for list of devices */
++
++      /*** Linux network device ***/
++      struct net_device       *netdev;        /* pointer to linux netdevice */
++      struct net_device       *prev_nd;       /* FIXME: We should not chain via our
++                                               * private struct wlandevice _and_
++                                               * the struct net_device. */
++      /*** 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;
++
++      /*** Locking ***/
++      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
++
++      /*** Hardware identification ***/
++      const char      *chip_name;
++      u8              dev_type;
++      u8              chip_type;
++      u8              form_factor;
++      u8              radio_type;
++      u8              eeprom_version;
++
++      /*** Firmware identification ***/
++      char            firmware_version[FW_ID_SIZE+1];
++      u32             firmware_numver;
++      u32             firmware_id;
++
++      /*** 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 */
++      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) */
++
++      unsigned long   dup_msg_expiry;
++      int             dup_count;
++      int             nondup_count;
++      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;
++      u16             ps_enhanced_transition_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;
++      u32             short_retry;
++      u32             long_retry;
++      u16             msdu_lifetime;
++      u16             listen_interval;        /* given in units of beacon interval */
++      u32             beacon_interval;
++
++      u16             capabilities;
++      u8              capab_short;
++      u8              capab_pbcc;
++      u8              capab_agility;
++      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];
++
++      /*** Card Rx/Tx management ***/
++      u16             rx_config_1;
++      u16             rx_config_2;
++      u16             memblocksize;
++      u32             tx_free;
++
++      /*** Unknown ***/
++      u8              dtim_interval;
++
++/*** 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 ***/
++#ifdef ACX_PCI
++      /* pointers to tx buffers, tx host descriptors (in host memory)
++      ** and tx descrs in device memory */
++      u8              *txbuf_start;
++      txhostdesc_t    *txhostdesc_start;
++      txdesc_t        *txdesc_start;  /* points to PCI-mapped memory */
++      /* same for rx */
++      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; */
++      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    rxbuf_area_size;
++      unsigned int    rxhostdesc_area_size;
++
++      unsigned int    txdesc_size;    /* size per tx descr; ACX111 = ACX100 + 4 */
++      unsigned int    tx_head;        /* current ring buffer pool member index */
++      unsigned int    tx_tail;
++      unsigned int    rx_tail;
++
++      client_t        *txc[TX_CNT];
++
++      u8              need_radio_fw;
++      u8              irqs_active;    /* whether irq sending is activated */
++
++      const u16       *io;            /* points to ACX100 or ACX111 I/O register address set */
++
++#if defined(CONFIG_ACX_CFI)
++      struct device   *dev;
++#else
++      struct pci_dev  *pdev;
++#endif
++
++      unsigned long   membase;
++      unsigned long   membase2;
++      void            *iobase;
++      void            *iobase2;
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 10)
++      /* 2.6.9-rc3-mm2 (2.6.9-bk4, too) introduced a shorter API version,
++         then it made its way into 2.6.10 */
++      u32             pci_state[16];          /* saved PCI state for suspend/resume */
++#endif
++      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;
++
++      /* command interface */
++      void            *cmd_area;      /* points to PCI mapped memory */
++      void            *info_area;     /* points to PCI mapped memory */
++      u16             cmd_type;
++      u16             cmd_status;
++      u16             info_type;
++      u16             info_status;
++#endif
++
++      /*** USB stuff ***/
++#ifdef ACX_USB
++      struct usb_device       *usbdev;
++
++      rxbuffer_t      rxtruncbuf;
++      /* TODO: convert (bulkins,bulkrx_urbs,rxcons) triple into
++      ** struct usb_rx (see struct usb_tx for an example) */
++      rxbuffer_t      bulkins[ACX100_USB_NUM_BULK_URBS];
++      struct urb      *bulkrx_urbs[ACX100_USB_NUM_BULK_URBS];
++      /* Used by rx urb completion handler in order to find
++      ** corresponding priv/index pair */
++      acx_usb_bulk_context_t  rxcons[ACX100_USB_NUM_BULK_URBS];
++      usb_tx_t        usb_tx[ACX100_USB_NUM_BULK_URBS];
++
++      int             bulkinep;       /* bulk-in endpoint */
++      int             bulkoutep;      /* bulk-out endpoint */
++      int             rxtruncsize;
++#endif
++
++};
++
++/* 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
++#define GETSET_ALL            0x80000000L
++
++
++/*============================================================================*
++ * Firmware loading                                                           *
++ *============================================================================*/
++/* Doh, 2.4.x also has CONFIG_FW_LOADER_MODULE
++ * (but doesn't have the new device model yet which we require!)
++ * FIXME: exact version that introduced new device handling? */
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
++#if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE)
++#define USE_FW_LOADER_26 1
++#define USE_FW_LOADER_LEGACY 0
++#else
++#define USE_FW_LOADER_26 0
++#define USE_FW_LOADER_LEGACY 1
++#endif
++#endif
++
++#if USE_FW_LOADER_26
++#include <linux/firmware.h>   /* request_firmware() */
++#include <linux/pci.h>                /* struct pci_device */
++#endif
++
++
++/***********************************************************************
++*/
++typedef struct acx100_ie_memblocksize {
++      u16     type ACX_PACKED;
++      u16     len ACX_PACKED;
++      u16     size ACX_PACKED;
++} acx100_ie_memblocksize_t;
++
++typedef struct acx100_ie_queueconfig {
++      u16     type ACX_PACKED;
++      u16     len ACX_PACKED;
++      u32     AreaSize ACX_PACKED;
++      u32     RxQueueStart ACX_PACKED;
++      u8      QueueOptions ACX_PACKED;
++      u8      NumTxQueues ACX_PACKED;
++      u8      NumRxDesc ACX_PACKED;    /* for USB only */
++      u8      pad1 ACX_PACKED;
++      u32     QueueEnd ACX_PACKED;
++      u32     HostQueueEnd ACX_PACKED; /* QueueEnd2 */
++      u32     TxQueueStart ACX_PACKED;
++      u8      TxQueuePri ACX_PACKED;
++      u8      NumTxDesc ACX_PACKED;
++      u16     pad2 ACX_PACKED;
++} acx100_ie_queueconfig_t;
++
++typedef struct acx111_ie_queueconfig {
++      u16     type ACX_PACKED;
++      u16     len ACX_PACKED;
++      u32     tx_memory_block_address ACX_PACKED;
++      u32     rx_memory_block_address ACX_PACKED;
++      u32     rx1_queue_address ACX_PACKED;
++      u32     reserved1 ACX_PACKED;
++      u32     tx1_queue_address ACX_PACKED;
++      u8      tx1_attributes ACX_PACKED;
++      u16     reserved2 ACX_PACKED;
++      u8      reserved3 ACX_PACKED;
++} acx111_ie_queueconfig_t;
++
++typedef struct acx100_ie_memconfigoption {
++      u16     type ACX_PACKED;
++      u16     len ACX_PACKED;
++      u32     DMA_config ACX_PACKED;
++      acx_ptr pRxHostDesc ACX_PACKED;
++      u32     rx_mem ACX_PACKED;
++      u32     tx_mem ACX_PACKED;
++      u16     RxBlockNum ACX_PACKED;
++      u16     TxBlockNum ACX_PACKED;
++} acx100_ie_memconfigoption_t;
++
++typedef struct acx111_ie_memoryconfig {
++      u16     type ACX_PACKED;
++      u16     len ACX_PACKED;
++      u16     no_of_stations ACX_PACKED;
++      u16     memory_block_size ACX_PACKED;
++      u8      tx_rx_memory_block_allocation ACX_PACKED;
++      u8      count_rx_queues ACX_PACKED;
++      u8      count_tx_queues ACX_PACKED;
++      u8      options ACX_PACKED;
++      u8      fragmentation ACX_PACKED;
++      u16     reserved1 ACX_PACKED;
++      u8      reserved2 ACX_PACKED;
++
++      /* start of rx1 block */
++      u8      rx_queue1_count_descs ACX_PACKED;
++      u8      rx_queue1_reserved1 ACX_PACKED;
++      u8      rx_queue1_type ACX_PACKED; /* must be set to 7 */
++      u8      rx_queue1_prio ACX_PACKED; /* must be set to 0 */
++      acx_ptr rx_queue1_host_rx_start ACX_PACKED;
++      /* end of rx1 block */
++
++      /* start of tx1 block */
++      u8      tx_queue1_count_descs ACX_PACKED;
++      u8      tx_queue1_reserved1 ACX_PACKED;
++      u8      tx_queue1_reserved2 ACX_PACKED;
++      u8      tx_queue1_attributes ACX_PACKED;
++      /* end of tx1 block */
++} acx111_ie_memoryconfig_t;
++
++typedef struct acx_ie_memmap {
++      u16     type ACX_PACKED;
++      u16     len ACX_PACKED;
++      u32     CodeStart ACX_PACKED;
++      u32     CodeEnd ACX_PACKED;
++      u32     WEPCacheStart ACX_PACKED;
++      u32     WEPCacheEnd ACX_PACKED;
++      u32     PacketTemplateStart ACX_PACKED;
++      u32     PacketTemplateEnd ACX_PACKED;
++      u32     QueueStart ACX_PACKED;
++      u32     QueueEnd ACX_PACKED;
++      u32     PoolStart ACX_PACKED;
++      u32     PoolEnd ACX_PACKED;
++} acx_ie_memmap_t;
++
++typedef struct acx111_ie_feature_config {
++      u16     type ACX_PACKED;
++      u16     len ACX_PACKED;
++      u32     feature_options ACX_PACKED;
++      u32     data_flow_options ACX_PACKED;
++} acx111_ie_feature_config_t;
++
++typedef struct acx111_ie_tx_level {
++      u16     type ACX_PACKED;
++      u16     len ACX_PACKED;
++      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_STILL_RCV_BCASTS       0x01
++
++typedef struct acx100_ie_powermgmt {
++      u32     type ACX_PACKED;
++      u32     len ACX_PACKED;
++      u8      wakeup_cfg ACX_PACKED;
++      u8      listen_interval ACX_PACKED; /* for EACH_ITVL: wake up every "beacon units" interval */
++      u8      options ACX_PACKED;
++      u8      hangover_period ACX_PACKED; /* remaining wake time after Tx MPDU w/ PS bit, in values of 1/1024 seconds */
++      u16     enhanced_ps_transition_time ACX_PACKED; /* rem. wake time for Enh. PS */
++} acx100_ie_powermgmt_t;
++
++typedef struct acx111_ie_powermgmt {
++      u32     type ACX_PACKED;
++      u32     len ACX_PACKED;
++      u8      wakeup_cfg ACX_PACKED;
++      u8      listen_interval ACX_PACKED; /* for EACH_ITVL: wake up every "beacon units" interval */
++      u8      options ACX_PACKED;
++      u8      hangover_period ACX_PACKED; /* remaining wake time after Tx MPDU w/ PS bit, in values of 1/1024 seconds */
++      u32     beaconRxTime ACX_PACKED;
++      u32     enhanced_ps_transition_time ACX_PACKED; /* rem. wake time for Enh. PS */
++} acx111_ie_powermgmt_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_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 ACX_PACKED;       /* number of scans to do, 0xffff == continuous */
++      u16     start_chan ACX_PACKED;
++      u16     flags ACX_PACKED;       /* channel list mask; 0x8000 == all channels? */
++      u8      max_rate ACX_PACKED;    /* max. probe rate */
++      u8      options ACX_PACKED;     /* bit mask, see defines above */
++      u16     chan_duration ACX_PACKED;
++      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 ACX_PACKED;               /* number of scans to do */
++      u8      channel_list_select ACX_PACKED; /* 0: scan all channels, 1: from chan_list only */
++      u16     reserved1 ACX_PACKED;
++      u8      reserved2 ACX_PACKED;
++      u8      rate ACX_PACKED;                /* rate for probe requests (if active scan) */
++      u8      options ACX_PACKED;             /* bit mask, see defines above */
++      u16     chan_duration ACX_PACKED;       /* 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 ACX_PACKED;     /* max time to wait for reply on one channel (active scan) */
++                                              /* time to listen on a channel (passive scan) */
++      u8      modulation ACX_PACKED;
++      u8      channel_list[26] ACX_PACKED;    /* bits 7:0 first byte: channels 8:1 */
++                                              /* bits 7:0 second byte: channels 16:9 */
++                                              /* 26 bytes is enough to cover 802.11a */
++} 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 ACX_PACKED;
++      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 ACX_PACKED;
++      u8      tim_eid ACX_PACKED;     /* 00 1 TIM IE ID * */
++      u8      len ACX_PACKED;         /* 01 1 Length * */
++      u8      dtim_cnt ACX_PACKED;    /* 02 1 DTIM Count */
++      u8      dtim_period ACX_PACKED; /* 03 1 DTIM Period */
++      u8      bitmap_ctrl ACX_PACKED; /* 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 acx100_template_probereq {
++      u16     size ACX_PACKED;
++      u16     fc ACX_PACKED;          /* 00 2 fc */
++      u16     dur ACX_PACKED;         /* 02 2 Duration */
++      u8      da[6] ACX_PACKED;       /* 04 6 Destination Address * */
++      u8      sa[6] ACX_PACKED;       /* 0A 6 Source Address * */
++      u8      bssid[6] ACX_PACKED;    /* 10 6 BSSID * */
++      u16     seq ACX_PACKED;         /* 16 2 Sequence Control */
++      u8      timestamp[8] ACX_PACKED;/* 18 8 Timestamp */
++      u16     beacon_interval ACX_PACKED; /* 20 2 Beacon Interval * */
++      u16     cap ACX_PACKED;         /* 22 2 Capability Information * */
++                                      /* 24 n SSID * */
++                                      /* nn n Supported Rates * */
++      u8      variable[0x44 - 2-2-6-6-6-2-8-2-2] ACX_PACKED;
++} acx100_template_probereq_t;
++
++typedef struct acx111_template_probereq {
++      u16     size ACX_PACKED;
++      u16     fc ACX_PACKED;          /* 00 2 fc * */
++      u16     dur ACX_PACKED;         /* 02 2 Duration */
++      u8      da[6] ACX_PACKED;       /* 04 6 Destination Address * */
++      u8      sa[6] ACX_PACKED;       /* 0A 6 Source Address * */
++      u8      bssid[6] ACX_PACKED;    /* 10 6 BSSID * */
++      u16     seq ACX_PACKED;         /* 16 2 Sequence Control */
++                                      /* 18 n SSID * */
++                                      /* nn n Supported Rates * */
++      u8      variable[0x44 - 2-2-6-6-6-2] ACX_PACKED;
++} acx111_template_probereq_t;
++
++typedef struct acx_template_proberesp {
++      u16     size ACX_PACKED;
++      u16     fc ACX_PACKED;          /* 00 2 fc * (bits [15:12] and [10:8] per 802.11 section 7.1.3.1) */
++      u16     dur ACX_PACKED;         /* 02 2 Duration */
++      u8      da[6] ACX_PACKED;       /* 04 6 Destination Address */
++      u8      sa[6] ACX_PACKED;       /* 0A 6 Source Address */
++      u8      bssid[6] ACX_PACKED;    /* 10 6 BSSID */
++      u16     seq ACX_PACKED;         /* 16 2 Sequence Control */
++      u8      timestamp[8] ACX_PACKED;/* 18 8 Timestamp */
++      u16     beacon_interval ACX_PACKED; /* 20 2 Beacon Interval * */
++      u16     cap ACX_PACKED;         /* 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 ACX_PACKED;
++      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] ACX_PACKED;
++      u16     beacon_interval ACX_PACKED;
++      union {
++              struct {
++                      u8      dtim_interval ACX_PACKED;
++                      u8      rates_basic ACX_PACKED;
++                      u8      rates_supported ACX_PACKED;
++              } acx100 ACX_PACKED;
++              struct {
++                      u16     rates_basic ACX_PACKED;
++                      u8      dtim_interval ACX_PACKED;
++              } acx111 ACX_PACKED;
++      } u ACX_PACKED;
++      u8      genfrm_txrate ACX_PACKED;       /* generated frame (bcn, proberesp, RTS, PSpoll) tx rate */
++      u8      genfrm_mod_pre ACX_PACKED;      /* generated frame modulation/preamble:
++                                              ** bit7: PBCC, bit6: OFDM (else CCK/DQPSK/DBPSK)
++                                              ** bit5: short pre */
++      u8      macmode ACX_PACKED;     /* BSS Type, must be one of ACX_MODE_xxx */
++      u8      channel ACX_PACKED;
++      u8      essid_len ACX_PACKED;
++      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 ACX_PACKED;
++      u16     type ACX_PACKED; /* 0x0 int. RAM / 0xffff MAC reg. / 0x81 PHY RAM / 0x82 PHY reg. */
++      u32     len ACX_PACKED;
++      u32     data ACX_PACKED;
++} mem_read_write_t;
++
++typedef struct firmware_image {
++      u32     chksum ACX_PACKED;
++      u32     size ACX_PACKED;
++      u8      data[1] ACX_PACKED; /* the byte array of the actual firmware... */
++} firmware_image_t;
++
++typedef struct acx_cmd_radioinit {
++      u32     offset ACX_PACKED;
++      u32     len ACX_PACKED;
++} acx_cmd_radioinit_t;
++
++typedef struct acx100_ie_wep_options {
++      u16     type ACX_PACKED;
++      u16     len ACX_PACKED;
++      u16     NumKeys ACX_PACKED;     /* max # of keys */
++      u8      WEPOption ACX_PACKED;   /* 0 == decrypt default key only, 1 == override decrypt */
++      u8      Pad ACX_PACKED;         /* used only for acx111 */
++} acx100_ie_wep_options_t;
++
++typedef struct ie_dot11WEPDefaultKey {
++      u16     type ACX_PACKED;
++      u16     len ACX_PACKED;
++      u8      action ACX_PACKED;
++      u8      keySize ACX_PACKED;
++      u8      defaultKeyNum ACX_PACKED;
++      u8      key[29] ACX_PACKED;     /* check this! was Key[19]. */
++} ie_dot11WEPDefaultKey_t;
++
++typedef struct acx111WEPDefaultKey {
++      u8      MacAddr[ETH_ALEN] ACX_PACKED;
++      u16     action ACX_PACKED; /* NOTE: this is a u16, NOT a u8!! */
++      u16     reserved ACX_PACKED;
++      u8      keySize ACX_PACKED;
++      u8      type ACX_PACKED;
++      u8      index ACX_PACKED;
++      u8      defaultKeyNum ACX_PACKED;
++      u8      counter[6] ACX_PACKED;
++      u8      key[32] ACX_PACKED;     /* up to 32 bytes (for TKIP!) */
++} acx111WEPDefaultKey_t;
++
++typedef struct ie_dot11WEPDefaultKeyID {
++      u16     type ACX_PACKED;
++      u16     len ACX_PACKED;
++      u8      KeyID ACX_PACKED;
++} ie_dot11WEPDefaultKeyID_t;
++
++typedef struct acx100_cmd_wep_mgmt {
++      u8      MacAddr[ETH_ALEN] ACX_PACKED;
++      u16     Action ACX_PACKED;
++      u16     KeySize ACX_PACKED;
++      u8      Key[29] ACX_PACKED; /* 29*8 == 232bits == WEP256 */
++} acx100_cmd_wep_mgmt_t;
++
++typedef struct defaultkey {
++      u8      num;
++} defaultkey_t;
++
++typedef struct acx_ie_generic {
++      u16     type ACX_PACKED;
++      u16     len ACX_PACKED;
++      union {
++              /* struct wep wp ACX_PACKED; */
++              /* Association ID IE: just a 16bit value: */
++              u16     aid;
++              /* UNUSED? struct defaultkey dkey ACX_PACKED; */
++              /* generic member for quick implementation of commands */
++              u8      bytes[32] ACX_PACKED;
++      } m ACX_PACKED;
++} acx_ie_generic_t;
++
++/* Config Option structs */
++
++typedef struct co_antennas {
++      u8      type ACX_PACKED;
++      u8      len ACX_PACKED;
++      u8      list[2] ACX_PACKED;
++} co_antennas_t;
++
++typedef struct co_powerlevels {
++      u8      type ACX_PACKED;
++      u8      len ACX_PACKED;
++      u16     list[8] ACX_PACKED;
++} co_powerlevels_t;
++
++typedef struct co_datarates {
++      u8      type ACX_PACKED;
++      u8      len ACX_PACKED;
++      u8      list[8] ACX_PACKED;
++} co_datarates_t;
++
++typedef struct co_domains {
++      u8      type ACX_PACKED;
++      u8      len ACX_PACKED;
++      u8      list[6] ACX_PACKED;
++} co_domains_t;
++
++typedef struct co_product_id {
++      u8      type ACX_PACKED;
++      u8      len ACX_PACKED;
++      u8      list[128] ACX_PACKED;
++} co_product_id_t;
++
++typedef struct co_manuf_id {
++      u8      type ACX_PACKED;
++      u8      len ACX_PACKED;
++      u8      list[128] ACX_PACKED;
++} co_manuf_t;
++
++typedef struct co_fixed {
++      u8      type ACX_PACKED;
++      u8      len ACX_PACKED;
++      char    NVSv[8] ACX_PACKED;
++      u8      MAC[6] ACX_PACKED;
++      u16     probe_delay ACX_PACKED;
++      u32     eof_memory ACX_PACKED;
++      u8      dot11CCAModes ACX_PACKED;
++      u8      dot11Diversity ACX_PACKED;
++      u8      dot11ShortPreambleOption ACX_PACKED;
++      u8      dot11PBCCOption ACX_PACKED;
++      u8      dot11ChannelAgility ACX_PACKED;
++      u8      dot11PhyType ACX_PACKED;
++/*    u8      dot11TempType ACX_PACKED;
++      u8      num_var ACX_PACKED;           seems to be erased     */
++} co_fixed_t;
++
++
++typedef struct acx111_ie_configoption {
++      co_fixed_t              configoption_fixed ACX_PACKED;
++      co_antennas_t           antennas ACX_PACKED;
++      co_powerlevels_t        power_levels ACX_PACKED;
++      co_datarates_t          data_rates ACX_PACKED;
++      co_domains_t            domains ACX_PACKED;
++      co_product_id_t         product_id ACX_PACKED;
++      co_manuf_t              manufacturer ACX_PACKED;
++} acx111_ie_configoption_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);
++}
++
++
++/*============================================================================*
++ * Global data                                                                *
++ *============================================================================*/
++extern const u8 bitpos2ratebyte[];
++extern const u8 bitpos2rate100[];
++
++extern const u8 reg_domain_ids[];
++extern const u8 reg_domain_ids_len;
++
++extern const struct iw_handler_def acx_ioctl_handler_def;
+diff -Naur linux-2.6.14-omap2/drivers/net/wireless/tiacx/cfi.c linux-h6300-omap2-2.6.14.3/drivers/net/wireless/tiacx/cfi.c
+--- linux-2.6.14-omap2/drivers/net/wireless/tiacx/cfi.c        1970-01-01 02:00:00.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/drivers/net/wireless/tiacx/cfi.c        2005-10-29 22:02:44.000000000 +0300
+@@ -0,0 +1,4779 @@
++/***********************************************************************
++** 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/config.h>
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
++#include <linux/moduleparam.h>
++#endif
++#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>
++#if WIRELESS_EXT >= 13
++#include <net/iw_handler.h>
++#endif
++#include <linux/device.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/ioport.h>
++#include <linux/pm.h>
++#include <linux/vmalloc.h>
++
++#include <asm/hardware.h>
++#include <asm/mach-types.h>
++#include <asm/sizes.h>
++#include <asm/arch/tc.h>
++
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/arch/gpio.h>
++#include <asm/arch/pca9535.h>
++
++#include "acx.h"
++
++#define CARDNAME "tnetw1100b"
++
++/*================================================================*/
++/* Local Constants */
++#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      0x280
++
++#define CARD_EEPROM_ID_SIZE 6
++#define MAX_IRQLOOPS_PER_JIFFY  (20000/HZ) /* a la orinoco.c */
++
++
++/***********************************************************************
++*/
++static void acx_l_disable_irq(wlandevice_t *priv);
++static void acx_l_enable_irq(wlandevice_t *priv);
++static int acx_drv_probe(struct device *dev);
++static int acx_remove(struct device *dev);
++
++static inline void test(wlandevice_t *priv);
++
++#ifdef CONFIG_PM
++static int acx_suspend(struct device *dev, pm_message_t state, u32 level);
++static int acx_resume(struct device *dev, u32 level);
++#endif
++
++static void acx_i_tx_timeout(netdevice_t *dev);
++static struct net_device_stats *acx_e_get_stats(netdevice_t *dev);
++static struct iw_statistics *acx_e_get_wireless_stats(netdevice_t *dev);
++
++static irqreturn_t acx_i_interrupt(int irq, void *dev_id, struct pt_regs *regs);
++static void acx_i_set_multicast_list(netdevice_t *dev);
++
++static int acx_e_open(netdevice_t *dev);
++static int acx_e_close(netdevice_t *dev);
++static void acx_s_up(netdevice_t *dev);
++static void acx_s_down(netdevice_t *dev);
++
++
++/***********************************************************************
++** Register access
++*/
++
++/* Pick one */
++/* #define INLINE_IO static */
++#define INLINE_IO static inline
++
++INLINE_IO u32
++acx_read_reg32(wlandevice_t *priv, unsigned int offset)
++{
++#if ACX_IO_WIDTH == 32
++      return readl((u8 *)priv->iobase + priv->io[offset]);
++#else
++      return readw((u8 *)priv->iobase + priv->io[offset])
++          + (readw((u8 *)priv->iobase + priv->io[offset] + 2) << 16);
++#endif
++}
++
++INLINE_IO u16
++acx_read_reg16(wlandevice_t *priv, unsigned int offset)
++{
++      return readw((u8 *)priv->iobase + priv->io[offset]);
++}
++
++INLINE_IO u8
++acx_read_reg8(wlandevice_t *priv, unsigned int offset)
++{
++      return readb((u8 *)priv->iobase + priv->io[offset]);
++}
++
++INLINE_IO void
++acx_write_reg32(wlandevice_t *priv, unsigned int offset, u32 val)
++{
++#if ACX_IO_WIDTH == 32
++      writel(val, (u8 *)priv->iobase + priv->io[offset]);
++#else
++      writew(val & 0xffff, (u8 *)priv->iobase + priv->io[offset]);
++      writew(val >> 16, (u8 *)priv->iobase + priv->io[offset] + 2);
++#endif
++}
++
++INLINE_IO void
++acx_write_reg16(wlandevice_t *priv, unsigned int offset, u16 val)
++{
++      writew(val, (u8 *)priv->iobase + priv->io[offset]);
++}
++
++INLINE_IO void
++acx_write_reg8(wlandevice_t *priv, unsigned int offset, u8 val)
++{
++      writeb(val, (u8 *)priv->iobase + priv->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
++acx_write_flush(wlandevice_t *priv)
++{
++      /* readb(priv->iobase + priv->io[IO_ACX_INFO_MAILBOX_OFFS]); */
++      /* faster version (accesses the first register, IO_ACX_SOFT_RESET,
++       * which should also be safe): */
++      readb(priv->iobase);
++}
++
++
++INLINE_IO void acx_mailbox_fill(wlandevice_t *priv, unsigned int offset, unsigned char val, int len){
++        unsigned int  addr  = offset;
++        unsigned int  buff  = 0;
++
++      // Fill the buffer
++      memset((void *) &buff, val, len);
++
++      acx_write_reg32(priv, IO_ACX_SLV_END_CTL, 0);
++        acx_write_reg32(priv, IO_ACX_SLV_MEM_CTL, 0x00010000);
++        acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR, addr);
++
++        while(len >= 4){
++              // Write data
++                acx_write_reg32(priv, IO_ACX_SLV_MEM_DATA,buff);
++                acx_write_flush(priv);
++
++                addr += 4;
++                len  -= 4;
++        }
++
++        if(len > 0) {
++                val = 0;
++                memset((void *) &buff, val , len);
++
++                acx_write_reg32(priv, IO_ACX_SLV_MEM_DATA,buff);
++                acx_write_flush(priv);
++        }
++}
++
++
++INLINE_IO void acx_mailbox_write(wlandevice_t *priv, unsigned int offset, void *cmd, int len){
++      unsigned char *buff = (unsigned char *) cmd;
++        unsigned int  addr  = offset;
++      unsigned int  val   = 0;
++
++      if(!cmd){
++              return;
++      }
++
++      acx_write_reg32(priv, IO_ACX_SLV_END_CTL, 0);
++        acx_write_reg32(priv, IO_ACX_SLV_MEM_CTL, 0x00010000);
++        acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR, addr);
++
++        while(len >= 4){
++                acx_write_reg32(priv, IO_ACX_SLV_MEM_DATA,*((unsigned int *) buff));
++              acx_write_flush(priv);
++
++                buff += 4;
++                addr += 4;
++              len  -= 4;
++        }
++
++      if(len > 0) {
++              val = 0;
++              memcpy((void *) &val, (void *) buff, len);
++
++              acx_write_reg32(priv, IO_ACX_SLV_MEM_DATA,val);
++              acx_write_flush(priv);
++      }
++}
++
++INLINE_IO void acx_mailbox_read(wlandevice_t *priv, unsigned int offset, void *data, int len){
++        unsigned char *buff = (unsigned char *) data;
++        unsigned int  addr  = offset;
++      unsigned int  value = 0;
++
++      if(!data){
++              return;
++      }
++
++      acx_write_reg32(priv, IO_ACX_SLV_END_CTL, 0);
++        acx_write_reg32(priv, IO_ACX_SLV_MEM_CTL, 0x00010000);
++      acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR, addr);       
++
++        while(len >= 4){
++              *buff = 0;
++                *((unsigned int *) buff) = acx_read_reg32(priv, IO_ACX_SLV_MEM_DATA);
++
++                buff += 4;
++                addr += 4;
++              len  -= 4;
++        }
++
++      if(len > 0){
++              value = acx_read_reg32(priv, IO_ACX_SLV_MEM_DATA);
++              memcpy((void *) buff, (void *) &value, len);
++      }
++}
++
++/***********************************************************************
++*/
++static const char name_acx100[] = "ACX100";
++static const char name_tnetw1100a[] = "TNETW1100A";
++static const char name_tnetw1100b[] = "TNETW1100B";
++
++static const char name_acx111[] = "ACX111";
++static const char name_tnetw1130[] = "TNETW1130";
++
++struct device_driver acx_driver = {
++        .name           = CARDNAME,
++        .bus            = &platform_bus_type,
++        .probe          = acx_drv_probe,
++        .remove         = acx_remove,
++#ifdef CONFIG_PM
++        .suspend        = acx_suspend,
++        .resume         = acx_resume
++#endif
++};
++
++typedef struct acx_device {
++      netdevice_t *newest;
++} acx_device_t;
++
++/* if this driver was only about PCI devices, then we probably wouldn't
++ * need this linked list.
++ * But if we want to register ALL kinds of devices in one global list,
++ * then we need it and need to maintain it properly. */
++static struct acx_device root_acx_dev = {
++      .newest         = NULL,
++};
++DECLARE_MUTEX(root_acx_dev_sem);
++
++
++/***********************************************************************
++*/
++static inline txdesc_t*
++get_txdesc(wlandevice_t* priv, int index)
++{
++      return (txdesc_t*) (((u8*)priv->txdesc_start) + index * priv->txdesc_size);
++}
++
++static inline txdesc_t*
++move_txdesc(wlandevice_t* priv, txdesc_t* txdesc, int inc)
++{
++      return (txdesc_t*) (((u8*)txdesc) + inc * priv->txdesc_size);
++}
++
++static txhostdesc_t*
++acx_get_txhostdesc(wlandevice_t* priv, txdesc_t* txdesc)
++{
++      int index = (u8*)txdesc - (u8*)priv->txdesc_start;
++      if (ACX_DEBUG && (index % priv->txdesc_size)) {
++              printk("bad txdesc ptr %p\n", txdesc);
++              return NULL;
++      }
++      index /= priv->txdesc_size;
++      if (ACX_DEBUG && (index >= TX_CNT)) {
++              printk("bad txdesc ptr %p\n", txdesc);
++              return NULL;
++      }
++      return &priv->txhostdesc_start[index*2];
++}
++
++static client_t*
++acx_get_txc(wlandevice_t* priv, txdesc_t* txdesc)
++{
++      int index = (u8*)txdesc - (u8*)priv->txdesc_start;
++      if (ACX_DEBUG && (index % priv->txdesc_size)) {
++              printk("bad txdesc ptr %p\n", txdesc);
++              return NULL;
++      }
++      index /= priv->txdesc_size;
++      if (ACX_DEBUG && (index >= TX_CNT)) {
++              printk("bad txdesc ptr %p\n", txdesc);
++              return NULL;
++      }
++      return priv->txc[index];
++}
++
++static void
++acx_put_txc(wlandevice_t* priv, txdesc_t* txdesc, client_t* c)
++{
++      int index = (u8*)txdesc - (u8*)priv->txdesc_start;
++      if (ACX_DEBUG && (index % priv->txdesc_size)) {
++              printk("bad txdesc ptr %p\n", txdesc);
++              return;
++      }
++      index /= priv->txdesc_size;
++      if (ACX_DEBUG && (index >= TX_CNT)) {
++              printk("bad txdesc ptr %p\n", txdesc);
++              return;
++      }
++      priv->txc[index] = c;
++}
++
++/***********************************************************************
++** EEPROM and PHY read/write helpers
++*/
++/***********************************************************************
++** acx_read_eeprom_offset
++**
++** Function called to read an octet in the EEPROM.
++**
++** This function is used by acx_probe_pci to check if the
++** connected card is a legal one or not.
++**
++** Arguments:
++**    priv            ptr to wlandevice structure
++**    addr            address to read in the EEPROM
++**    charbuf         ptr to a char. This is where the read octet
++**                    will be stored
++**
++** Returns:
++**    zero (0)        - failed
++**    one (1)         - success
++**
++** NOT ADAPTED FOR ACX111!!
++*/
++int
++acx_read_eeprom_offset(wlandevice_t *priv, u32 addr, u8 *charbuf)
++{
++      int result = NOT_OK;
++      int count;
++
++      acx_write_reg32(priv, IO_ACX_EEPROM_CFG, 0);
++      acx_write_reg32(priv, IO_ACX_EEPROM_ADDR, addr);
++      acx_write_flush(priv);
++      acx_write_reg32(priv, IO_ACX_EEPROM_CTL, 2);
++
++      count = 0xffff;
++      while (acx_read_reg16(priv, 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",
++                                                      priv->netdev->name);
++                      goto fail;
++              }
++      }
++
++      *charbuf = acx_read_reg8(priv, IO_ACX_EEPROM_DATA);
++      acxlog(L_DEBUG, "EEPROM at 0x%04X = 0x%02X\n", addr, *charbuf);
++      result = OK;
++
++fail:
++      return result;
++}
++
++
++/***********************************************************************
++** Dummy EEPROM read? why?!
++*/
++static int
++acx_read_eeprom_area(wlandevice_t *priv)
++{
++      int offs;
++      u8 tmp[0x3b];
++
++      for (offs = 0x8c; offs < 0xb9; offs++) {
++              acx_read_eeprom_offset(priv, offs, &tmp[offs - 0x8c]);
++      }
++      return OK;
++}
++
++
++/***********************************************************************
++** 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
++acx_s_write_eeprom_offset(wlandevice_t *priv, 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 = acx_read_reg16(priv, IO_ACX_GPIO_OE);
++      acx_write_reg16(priv, IO_ACX_GPIO_OE, gpio_orig & ~1);
++      acx_write_flush(priv);
++
++      /* ok, now start writing the data out */
++      for (i = 0; i < len; i++) {
++              acx_write_reg32(priv, IO_ACX_EEPROM_CFG, 0);
++              acx_write_reg32(priv, IO_ACX_EEPROM_ADDR, addr + i);
++              acx_write_reg32(priv, IO_ACX_EEPROM_DATA, *(charbuf + i));
++              acx_write_flush(priv);
++              acx_write_reg32(priv, IO_ACX_EEPROM_CTL, 1);
++
++              while (acx_read_reg16(priv, IO_ACX_EEPROM_CTL)) {
++                      if (unlikely(++count > 0xffff)) {
++                              printk("WARNING, DANGER!!! "
++                                      "Timeout waiting for EEPROM write\n");
++                              goto end;
++                      }
++              }
++      }
++
++      /* disable EEPROM writing */
++      acx_write_reg16(priv, IO_ACX_GPIO_OE, gpio_orig);
++      acx_write_flush(priv);
++
++      /* now start a verification run */
++      count = 0xffff;
++      for (i = 0; i < len; i++) {
++              acx_write_reg32(priv, IO_ACX_EEPROM_CFG, 0);
++              acx_write_reg32(priv, IO_ACX_EEPROM_ADDR, addr + i);
++              acx_write_flush(priv);
++              acx_write_reg32(priv, IO_ACX_EEPROM_CTL, 2);
++
++              while (acx_read_reg16(priv, IO_ACX_EEPROM_CTL)) {
++                      if (unlikely(!--count)) {
++                              printk("timeout waiting for EEPROM read\n");
++                              goto end;
++                      }
++              }
++
++              data_verify[i] = acx_read_reg16(priv, 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
++** (acx_write_reg32(priv, IO_ACX_ENABLE, 0b000000xx)) kills traffic
++*/
++int
++acxpci_s_read_phy_reg(wlandevice_t *priv, u32 reg, u8 *charbuf)
++{
++      int result = NOT_OK;
++      int count;
++
++      FN_ENTER;
++
++      acx_write_reg32(priv, IO_ACX_PHY_ADDR, reg);
++      acx_write_flush(priv);
++      acx_write_reg32(priv, IO_ACX_PHY_CTL, 2);
++
++      count = 0xffff;
++      while (acx_read_reg32(priv, 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",
++                                                      priv->netdev->name);
++                      *charbuf = 0;
++                      goto fail;
++              }
++      }
++
++      acxlog(L_DEBUG, "count was %u\n", count);
++      *charbuf = acx_read_reg8(priv, IO_ACX_PHY_DATA);
++
++      acxlog(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(wlandevice_t *priv, u32 reg, u8 value)
++{
++      FN_ENTER;
++
++      /* FIXME: we didn't use 32bit access here since mprusko said that
++       * it results in distorted sensitivity on his card (huh!?!?
++       * doesn't happen with my setup...)
++       * But with the access reordering and flushing it
++       * shouldn't happen any more...
++       * FIXME: which radio is in the problematic card? My working one
++       * is 0x11 */
++      acx_write_reg32(priv, IO_ACX_PHY_DATA, value);
++      acx_write_reg32(priv, IO_ACX_PHY_ADDR, reg);
++      acx_write_flush(priv);
++      acx_write_reg32(priv, IO_ACX_PHY_CTL, 1);
++      acx_write_flush(priv);
++      acxlog(L_DEBUG, "radio PHY write 0x%02X at 0x%04X\n", value, reg);
++
++      FN_EXIT1(OK);
++      return OK;
++}
++
++
++#define NO_AUTO_INCREMENT     1
++
++/***********************************************************************
++** acx_s_write_fw
++**
++** Write the firmware image into the card.
++**
++** Arguments:
++**    priv            wlan device structure
++**    apfw_image      firmware image.
++**
++** Returns:
++**    1       firmware image corrupted
++**    0       success
++*/
++static int
++acx_s_write_fw(wlandevice_t *priv, const firmware_image_t *apfw_image, u32 offset)
++{
++      int len, size;
++      u32 sum, v32;
++      /* we skip the first four bytes which contain the control sum */
++      const u8 *image = (u8*)apfw_image + 4;
++
++      /* start the image checksum by adding the image size value */
++      sum = image[0]+image[1]+image[2]+image[3];
++      image += 4;
++
++      acx_write_reg32(priv, IO_ACX_SLV_END_CTL, 0);
++
++#if NO_AUTO_INCREMENT
++      acxlog(L_INIT, "not using auto increment for firmware loading\n");
++      acx_write_reg32(priv, IO_ACX_SLV_MEM_CTL, 0); /* use basic mode */
++#else
++      acx_write_reg32(priv, IO_ACX_SLV_MEM_CTL, 1); /* use autoincrement mode */
++      acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR, offset); /* configure start address */
++      acx_write_flush(priv);
++#endif
++
++      len = 0;
++      size = le32_to_cpu(apfw_image->size) & (~3);
++
++      while (likely(len < size)) {
++              v32 = be32_to_cpu(*(u32*)image);
++              sum += image[0]+image[1]+image[2]+image[3];
++              image += 4;
++              len += 4;
++
++#if NO_AUTO_INCREMENT
++              acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR, offset + len - 4);
++              acx_write_flush(priv);
++#endif
++              acx_write_reg32(priv, IO_ACX_SLV_MEM_DATA, v32);
++      }
++
++      acxlog(L_DEBUG, "%s: firmware written\n", __func__);
++
++      /* compare our checksum with the stored image checksum */
++      return (sum != le32_to_cpu(apfw_image->chksum));
++}
++
++
++/***********************************************************************
++** acx_s_validate_fw
++**
++** Compare the firmware image given with
++** the firmware image written into the card.
++**
++** Arguments:
++**    priv            wlan device structure
++**   apfw_image  firmware image.
++**
++** Returns:
++**    NOT_OK  firmware image corrupted or not correctly written
++**    OK      success
++*/
++static int
++acx_s_validate_fw(wlandevice_t *priv, const firmware_image_t *apfw_image,
++                              u32 offset)
++{
++      u32 v32, w32, sum;
++      int len, size;
++      int result = OK;
++      /* we skip the first four bytes which contain the control sum */
++      const u8 *image = (u8*)apfw_image + 4;
++
++      /* start the image checksum by adding the image size value */
++      sum = image[0]+image[1]+image[2]+image[3];
++      image += 4;
++
++      acx_write_reg32(priv, IO_ACX_SLV_END_CTL, 0);
++
++#if NO_AUTO_INCREMENT
++      acx_write_reg32(priv, IO_ACX_SLV_MEM_CTL, 0); /* use basic mode */
++#else
++      acx_write_reg32(priv, IO_ACX_SLV_MEM_CTL, 1); /* use autoincrement mode */
++      acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR, offset); /* configure start address */
++#endif
++
++      len = 0;
++      size = le32_to_cpu(apfw_image->size) & (~3);
++
++      while (likely(len < size)) {
++              v32 = be32_to_cpu(*(u32*)image);
++              image += 4;
++              len += 4;
++
++#if NO_AUTO_INCREMENT
++              acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR, offset + len - 4);
++#endif
++              w32 = acx_read_reg32(priv, 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(apfw_image->chksum)) {
++                      printk("acx: FATAL: firmware upload: "
++                              "checksums don't match!\n");
++                      result = NOT_OK;
++              }
++      }
++
++      return result;
++}
++
++
++/***********************************************************************
++** acx_s_upload_fw
++**
++** Arguments:
++**    wlandevice: private device that contains card device
++** Returns:
++**    NOT_OK: failed
++**    OK: success
++** Call context:
++**    acx_reset_dev
++*/
++static int
++acx_s_upload_fw(wlandevice_t *priv)
++{
++      firmware_image_t *apfw_image = NULL;
++      int res = NOT_OK;
++      int try;
++      u32 size;
++      char filename[sizeof("tiacx1NNcNN")];
++
++      FN_ENTER;
++
++      /* Try combined, then main image */
++      priv->need_radio_fw = 0;
++      sprintf(filename, "tiacx1%02dc%02X",
++              IS_ACX111(priv)*11, priv->radio_type);
++
++      apfw_image = acx_s_read_fw(priv->dev, filename, &size);
++      if (!apfw_image) {
++              priv->need_radio_fw = 1;
++              filename[sizeof("tiacx1NN")-1] = '\0';
++              apfw_image = acx_s_read_fw(priv->dev, filename, &size);
++              if (!apfw_image) {
++                      FN_EXIT1(NOT_OK);
++                      return NOT_OK;
++              }
++      }
++
++      for (try = 1; try <= 5; try++) {
++              res = acx_s_write_fw(priv, apfw_image, 0);
++              acxlog(L_DEBUG|L_INIT, "acx_write_fw (main/combined):%d\n", res);
++              if (OK == res) {
++                      res = acx_s_validate_fw(priv, apfw_image, 0);
++                      acxlog(L_DEBUG|L_INIT, "acx_validate_fw "
++                                      "(main/combined):%d\n", res);
++              }
++
++              if (OK == res) {
++                      SET_BIT(priv->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((void *) apfw_image);
++
++      FN_EXIT1(res);
++      return res;
++}
++
++
++/***********************************************************************
++** acx_s_upload_radio
++**
++** Uploads the appropriate radio module firmware
++** into the card.
++*/
++int
++acx_s_upload_radio(wlandevice_t *priv)
++{
++      acx_ie_memmap_t mm;
++      firmware_image_t *radio_image = NULL;
++      acx_cmd_radioinit_t radioinit;
++      int res = NOT_OK;
++      int try;
++      u32 offset;
++      u32 size;
++      char filename[sizeof("tiacx1NNrNN")];
++
++      if (!priv->need_radio_fw) return OK;
++
++      FN_ENTER;
++
++      acx_s_interrogate(priv, &mm, ACX1xx_IE_MEMORY_MAP);
++      offset = le32_to_cpu(mm.CodeEnd);
++
++      sprintf(filename, "tiacx1%02dr%02X",
++              IS_ACX111(priv)*11,
++              priv->radio_type);
++      radio_image = acx_s_read_fw(priv->dev, filename, &size);
++      if (!radio_image) {
++              printk("acx: can't load radio module '%s'\n", filename);
++              goto fail;
++      }
++
++      acx_s_issue_cmd(priv, ACX1xx_CMD_SLEEP, NULL, 0);
++
++      for (try = 1; try <= 5; try++) {
++              res = acx_s_write_fw(priv, radio_image, offset);
++              acxlog(L_DEBUG|L_INIT, "acx_write_fw (radio): %d\n", res);
++              if (OK == res) {
++                      res = acx_s_validate_fw(priv, radio_image, offset);
++                      acxlog(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(priv, 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(priv, ACX1xx_CMD_RADIOINIT,
++              &radioinit, sizeof(radioinit), CMD_TIMEOUT_MS(1000));
++
++      res = acx_s_interrogate(priv, &mm, ACX1xx_IE_MEMORY_MAP);
++fail:
++      FN_EXIT1(res);
++      return res;
++}
++
++void write_reg(wlandevice_t *priv, int reg, u32 value){
++        acx_write_reg32(priv,IO_ACX_HW_SLAVE_REG_ADDR,priv->io[reg]);
++        acx_write_reg16(priv,IO_ACX_HW_SLAVE_REG_DATA,value);
++}
++
++u32 read_reg(wlandevice_t *priv, int reg){
++      u32 value;
++
++        acx_write_reg32(priv,IO_ACX_HW_SLAVE_REG_ADDR,reg);
++        value = acx_read_reg32(priv,IO_ACX_HW_SLAVE_REG_DATA);
++
++      return value;
++}
++
++
++/***********************************************************************
++** acx_l_reset_mac
++**
++** Arguments:
++**    wlandevice: private device that contains card device
++** Side effects:
++**    MAC will be reset
++** Call context:
++**    acx_reset_dev
++** Comment:
++**    resets onboard acx100 MAC
++**
++** Requires lock to be taken
++*/
++static void
++acx_l_reset_mac(wlandevice_t *priv)
++{
++      u16 temp;
++
++      FN_ENTER;
++
++      /* Pocket PC driver setting this register
++       * with 2.
++       */
++      acx_write_reg16(priv,IO_ACX_PCI_ARB_CFG,0x2);
++
++      msleep(300);
++      
++      /* halt eCPU */
++      acxlog(L_DEBUG, "%s: Halt eCPU ...\n", __func__);
++      temp = acx_read_reg16(priv, IO_ACX_ECPU_CTRL) | 0x1;
++      acx_write_reg16(priv, IO_ACX_ECPU_CTRL, temp);
++      acx_write_flush(priv);
++
++      test(priv);
++
++      /* now do soft reset of eCPU */
++      temp = acx_read_reg16(priv, IO_ACX_SOFT_RESET) | 0x1;
++      acxlog(L_DEBUG, "%s: enable soft reset...\n", __func__);
++      acx_write_reg16(priv, IO_ACX_SOFT_RESET, temp);
++      acx_write_flush(priv);
++
++      test(priv);
++
++      /* now reset bit again */
++      acxlog(L_DEBUG, "%s: disable soft reset and go to init mode...\n", __func__);
++      /* deassert eCPU reset */
++      acx_write_reg16(priv, IO_ACX_SOFT_RESET, temp & ~0x1);
++
++      /* now start a burst read from initial flash EEPROM */
++      temp = acx_read_reg16(priv, IO_ACX_EE_START) | 0x1;
++      acx_write_reg16(priv, IO_ACX_EE_START, temp);
++      acx_write_flush(priv);
++      
++      test(priv);
++
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++** acx_s_verify_init
++*/
++static int
++acx_s_verify_init(wlandevice_t *priv)
++{
++      int result = NOT_OK;
++      int timer;
++
++      FN_ENTER;
++
++      for (timer = 40; timer > 0; timer--) {
++              u16 irqstat = acx_read_reg16(priv, IO_ACX_IRQ_STATUS_NON_DES);
++              if (irqstat & HOST_INT_FCS_THRESHOLD) {
++                      result = OK;
++                      acx_write_reg16(priv, IO_ACX_IRQ_ACK, HOST_INT_FCS_THRESHOLD);
++                      break;
++              }
++              /* HZ / 50 resulted in 24 schedules for ACX100 on my machine,
++               * so better schedule away longer for greater efficiency,
++               * decrease loop count */
++              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
++*/
++
++/***********************************************************************
++** acx_read_info_status
++*/
++/* Info mailbox format:
++2 bytes: type
++2 bytes: status
++more bytes may follow
++    docs 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 is no message 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
++acx_read_info_status(wlandevice_t *priv)
++{
++      u32 value;
++
++      acx_write_reg32(priv, IO_ACX_SLV_END_CTL, 0x0);
++      acx_write_reg32(priv, IO_ACX_SLV_MEM_CTL, 0x1);
++
++      acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR,
++              acx_read_reg32(priv, IO_ACX_INFO_MAILBOX_OFFS));
++
++      /* make sure we only read the data once all cfg registers are written: */
++      acx_write_flush(priv);
++      value = acx_read_reg32(priv, IO_ACX_SLV_MEM_DATA);
++
++      priv->info_type = (u16)value;
++      priv->info_status = (value >> 16);
++
++      /* inform hw that we have read this info message */
++      acx_write_reg32(priv, IO_ACX_SLV_MEM_DATA, priv->info_type | 0x00010000);
++      acx_write_flush(priv);
++      /* now bother hw to notice it: */
++      acx_write_reg16(priv, IO_ACX_INT_TRIG, INT_TRIG_INFOACK);
++      acx_write_flush(priv);
++
++      acxlog(L_CTL, "info_type 0x%04X, info_status 0x%04X\n",
++                      priv->info_type, priv->info_status);
++}
++
++
++/***********************************************************************
++** acx_write_cmd_type_or_status
++*/
++static void
++acx_write_cmd_type_or_status(wlandevice_t *priv, u32 val)
++{
++      acx_write_reg32(priv, IO_ACX_SLV_END_CTL, 0x0);
++      acx_write_reg32(priv, IO_ACX_SLV_MEM_CTL, 0x1); /* FIXME: why auto increment?? */
++
++      acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR,
++              acx_read_reg32(priv, IO_ACX_CMD_MAILBOX_OFFS));
++
++      /* make sure we only write the data once all config registers are written */
++      acx_write_flush(priv);
++      acx_write_reg32(priv, IO_ACX_SLV_MEM_DATA, val);
++      acx_write_flush(priv);
++}
++static inline void
++acx_write_cmd_type(wlandevice_t *priv, u32 val)
++{
++      acx_write_cmd_type_or_status(priv, val);
++}
++static inline void
++acx_write_cmd_status(wlandevice_t *priv, u32 val)
++{
++      acx_write_cmd_type_or_status(priv, val<<16);
++}
++
++
++/***********************************************************************
++** acx_read_cmd_status
++*/
++static void
++acx_read_cmd_status(wlandevice_t *priv)
++{
++      u32 value;
++
++      acx_write_reg32(priv, IO_ACX_SLV_END_CTL, 0x0);
++      acx_write_reg32(priv, IO_ACX_SLV_MEM_CTL, 0x1); /* FIXME: why auto increment?? */
++
++      acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR,
++              acx_read_reg32(priv, IO_ACX_CMD_MAILBOX_OFFS));
++
++      /* make sure we only read the data once all config registers are written */
++      acx_write_flush(priv);
++      value = acx_read_reg32(priv, IO_ACX_SLV_MEM_DATA);
++
++      priv->cmd_type = (u16)value;
++      priv->cmd_status = (value >> 16);
++
++      acxlog(L_CTL, "cmd_type 0x%04X, cmd_status 0x%04X [%s]\n",
++              priv->cmd_type, priv->cmd_status,
++              acx_cmd_status_str(priv->cmd_status));
++}
++
++/***********************************************************************
++** acx_s_reset_dev
++**
++** Arguments:
++**    netdevice that contains the wlandevice priv variable
++** Returns:
++**    NOT_OK on fail
++**    OK on success
++** Side effects:
++**    device is hard reset
++** Call context:
++**    acx_probe_pci
++** Comment:
++**    This resets the acx100 device using low level hardware calls
++**    as well as uploads and verifies the firmware to the card
++*/
++static int
++acx_s_reset_dev(netdevice_t *dev)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++      const char* msg = "";
++      unsigned long flags;
++      int result = NOT_OK;
++      u16 hardware_info;
++      u16 ecpu_ctrl;
++
++      FN_ENTER;
++
++      /* we're doing a reset, so hardware is unavailable */
++
++      /* reset the device to make sure the eCPU is stopped
++       * to upload the firmware correctly */
++
++      acx_lock(priv, flags);
++
++      acx_l_reset_mac(priv);
++
++      ecpu_ctrl = acx_read_reg16(priv, IO_ACX_ECPU_CTRL) & 1;
++      if (!ecpu_ctrl) {
++              msg = "eCPU is already running. ";
++              goto fail_unlock;
++      }
++
++#ifdef WE_DONT_NEED_THAT_DO_WE
++      if (acx_read_reg16(priv, IO_ACX_SOR_CFG) & 2) {
++              /* eCPU most likely means "embedded CPU" */
++              msg = "eCPU did not start after boot from flash. ";
++              goto fail_unlock;
++      }
++
++      /* check sense on reset flags */
++      if (acx_read_reg16(priv, IO_ACX_SOR_CFG) & 0x10) {
++              printk("%s: eCPU did not start after boot (SOR), "
++                      "is this fatal?\n", dev->name);
++      }
++#endif
++      /* scan, if any, is stopped now, setting corresponding IRQ bit */
++      priv->irq_status |= HOST_INT_SCAN_COMPLETE;
++
++      acx_unlock(priv, flags);
++
++      /* without this delay acx100 may fail to report hardware_info
++      ** (see below). Most probably eCPU runs some init code */
++      acx_s_msleep(10);
++
++      /* Need to know radio type before fw load */
++      hardware_info = acx_read_reg16(priv, IO_ACX_EEPROM_INFORMATION);
++      priv->form_factor = hardware_info & 0xff;
++      priv->radio_type = hardware_info >> 8;
++
++      /* load the firmware */
++      if (OK != acx_s_upload_fw(priv)){
++              printk("Failed to load firmware\n");
++              goto fail;
++      }
++
++      acx_s_msleep(10);
++
++      /* now start eCPU by clearing bit */
++      acxlog(L_DEBUG, "booted eCPU up and waiting for completion...\n");
++      //acx_write_reg16(priv, IO_ACX_ECPU_CTRL, ecpu_ctrl & ~0x1);
++      write_reg(priv, IO_ACX_ECPU_CTRL, ecpu_ctrl & ~0x1);
++
++      /* wait for eCPU bootup */
++      if (OK != acx_s_verify_init(priv)) {
++              msg = "timeout waiting for eCPU. ";
++              goto fail;
++      }
++
++      acxlog(L_DEBUG, "eCPU has woken up, card is ready to be configured\n");
++
++      if (IS_ACX111(priv)) {
++              acxlog(L_DEBUG, "cleaning up cmd mailbox access area\n");
++              acx_write_cmd_status(priv, 0);
++              acx_read_cmd_status(priv);
++              if (priv->cmd_status) {
++                      msg = "error cleaning cmd mailbox area. ";
++                      goto fail;
++              }
++      }
++
++      /* TODO what is this one doing ?? adapt for acx111 */
++      if ((OK != acx_read_eeprom_area(priv)) && IS_ACX100(priv)) {
++              /* does "CIS" mean "Card Information Structure"?
++               * If so, then this would be a PCMCIA message...
++               */
++              msg = "CIS error. ";
++              goto fail;
++      }
++
++      result = OK;
++      FN_EXIT1(result);
++      return result;
++
++/* Finish error message. Indicate which function failed */
++fail_unlock:
++      acx_unlock(priv, flags);
++fail:
++      printk("acx: %sreset_dev() FAILED\n", msg);
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/***********************************************************************
++** acx_init_mboxes
++*/
++void
++acx_init_mboxes(wlandevice_t *priv)
++{
++      u32 cmd_offs, info_offs;
++
++      FN_ENTER;
++
++      cmd_offs = acx_read_reg32(priv, IO_ACX_CMD_MAILBOX_OFFS);
++      info_offs = acx_read_reg32(priv, IO_ACX_INFO_MAILBOX_OFFS);
++      priv->cmd_area = (u8 *) cmd_offs + 0x4;
++      priv->info_area = (u8 *) info_offs + 0x4;
++      acxlog(L_DEBUG, "iobase2=%p\n"
++              "cmd_mbox_offset=%X cmd_area=%p\n"
++              "info_mbox_offset=%X info_area=%p\n",
++              priv->iobase2,
++              cmd_offs, priv->cmd_area,
++              info_offs, priv->info_area);
++
++      FN_EXIT0;
++}
++
++
++/*----------------------------------------------------------------
++* acx_s_issue_cmd_timeo
++* Excecutes a command in the command mailbox
++*
++* Arguments:
++*   *pcmdparam = an pointer to the data. The data mustn't include
++*                the 4 byte command header!
++*
++* 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(
++      wlandevice_t *priv,
++      unsigned int cmd,
++      void *buffer,
++      unsigned buflen,
++      unsigned timeout)
++{
++#else
++int
++acxpci_s_issue_cmd_timeo_debug(
++      wlandevice_t *priv,
++      unsigned cmd,
++      void *buffer,
++      unsigned buflen,
++      unsigned timeout,
++      const char* cmdstr)
++{
++      unsigned long start = jiffies;
++#endif
++      const char *devname;
++      unsigned counter;
++      u16 irqtype;
++      u16 cmd_status;
++
++      FN_ENTER;
++
++      devname = priv->netdev->name;
++      if (!devname || !devname[0])
++              devname = "acx";
++
++      acxlog(L_CTL, FUNC"(cmd:%s,buflen:%u,timeout:%ums,type:0x%04X)\n",
++              cmdstr, buflen, timeout,
++              buffer ? le16_to_cpu(((acx_ie_generic_t *)buffer)->type) : -1);
++
++      if (!(priv->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 pdr (len=%u):\n", buflen);
++              acx_dump_bytes(buffer, buflen);
++      }
++
++      /* wait for firmware to become idle for our command submission */
++      counter = 199; /* in ms */
++      do {
++              acx_read_cmd_status(priv);
++              /* Test for IDLE state */
++              if (!priv->cmd_status)
++                      break;
++              if (counter % 10 == 0) {
++                      /* we waited 10 iterations, no luck. Sleep 10 ms */
++                      acx_s_msleep(10);
++              }
++      } while (--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, priv->cmd_status);
++              goto bad;
++      } else if (counter < 190) { /* if waited >10ms... */
++              acxlog(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)
++                      acx_mailbox_fill(priv, (unsigned int) priv->cmd_area, 0xAA, buflen);
++#endif
++              acx_mailbox_write(priv, 
++                               (unsigned int) priv->cmd_area, 
++                               buffer, (cmd == ACX1xx_CMD_INTERROGATE) ? 4 : buflen);
++      }
++
++      /* now write the actual command type */
++      priv->cmd_type = cmd;
++      acx_write_cmd_type(priv, cmd);
++      /* execute command */
++      acx_write_reg16(priv, IO_ACX_INT_TRIG, INT_TRIG_CMD);
++      acx_write_flush(priv);
++
++      /* 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 */
++      timeout = (timeout-1) | 1;
++      if (unlikely(timeout > 1199))
++              timeout = 1199;
++      /* clear CMD_COMPLETE bit. can be set only by IRQ handler: */
++      priv->irq_status &= ~HOST_INT_CMD_COMPLETE;
++
++      /* we schedule away sometimes (timeout can be large) */
++      counter = timeout;
++      do {
++              if (!priv->irqs_active) { /* IRQ disabled: poll */
++                      irqtype = acx_read_reg16(priv, IO_ACX_IRQ_STATUS_NON_DES);
++                      if (irqtype & HOST_INT_CMD_COMPLETE) {
++                              acx_write_reg16(priv, IO_ACX_IRQ_ACK,
++                                              HOST_INT_CMD_COMPLETE);
++                              break;
++                      }
++              } else { /* Wait when IRQ will set the bit */
++                      irqtype = priv->irq_status;
++                      if (irqtype & HOST_INT_CMD_COMPLETE)
++                              break;
++              }
++
++              if (counter % 10 == 0) {
++                      /* we waited 10 iterations, no luck. Sleep 10 ms */
++                      acx_s_msleep(10);
++              }
++      } while (--counter);
++
++      /* save state for debugging */
++      acx_read_cmd_status(priv);
++      cmd_status = priv->cmd_status;
++
++      /* put the card in IDLE state */
++      priv->cmd_status = 0;
++      acx_write_cmd_status(priv, 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, (priv->irqs_active) ? "waiting" : "polling",
++                      irqtype, priv->irq_status, timeout,
++                      cmd_status, acx_cmd_status_str(cmd_status));
++              goto bad;
++      } else if (timeout - counter > 30) { /* if waited >30ms... */
++              acxlog(L_CTL|L_DEBUG, FUNC"(): %s for CMD_COMPLETE %dms. "
++                      "count:%d. Please report\n",
++                      (priv->irqs_active) ? "waited" : "polled",
++                      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),
++                      timeout - counter, timeout);
++              /* zero out result buffer */
++              if (buffer && buflen)
++                      memset(buffer, 0, buflen);
++              goto bad;
++      }
++
++      /* read in result parameters if needed */
++      if (buffer && buflen && (cmd == ACX1xx_CMD_INTERROGATE)) {
++              //memcpy(buffer, priv->cmd_area, buflen);
++              acx_mailbox_read(priv, (unsigned int) priv->cmd_area, buffer, buflen);
++              if (acx_debug & L_DEBUG) {
++                      printk("output buffer (len=%u): ", buflen);
++                      acx_dump_bytes(buffer, buflen);
++              }
++      }
++/* ok: */
++      acxlog(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;
++}
++
++
++/*----------------------------------------------------------------
++* acx_s_get_firmware_version
++*----------------------------------------------------------------*/
++static void
++acx_s_get_firmware_version(wlandevice_t *priv)
++{
++      fw_ver_t fw;
++      u8 hexarr[4] = { 0, 0, 0, 0 };
++      int hexidx = 0, val = 0;
++      const char *num;
++      char c;
++
++      FN_ENTER;
++
++      acx_s_interrogate(priv, &fw, ACX1xx_IE_FWREV);
++      memcpy(priv->firmware_version, fw.fw_id, FW_ID_SIZE);
++      priv->firmware_version[FW_ID_SIZE] = '\0';
++      acxlog(L_DEBUG, "fw_ver: fw_id='%s' hw_id=%08X\n",
++                              priv->firmware_version, fw.hw_id);
++
++      if (strncmp(fw.fw_id, "Rev ", 4) != 0) {
++              printk("acx: strange firmware version string "
++                      "'%s', please report\n", priv->firmware_version);
++              priv->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;
++              }
++
++              priv->firmware_numver = (u32)(
++                              (hexarr[0] << 24) + (hexarr[1] << 16)
++                              + (hexarr[2] << 8) + hexarr[3]);
++              acxlog(L_DEBUG, "firmware_numver 0x%08X\n", priv->firmware_numver);
++      }
++      if (IS_ACX111(priv)) {
++              if (priv->firmware_numver == 0x00010011) {
++                      /* This one does not survive floodpinging */
++                      printk("acx: firmware '%s' is known to be buggy, "
++                              "please upgrade\n", priv->firmware_version);
++              }
++              if (priv->firmware_numver == 0x02030131) {
++                      /* With this one, all rx packets look mangled
++                      ** Most probably we simply do not know how to use it
++                      ** properly */
++                      printk("acx: firmware '%s' does not work well "
++                              "with this driver\n", priv->firmware_version);
++              }
++      }
++
++      priv->firmware_id = le32_to_cpu(fw.hw_id);
++
++      /* we're able to find out more detailed chip names now */
++      switch (priv->firmware_id & 0xffff0000) {
++              case 0x01010000:
++              case 0x01020000:
++                      priv->chip_name = name_tnetw1100a;
++                      break;
++              case 0x01030000:
++                      priv->chip_name = name_tnetw1100b;
++                      break;
++              case 0x03000000:
++              case 0x03010000:
++                      priv->chip_name = name_tnetw1130;
++                      break;
++              default:
++                      printk("acx: unknown chip ID 0x%08X, "
++                              "please report\n", priv->firmware_id);
++                      break;
++      }
++
++      FN_EXIT0;
++}
++
++
++/*----------------------------------------------------------------
++* acx_display_hardware_details
++*
++* Arguments:
++*     priv: ptr to wlandevice that contains all the details
++*       displayed by this function
++* Call context:
++*     acx_probe_pci
++* Comment:
++*     This function will display strings to the system log according
++* to device form_factor and radio type. It will needed to be
++*----------------------------------------------------------------*/
++static void
++acx_display_hardware_details(wlandevice_t *priv)
++{
++      const char *radio_str, *form_str;
++
++      FN_ENTER;
++
++      switch (priv->radio_type) {
++      case RADIO_MAXIM_0D:
++              /* hmm, the DWL-650+ seems to have two variants,
++               * according to a windows driver changelog comment:
++               * RFMD and Maxim. */
++              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;
++      default:
++              radio_str = "UNKNOWN, please report the radio type name!";
++              break;
++      }
++
++      switch (priv->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: form factor 0x%02X (%s), "
++              "radio type 0x%02X (%s), EEPROM version 0x%02X, "
++              "uploaded firmware '%s' (0x%08X)\n",
++              priv->form_factor, form_str, priv->radio_type, radio_str,
++              priv->eeprom_version, priv->firmware_version,
++              priv->firmware_id);
++
++      FN_EXIT0;
++}
++
++/***********************************************************************
++*/
++#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(wlandevice_t *priv)
++{
++      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 != acx_read_eeprom_offset(priv,
++                                       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 */
++
++
++/***********************************************************************
++*/
++static void
++acx_s_device_chain_add(struct net_device *dev)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++
++      down(&root_acx_dev_sem);
++      priv->prev_nd = root_acx_dev.newest;
++      root_acx_dev.newest = dev;
++      priv->netdev = dev;
++      up(&root_acx_dev_sem);
++}
++
++static void
++acx_s_device_chain_remove(struct net_device *dev)
++{
++      struct net_device *querydev;
++      struct net_device *olderdev;
++      struct net_device *newerdev;
++
++      down(&root_acx_dev_sem);
++      querydev = root_acx_dev.newest;
++      newerdev = NULL;
++      while (querydev) {
++              olderdev = ((wlandevice_t*)netdev_priv(querydev))->prev_nd;
++              if (0 == strcmp(querydev->name, dev->name)) {
++                      if (!newerdev) {
++                              /* if we were at the beginning of the
++                               * list, then it's the list head that
++                               * we need to update to point at the
++                               * next older device */
++                              root_acx_dev.newest = olderdev;
++                      } else {
++                              /* it's the device that is newer than us
++                               * that we need to update to point at
++                               * the device older than us */
++                              ((wlandevice_t*)netdev_priv(newerdev))->
++                                      prev_nd = olderdev;
++                      }
++                      break;
++              }
++              /* "newerdev" is actually the device of the old iteration,
++               * but since the list starts (root_acx_dev.newest)
++               * with the newest devices,
++               * it's newer than the ones following.
++               * Oh the joys of iterating from newest to oldest :-\ */
++              newerdev = querydev;
++
++              /* keep checking old devices for matches until we hit the end
++               * of the list */
++              querydev = olderdev;
++      }
++      up(&root_acx_dev_sem);
++}
++
++
++/***********************************************************************
++** acx_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
++acx_free_coherent(struct pci_dev *hwdev, size_t size,
++                      void *vaddr, dma_addr_t dma_handle)
++{
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 53)
++      dma_free_coherent(hwdev == NULL ? NULL : &hwdev->dev,
++                      size, vaddr, dma_handle);
++#else
++      pci_free_consistent(hwdev, size, vaddr, dma_handle);
++#endif
++}
++
++void
++acx_free_desc_queues(wlandevice_t *priv)
++{
++#define ACX_FREE_QUEUE(size, ptr, phyaddr) \
++      if (ptr) { \
++              acx_free_coherent(0, size, ptr, phyaddr); \
++              ptr = NULL; \
++              size = 0; \
++      }
++
++      FN_ENTER;
++
++      ACX_FREE_QUEUE(priv->txhostdesc_area_size, priv->txhostdesc_start, priv->txhostdesc_startphy);
++      ACX_FREE_QUEUE(priv->txbuf_area_size, priv->txbuf_start, priv->txbuf_startphy);
++
++      priv->txdesc_start = NULL;
++
++      ACX_FREE_QUEUE(priv->rxhostdesc_area_size, priv->rxhostdesc_start, priv->rxhostdesc_startphy);
++      ACX_FREE_QUEUE(priv->rxbuf_area_size, priv->rxbuf_start, priv->rxbuf_startphy);
++
++      priv->rxdesc_start = NULL;
++
++      FN_EXIT0;
++}
++
++
++/*----------------------------------------------------------------
++* acx_s_delete_dma_regions
++*----------------------------------------------------------------*/
++static void
++acx_s_delete_dma_regions(wlandevice_t *priv)
++{
++      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? */
++      acx_write_reg16(priv, IO_ACX_ENABLE, 0);
++
++      acx_s_msleep(100);
++
++      acx_lock(priv, flags);
++      acx_free_desc_queues(priv);
++      acx_unlock(priv, flags);
++
++      FN_EXIT0;
++}
++
++
++/*----------------------------------------------------------------
++* acx_e_probe_pci
++*
++* 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
++*
++* Arguments:
++*     pdev            ptr to pci device structure containing info about
++*                     pci configuration.
++*     id              ptr to the device id entry that matched this device.
++*
++* Returns:
++*     zero            - success
++*     negative        - failed
++*
++* Call context:
++*     process thread
++----------------------------------------------------------------*/
++static const u16
++IO_ACX100[] =
++{
++      0x0000, /* IO_ACX_SOFT_RESET */
++
++      0x0004, /* IO_ACX_HW_SLAVE_REG_ADDR */
++      0x0008, /* IO_ACX_HW_SLAVE_REG_DATA */
++      0x000c, /* IO_ACX_HW_SLAVE_REG_REG_CTRL */
++
++      0x0014, /* IO_ACX_SLV_MEM_ADDR */
++      0x0018, /* IO_ACX_SLV_MEM_DATA */
++      0x001c, /* IO_ACX_SLV_MEM_CTL */
++      0x0020, /* IO_ACX_SLV_END_CTL */
++      0x0024, /* IO_ACX_CHIPID */
++
++      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 */
++
++      0x0294, /* IO_ACX_GPIO_IN */
++      0x0298, /* IO_ACX_GPIO_OUT */
++      0x029c, /* IO_ACX_GPIO_PD */
++      0x02a0, /* IO_ACX_GPIO_CFG */
++
++      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 */
++      
++      0x0804, /* IO_ACX_HI_CTL */
++      0x0808, /* IO_ACX_LPWR_MGN */
++
++      0x010c, /* IO_ACX_PCI_ARB_CFG */ 
++      
++};
++
++static void
++acx_netdev_init(struct net_device *dev) {}
++
++//FIXME: do the same for USB
++static int
++acx_change_mtu(struct net_device *dev, int mtu)
++{
++      enum {
++              MIN_MTU = 256,
++              MAX_MTU = WLAN_DATA_MAXLEN - (ETH_HLEN)
++      };
++
++      if (mtu < MIN_MTU || mtu > MAX_MTU)
++              return -EINVAL;
++
++      dev->mtu = mtu;
++      return 0;
++}
++
++
++static int acx_enable(struct platform_device *pdev){
++        unsigned long flags;
++
++        /* We need to disabe the interrupt
++         * around reset.
++         */
++        local_irq_save(flags);
++
++        /* Now lets turn on and
++         * reset the device.
++         */
++        pca9535_gpio_write(GPIO6, LOW);
++        pca9535_gpio_write(GPIO12, LOW);
++
++        /* TODO: someother configuration needs
++         * to be done here.
++         */
++
++        // Now we can enable interrupt.
++        local_irq_restore(flags);
++
++
++        return 0;
++}
++
++static inline void test(wlandevice_t *priv) {
++      printk("===============================\n");
++      printk("Reset   : %04x\n",acx_read_reg16(priv, IO_ACX_SOFT_RESET));
++      printk("eCPU CTL: %04x\n",acx_read_reg16(priv, IO_ACX_ECPU_CTRL));
++      printk("SOR CFG : %08x\n",acx_read_reg32(priv, IO_ACX_SOR_CFG));
++      printk("EE START: %08x\n",acx_read_reg32(priv, IO_ACX_EE_START));
++      printk("HI CTRL : %08x\n",acx_read_reg32(priv, IO_ACX_HI_CTRL));
++//    printk("Info    : %08x\n",acx_read_reg32(priv, IO_ACX_EEPROM_INFORMATION));
++      printk("GPIO OE : %04x\n",acx_read_reg16(priv, IO_ACX_GPIO_OE));
++      printk("GPIO OUT: %04x\n",acx_read_reg16(priv, IO_ACX_GPIO_OUT));
++      printk("GPIO IN : %04x\n",acx_read_reg16(priv, IO_ACX_GPIO_IN));
++      printk("GPIO PD : %04x\n",acx_read_reg16(priv, IO_ACX_GPIO_PD));
++      printk("GPIO CFG: %04x\n",acx_read_reg16(priv, IO_ACX_GPIO_CFG));
++      printk("Chip ID : %08x\n",acx_read_reg32(priv, IO_ACX_CHIPID));
++
++/*
++      printk("HW CTRL : %08x\n",acx_read_reg32(priv,IO_ACX_HW_SLAVE_REG_CTRL));
++      printk("HW ADDR : %08x\n",acx_read_reg32(priv,IO_ACX_HW_SLAVE_REG_ADDR));
++      printk("HW DATA : %08x\n",acx_read_reg32(priv,IO_ACX_HW_SLAVE_REG_DATA));
++*/
++
++      msleep(50);
++
++      printk("==============================\n");     
++}
++
++static int __init acx_probe(struct net_device *ndev, void __iomem *addr, struct resource *res){
++      wlandevice_t    *priv             = netdev_priv(ndev);
++      int             ret               = 0;
++
++      ether_setup(ndev);
++
++      /* now that device init was successful, fill remaining fields... */
++        ndev->open            = &acx_e_open;
++        ndev->stop            = &acx_e_close;
++      ndev->hard_start_xmit   = &acx_i_start_xmit;
++        ndev->get_stats       = &acx_e_get_stats;
++        ndev->get_wireless_stats = &acx_e_get_wireless_stats;
++#if WIRELESS_EXT >= 13
++        ndev->wireless_handlers = (struct iw_handler_def *)&acx_ioctl_handler_def;
++#else
++        ndev->do_ioctl = &acx_e_ioctl_old;
++#endif
++        ndev->set_multicast_list = &acx_i_set_multicast_list;
++        ndev->tx_timeout       = &acx_i_tx_timeout;
++        ndev->change_mtu       = &acx_change_mtu;
++        ndev->watchdog_timeo   = 4 * HZ;
++
++      spin_lock_init(&priv->lock);    /* initial state: unlocked */
++        /* We do not start with downed sem: we want PARANOID_LOCKING to work */
++        sema_init(&priv->sem, 1);       /* initial state: 1 (upped) */
++
++      priv->iobase              = (unsigned char *) addr;
++        priv->iobase2             = 0;
++        priv->membase             = res->start;
++        priv->chip_type           = CHIPTYPE_ACX100;
++        priv->chip_name           = name_acx100;
++        priv->io                  = IO_ACX100;
++        priv->mgmt_timer.function = (void (*)(unsigned long))0x0000dead;
++        spin_lock_init(&priv->lock);
++      
++      test(priv);
++
++#ifdef NONESSENTIAL_FEATURES
++        acx_show_card_eeprom_id(priv);
++#endif /* NONESSENTIAL_FEATURES */
++
++        /* 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, "after setup");
++
++      /* register new dev in linked list */
++        acx_s_device_chain_add(ndev);
++
++      if((ret = acx_s_reset_dev(ndev)) != OK){
++                /* Failed to reset device */
++                ret = -EIO;
++                goto reset_fail;
++        }
++
++        /* ok, basic setup is finished, now start initialising the card */
++#if 0
++        hardware_info           = acx_read_reg16(priv, IO_ACX_EEPROM_INFORMATION);
++        priv->form_factor = (u8)(hardware_info & 0xff);
++        priv->radio_type  = (u8)(hardware_info >> 8 & 0xff);
++#endif
++
++        if (OK != acx_read_eeprom_offset(priv, 0x05, &priv->eeprom_version)) {
++                ret = -EIO;
++                goto fail_read_eeprom_version;
++        }
++
++        if (OK != acx_s_init_mac(ndev)) {
++                acxlog(L_DEBUG | L_INIT,
++                       "Danger Will Robinson, MAC did not come back\n");
++                ret = -EIO;
++                goto fail_init_mac;
++        }
++
++      if (OK != acx_s_set_defaults(priv)) {
++                printk("acx: set_defaults() FAILED\n");
++                goto fail_set_defaults;
++        }
++
++        /* needs to be after acx_init_mac() due to necessary init stuff */
++        acx_s_get_firmware_version(priv);
++
++      acx_display_hardware_details(priv);
++      
++      /* ...and 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 */
++        ret = register_netdev(ndev);
++        if (OK != ret) {
++                      printk(KERN_ERR
++                       "%s:  Register net device of %s FAILED: %d\n",
++                       __func__, ndev->name, ret);
++                ret = -EIO;
++                goto fail_register_netdev;
++        }
++      acx_carrier_off(ndev, "on probe");
++
++#ifdef CONFIG_PROC_FS
++        if (OK != acx_proc_register_entries(ndev)) {
++                ret = -EIO;
++                goto fail_proc_register_entries;
++        }
++#endif
++
++#if CMD_DISCOVERY
++        great_inquisitor(priv);
++#endif
++
++
++      return 0;
++
++#ifdef CONFIG_PROC_FS
++fail_proc_register_entries:
++#endif
++
++        if (priv->dev_state_mask & ACX_STATE_IFACE_UP)
++                acx_s_down(ndev);
++        unregister_netdev(ndev);
++
++fail_register_netdev:
++        acx_s_delete_dma_regions(priv);
++fail_set_defaults:
++fail_init_mac:
++fail_read_eeprom_version:
++reset_fail:
++      acx_s_device_chain_remove(ndev);
++
++      return ret;
++}
++
++static void dumpRegs(char *msg, unsigned char *base) {
++      u32 val  = 0;
++      u16 addr = 0;
++
++      printk("============= [ %s ] ===============\n",msg);
++
++      for(addr = 0; addr <= 0x0be0; addr+=4){
++              if(addr >= 0x0710 && addr <= 0x0740){
++                      val = 0;
++                      printk("Reg[%04x] : %08x\n",addr, val);
++                      msleep(50);     
++                      continue;
++              }
++
++              val = readw((u8 *) base + addr)  +  (readw((u8 *) base + addr + 2) << 16);
++
++              printk("Reg[%04x] : %08x\n",addr, val);
++              msleep(50);
++      }
++
++      printk("=====================================\n");
++}
++
++
++static int __init acx_drv_probe(struct device *dev){
++      struct platform_device *pdev   = to_platform_device(dev);
++        struct net_device       *ndev  = NULL;
++        struct resource         *res   = NULL;
++        unsigned int __iomem    *addr  = NULL;
++      wlandevice_t            *priv  = NULL;
++        int ret;
++
++        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++        if (!res) {
++                printk(KERN_ERR "Device not found\n");
++                ret = -ENODEV;
++                goto out;
++        }
++
++
++        if (!request_mem_region(res->start, SZ_32M, CARDNAME)) {
++                printk(KERN_ERR "Device busy\n");
++                ret = -EBUSY;
++                goto out;
++        }
++
++        // Create new ethernet device
++        ndev = alloc_netdev(sizeof(wlandevice_t), "wlan%d", acx_netdev_init);
++        if (!ndev) {
++                printk("%s: could not allocate device.\n", CARDNAME);
++                ret = -ENOMEM;
++                goto out_release_io;
++        }
++        SET_MODULE_OWNER(ndev);
++        SET_NETDEV_DEV(ndev, dev);
++      
++      // Get driver private data
++      priv      = netdev_priv(ndev);
++
++      // Cleanup the private area
++      memset((void *) priv, 0, sizeof(wlandevice_t));
++
++        ndev->dma = (unsigned char)-1;
++        ndev->irq = platform_get_irq(pdev, 0);
++      priv->dev = dev;
++
++        // Enable device
++      acx_enable(pdev);
++
++        /* Create IOMEM port so we
++         * can use to to read and write
++         * from card registers.
++         */
++        if(!(addr = ioremap(res->start, SZ_32M))){
++                printk(KERN_ERR "Failed to map ioport\n");
++                ret = -ENOMEM;
++                goto  free_device;
++        }
++
++        dev_set_drvdata(dev, ndev);
++
++      //dumpRegs("After",addr);
++
++
++        if((ret = acx_probe(ndev, addr,res))){
++                /* Something wrong we couldn't
++                 * talke to the device.
++                 */
++                printk(KERN_ERR "Failed to probe ACX\n");
++                goto out_iounmap;
++        }
++
++       printk("acx "WLAN_RELEASE": net device %s, driver compiled "
++                "against wireless extensions %d and Linux %s\n",
++                ndev->name, WIRELESS_EXT, UTS_RELEASE);
++      
++      return 0;
++
++out_iounmap:
++        dev_set_drvdata(dev, NULL);
++        iounmap(addr);
++free_device:
++        free_netdev(ndev);
++out_release_io:
++        release_mem_region(res->start, SZ_32M);
++out:
++        return ret;
++}
++
++static int acx_remove(struct device *dev) 
++{
++      struct platform_device *pdev  = to_platform_device(dev);
++        struct net_device       *ndev = (dev? dev_get_drvdata(dev) : NULL);
++        wlandevice_t            *priv = (ndev? (wlandevice_t *) netdev_priv(ndev) : NULL);
++        struct resource         *res  = NULL;
++
++        if(!ndev){
++                printk(KERN_ERR "Invalid network device structure\n");
++                return 0;
++        }
++
++        dev_set_drvdata(dev, NULL);
++        unregister_netdev(ndev);
++
++#if 0
++        free_irq(ndev->irq, ndev);
++#endif
++
++        iounmap(priv->iobase);
++        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++        release_mem_region(res->start, SZ_32M);
++
++        free_netdev(ndev);
++
++        return 0;
++}
++
++/***********************************************************************
++*/
++#ifdef CONFIG_PM
++static int if_was_up = 0; /* FIXME: HACK, do it correctly sometime instead */
++static int
++acx_suspend(struct device *dev, pm_message_t state, u32 level)
++{
++#if 0
++      struct net_device *ndev = pci_get_drvdata(pdev);
++      wlandevice_t *priv = netdev_priv(dev);
++
++      FN_ENTER;
++
++      acx_sem_lock(priv);
++
++      printk("acx: experimental suspend handler called for %p\n", priv);
++      if (netif_device_present(ndev)) {
++              if_was_up = 1;
++              acx_s_down(ndev);
++      }
++      else
++              if_was_up = 0;
++
++      netif_device_detach(ndev);      /* This one cannot sleep */
++      acx_s_delete_dma_regions(priv);
++
++      acx_sem_unlock(priv);
++
++      FN_EXIT0;
++#endif
++      return OK;
++}
++
++static int
++acx_resume(struct device *dev, u32 level)
++{
++#if 0
++      struct platform_device *pdev  = to_platform_device(dev);
++      struct net_device       *ndev;
++      wlandevice_t            *priv;
++
++      printk(KERN_WARNING "rsm: resume\n");
++      ndev = dev_get_drvdata(dev);
++      printk(KERN_WARNING "rsm: got dev\n");
++
++      if (!netif_running(ndev))
++              return 0;
++
++      priv = netdev_priv(ndev);
++
++      acx_sem_lock(priv);
++
++      printk(KERN_WARNING "rsm: got priv\n");
++      FN_ENTER;
++      printk("acx: experimental resume handler called for %p!\n", priv);
++      // TODO
++      acxlog(L_DEBUG, "rsm: power state set\n");
++
++      acxlog(L_DEBUG, "rsm: PCI state restored\n");
++      acx_s_reset_dev(ndev);
++      acxlog(L_DEBUG, "rsm: device reset done\n");
++
++      if (OK != acx_s_init_mac(ndev)) {
++              printk("rsm: init_mac FAILED\n");
++              goto fail;
++      }
++      acxlog(L_DEBUG, "rsm: init MAC done\n");
++
++      if (1 == if_was_up)
++              acx_s_up(ndev);
++      acxlog(L_DEBUG, "rsm: acx up\n");
++
++      /* now even reload all card parameters as they were before suspend,
++       * and possibly be back in the network again already :-)
++       * FIXME: should this be done in that scheduled task instead?? */
++      if (ACX_STATE_IFACE_UP & priv->dev_state_mask)
++              acx_s_update_card_settings(priv, 0, 1);
++      acxlog(L_DEBUG, "rsm: settings updated\n");
++      netif_device_attach(ndev);
++      acxlog(L_DEBUG, "rsm: device attached\n");
++fail: /* we need to return OK here anyway, right? */
++      acx_sem_unlock(priv);
++      FN_EXIT0;
++#endif
++      return OK;
++}
++#endif /* CONFIG_PM */
++
++
++/*----------------------------------------------------------------
++* acx_s_up
++*
++* Side effects:
++*     - Enables on-card interrupt requests
++*     - calls acx_start
++* Call context:
++*     - process thread
++* Comment:
++*     This function is called by acx_open (when ifconfig sets the
++*     device as up).
++*----------------------------------------------------------------*/
++static void
++acx_s_up(netdevice_t *dev)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++      unsigned long flags;
++
++      FN_ENTER;
++
++      acx_lock(priv, flags);
++      acx_l_enable_irq(priv);
++      acx_unlock(priv, 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(&priv->mgmt_timer);
++      priv->mgmt_timer.function = acx_i_timer;
++      priv->mgmt_timer.data = (unsigned long)priv;
++
++      /* Need to set ACX_STATE_IFACE_UP first, or else
++      ** timer won't be started by acx_set_status() */
++      SET_BIT(priv->dev_state_mask, ACX_STATE_IFACE_UP);
++      switch (priv->mode) {
++      case ACX_MODE_0_ADHOC:
++      case ACX_MODE_2_STA:
++              /* actual scan cmd will happen in start() */
++              acx_set_status(priv, ACX_STATUS_1_SCANNING); break;
++      case ACX_MODE_3_AP:
++      case ACX_MODE_MONITOR:
++              acx_set_status(priv, ACX_STATUS_4_ASSOCIATED); break;
++      }
++
++      acx_s_start(priv);
++
++      FN_EXIT0;
++}
++
++
++/*----------------------------------------------------------------
++* acx_s_down
++*
++* Side effects:
++*     - disables on-card interrupt request
++* Call context:
++*     process thread
++* Comment:
++*     this disables the netdevice
++*----------------------------------------------------------------*/
++static void
++acx_s_down(netdevice_t *dev)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++      unsigned long flags;
++
++      FN_ENTER;
++
++      /* Disable IRQs first, so that IRQs cannot race with us */
++      acx_lock(priv, flags);
++      acx_l_disable_irq(priv);
++      acx_unlock(priv, 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(priv);
++      FLUSH_SCHEDULED_WORK();
++      acx_sem_lock(priv);
++
++      /* 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(priv, flags);
++      acx_stop_queue(dev, "during close");
++      acx_set_status(priv, ACX_STATUS_0_STOPPED);
++      acx_unlock(priv, 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(&priv->mgmt_timer);
++
++      FN_EXIT0;
++}
++
++
++/*----------------------------------------------------------------
++* acx_e_open
++*
++* WLAN device open method.  Called from p80211netdev when kernel
++* device open (start) method is called in response to the
++* SIOCSIFFLAGS ioctl changing the flags bit IFF_UP
++* from clear to set.
++*
++* Returns:
++*     0       success
++*     >0      f/w reported error
++*     <0      driver reported error
++*
++* Call context:
++*     process thread
++----------------------------------------------------------------*/
++static int
++acx_e_open(netdevice_t *dev)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++      int result = OK;
++
++      FN_ENTER;
++
++      acxlog(L_INIT, "module count++\n");
++      WLAN_MOD_INC_USE_COUNT;
++
++      acx_sem_lock(priv);
++
++      acx_init_task_scheduler(priv);
++
++      /* request shared IRQ handler */
++      if (request_irq(dev->irq, acx_i_interrupt, SA_SHIRQ, dev->name, dev)) {
++              printk("%s: request_irq FAILED\n", dev->name);
++              result = -EAGAIN;
++              goto done;
++      }
++      acxlog(L_DEBUG|L_IRQ, "request_irq %d successful\n", dev->irq);
++
++      /* ifup device */
++      acx_s_up(dev);
++
++      /* 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(priv);
++
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/*----------------------------------------------------------------
++* acx_e_close
++*
++* WLAN device close method.  Called from network core when kernel
++* device close method is called in response to the
++* SIOCSIIFFLAGS ioctl changing the flags bit IFF_UP
++* from set to clear.
++* (i.e. called for "ifconfig DEV down")
++*
++* Returns:
++*     0       success
++*     >0      f/w reported error
++*     <0      driver reported error
++*
++* Call context:
++*     process thread
++----------------------------------------------------------------*/
++static int
++acx_e_close(netdevice_t *dev)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++
++      FN_ENTER;
++
++      acx_sem_lock(priv);
++
++      /* ifdown device */
++      CLEAR_BIT(priv->dev_state_mask, ACX_STATE_IFACE_UP);
++      if (netif_device_present(dev)) {
++              acx_s_down(dev);
++      }
++
++      /* disable all IRQs, release shared IRQ handler */
++      acx_write_reg16(priv, IO_ACX_IRQ_MASK, 0xffff);
++      acx_write_reg16(priv, IO_ACX_FEMR, 0x0);
++      free_irq(dev->irq, dev);
++
++      /* 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.
++       */
++      acxlog(L_INIT, "module count--\n");
++      WLAN_MOD_DEC_USE_COUNT;
++
++      acx_sem_unlock(priv);
++
++      acxlog(L_INIT, "closed device\n");
++      FN_EXIT0;
++      return OK;
++}
++
++
++/*----------------------------------------------------------------
++* acx_i_tx_timeout
++*
++* Called from network core. Must not sleep!
++*----------------------------------------------------------------*/
++static void
++acx_i_tx_timeout(netdevice_t *dev)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++      unsigned long flags;
++      unsigned int tx_num_cleaned;
++
++      FN_ENTER;
++
++      acx_lock(priv, flags);
++
++      /* clean processed tx descs, they may have been completely full */
++      tx_num_cleaned = acx_l_clean_tx_desc(priv);
++
++      /* 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 ((priv->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", dev->name);
++              acx_l_clean_tx_desc_emergency(priv);
++      }
++
++      if (acx_queue_stopped(dev) && (ACX_STATUS_4_ASSOCIATED == priv->status))
++              acx_wake_queue(dev, "after tx timeout");
++
++      /* stall may have happened due to radio drift, so recalib radio */
++      acx_schedule_after_interrupt_task(priv, ACX_AFTER_IRQ_CMD_RADIO_RECALIB);
++
++      /* do unimportant work last */
++      printk("%s: tx timeout!\n", dev->name);
++      priv->stats.tx_errors++;
++
++      acx_unlock(priv, flags);
++
++      FN_EXIT0;
++}
++
++
++/*----------------------------------------------------------------
++* acx_e_get_stats
++*----------------------------------------------------------------*/
++static struct net_device_stats*
++acx_e_get_stats(netdevice_t *dev)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++      return &priv->stats;
++}
++
++
++/*----------------------------------------------------------------
++* acx_e_get_wireless_stats
++*----------------------------------------------------------------*/
++static struct iw_statistics*
++acx_e_get_wireless_stats(netdevice_t *dev)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++      return &priv->wstats;
++}
++
++
++/*----------------------------------------------------------------
++* acx_i_set_multicast_list
++* FIXME: most likely needs refinement
++*----------------------------------------------------------------*/
++static void
++acx_i_set_multicast_list(netdevice_t *dev)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++      unsigned long flags;
++
++      FN_ENTER;
++
++      acx_lock(priv, flags);
++
++      /* firmwares don't have allmulti capability,
++       * so just use promiscuous mode instead in this case. */
++      if (dev->flags & (IFF_PROMISC|IFF_ALLMULTI)) {
++              SET_BIT(priv->rx_config_1, RX_CFG1_RCV_PROMISCUOUS);
++              CLEAR_BIT(priv->rx_config_1, RX_CFG1_FILTER_ALL_MULTI);
++              SET_BIT(priv->set_mask, SET_RXCONFIG);
++              /* let kernel know in case *we* needed to set promiscuous */
++              dev->flags |= (IFF_PROMISC|IFF_ALLMULTI);
++      } else {
++              CLEAR_BIT(priv->rx_config_1, RX_CFG1_RCV_PROMISCUOUS);
++              SET_BIT(priv->rx_config_1, RX_CFG1_FILTER_ALL_MULTI);
++              SET_BIT(priv->set_mask, SET_RXCONFIG);
++              dev->flags &= ~(IFF_PROMISC|IFF_ALLMULTI);
++      }
++
++      /* cannot update card settings directly here, atomic context */
++      acx_schedule_after_interrupt_task(priv, ACX_AFTER_IRQ_UPDATE_CARD_CFG);
++
++      acx_unlock(priv, flags);
++
++      FN_EXIT0;
++}
++
++static void
++acx_l_update_link_quality_led(wlandevice_t *priv)
++{
++      int qual;
++
++      qual = acx_signal_determine_quality(priv->wstats.qual.level, priv->wstats.qual.noise);
++      if (qual > priv->brange_max_quality)
++              qual = priv->brange_max_quality;
++
++      if (time_after(jiffies, priv->brange_time_last_state_change +
++                              (HZ/2 - HZ/2 * (unsigned long) qual/priv->brange_max_quality ) )) {
++              acx_l_power_led(priv, (priv->brange_last_state == 0));
++              priv->brange_last_state ^= 1; /* toggle */
++              priv->brange_time_last_state_change = jiffies;
++      }
++}
++
++
++/*----------------------------------------------------------------
++* acx_l_enable_irq
++*----------------------------------------------------------------*/
++static void
++acx_l_enable_irq(wlandevice_t *priv)
++{
++      FN_ENTER;
++      acx_write_reg16(priv, IO_ACX_IRQ_MASK, priv->irq_mask);
++      acx_write_reg16(priv, IO_ACX_FEMR, 0x8000);
++      priv->irqs_active = 1;
++      FN_EXIT0;
++}
++
++
++/*----------------------------------------------------------------
++* acx_l_disable_irq
++*----------------------------------------------------------------*/
++static void
++acx_l_disable_irq(wlandevice_t *priv)
++{
++      FN_ENTER;
++      acx_write_reg16(priv, IO_ACX_IRQ_MASK, priv->irq_mask_off);
++      acx_write_reg16(priv, IO_ACX_FEMR, 0x0);
++      priv->irqs_active = 0;
++      FN_EXIT0;
++}
++
++/* 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
++
++static void
++acx_l_handle_info_irq(wlandevice_t *priv)
++{
++#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
++      acx_read_info_status(priv);
++      acxlog(L_IRQ, "got Info IRQ: status 0x%04X type 0x%04X: %s\n",
++              priv->info_status, priv->info_type,
++              info_type_msg[(priv->info_type >= VEC_SIZE(info_type_msg)) ?
++                              0 : priv->info_type]
++      );
++}
++
++
++/*----------------------------------------------------------------
++* acx_i_interrupt
++*
++* IRQ handler (atomic context, must not sleep, blah, blah)
++*----------------------------------------------------------------*/
++static void
++acx_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) {
++              acxlog(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");
++      }
++              /* 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 irqreturn_t
++acx_i_interrupt(int irq, void *dev_id, struct pt_regs *regs)
++{
++      wlandevice_t *priv;
++      unsigned long flags;
++      unsigned int irqcount = MAX_IRQLOOPS_PER_JIFFY;
++      u16 irqtype, unmasked;
++
++      priv = (wlandevice_t *) (((netdevice_t *) dev_id)->priv);
++
++      /* LOCKING: can just spin_lock() since IRQs are disabled anyway.
++       * I am paranoid */
++      acx_lock(priv, flags);
++
++      unmasked = acx_read_reg16(priv, IO_ACX_IRQ_STATUS_CLEAR);
++      if (unlikely(0xffff == unmasked)) {
++              /* 0xffff value hints at missing hardware,
++               * so don't do anything.
++               * FIXME: that's not very clean - maybe we are able to
++               * establish a flag which definitely tells us that some
++               * hardware is absent and which we could check here?
++               * Hmm, but other drivers do the very same thing... */
++              acxlog(L_IRQ, "IRQ type:FFFF - device removed? IRQ_NONE\n");
++              goto none;
++      }
++
++      /* We will check only "interesting" IRQ types */
++      irqtype = unmasked & ~priv->irq_mask;
++      if (!irqtype) {
++              /* We are on a shared IRQ line and it wasn't our IRQ */
++              acxlog(L_IRQ, "IRQ type:%04X, mask:%04X - all are masked, IRQ_NONE\n",
++                      unmasked, priv->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 != priv->irq_last_jiffies) {
++      priv->irq_loops_this_jiffy = 0;
++      priv->irq_last_jiffies = jiffies;
++}
++
++/* safety condition; we'll normally abort loop below
++ * in case no IRQ type occurred */
++while (--irqcount) {
++#endif
++      /* ACK all IRQs asap */
++      acx_write_reg16(priv, IO_ACX_IRQ_ACK, 0xffff);
++
++      acxlog(L_IRQ, "IRQ type:%04X, mask:%04X, type & ~mask:%04X\n",
++                              unmasked, priv->irq_mask, irqtype);
++
++      /* Handle most important IRQ types first */
++      if (irqtype & HOST_INT_RX_COMPLETE) {
++              acxlog(L_IRQ, "got Rx_Complete IRQ\n");
++              acx_l_process_rx_desc(priv);
++      }
++      if (irqtype & HOST_INT_TX_COMPLETE) {
++              acxlog(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
++               * acx_l_clean_tx_desc() at a time when we won't wakeup
++               * the net queue in there for some reason...) */
++              if (priv->tx_free <= TX_START_CLEAN) {
++#if TX_CLEANUP_IN_SOFTIRQ
++                      acx_schedule_after_interrupt_task(priv, ACX_AFTER_IRQ_TX_CLEANUP);
++#else
++                      acx_l_clean_tx_desc(priv);
++#endif
++              }
++      }
++
++      /* Less frequent ones */
++      if (irqtype & (0
++              | HOST_INT_CMD_COMPLETE
++              | HOST_INT_INFO
++              | HOST_INT_SCAN_COMPLETE
++      )) {
++              if (irqtype & HOST_INT_CMD_COMPLETE) {
++                      acxlog(L_IRQ, "got Command_Complete IRQ\n");
++                      /* save the state for the running issue_cmd() */
++                      SET_BIT(priv->irq_status, HOST_INT_CMD_COMPLETE);
++              }
++              if (irqtype & HOST_INT_INFO) {
++                      acx_l_handle_info_irq(priv);
++              }
++              if (irqtype & HOST_INT_SCAN_COMPLETE) {
++                      acxlog(L_IRQ, "got Scan_Complete IRQ\n");
++                      /* need to do that in process context */
++                      acx_schedule_after_interrupt_task(priv, ACX_AFTER_IRQ_COMPLETE_SCAN);
++                      /* remember that fw is not scanning anymore */
++                      SET_BIT(priv->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
++      )) {
++              acx_log_unusual_irq(irqtype);
++      }
++
++#if IRQ_ITERATE
++      unmasked = acx_read_reg16(priv, IO_ACX_IRQ_STATUS_CLEAR);
++      irqtype = unmasked & ~priv->irq_mask;
++      /* Bail out if no new IRQ bits or if all are masked out */
++      if (!irqtype)
++              break;
++
++      if (unlikely(++priv->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 */
++              acx_write_reg16(priv, IO_ACX_IRQ_MASK, 0xffff);
++              /* This will short-circuit all future attempts to handle IRQ.
++               * We cant do much more... */
++              priv->irq_mask = 0;
++              break;
++      }
++}
++#endif
++      /* Routine to perform blink with range */
++      if (unlikely(priv->led_power == 2))
++              acx_l_update_link_quality_led(priv);
++
++/* handled: */
++      /* acx_write_flush(priv); - not needed, last op was read anyway */
++      acx_unlock(priv, flags);
++      FN_EXIT0;
++      return IRQ_HANDLED;
++
++none:
++      acx_unlock(priv, flags);
++      return IRQ_NONE;
++}
++
++
++/*----------------------------------------------------------------
++* acx_l_power_led
++*----------------------------------------------------------------*/
++void
++acx_l_power_led(wlandevice_t *priv, int enable)
++{
++      u16 gpio_pled = IS_ACX111(priv) ? 0x0040 : 0x0800;
++
++      /* A hack. Not moving message rate limiting to priv->xxx
++       * (it's only a debug message after all) */
++      static int rate_limit = 0;
++
++      if (rate_limit++ < 3)
++              acxlog(L_IOCTL, "Please report in case toggling the power "
++                              "LED doesn't work for your card!\n");
++      if (enable)
++              acx_write_reg16(priv, IO_ACX_GPIO_OUT,
++                      acx_read_reg16(priv, IO_ACX_GPIO_OUT) & ~gpio_pled);
++      else
++              acx_write_reg16(priv, IO_ACX_GPIO_OUT,
++                      acx_read_reg16(priv, IO_ACX_GPIO_OUT) | gpio_pled);
++}
++
++
++/***********************************************************************
++** Ioctls
++*/
++
++/***********************************************************************
++*/
++int
++acx111pci_ioctl_info(
++      struct net_device *dev,
++      struct iw_request_info *info,
++      struct iw_param *vwrq,
++      char *extra)
++{
++#if ACX_DEBUG
++      wlandevice_t *priv = netdev_priv(dev);
++      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(priv);
++
++      if (!IS_ACX111(priv)) {
++              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(priv, &memconf, ACX1xx_IE_QUEUE_CONFIG);
++
++      /* get Acx111 Queue Configuration */
++      memset(&queueconf, 0, sizeof(queueconf));
++      acx_s_interrogate(priv, &queueconf, ACX1xx_IE_MEMORY_CONFIG_OPTIONS);
++
++      /* get Acx111 Memory Map */
++      memset(memmap, 0, sizeof(memmap));
++      acx_s_interrogate(priv, &memmap, ACX1xx_IE_MEMORY_MAP);
++
++      /* get Acx111 Rx Config */
++      memset(rxconfig, 0, sizeof(rxconfig));
++      acx_s_interrogate(priv, &rxconfig, ACX1xx_IE_RXCONFIG);
++
++      /* get Acx111 fcs error count */
++      memset(fcserror, 0, sizeof(fcserror));
++      acx_s_interrogate(priv, &fcserror, ACX1xx_IE_FCS_ERROR_COUNT);
++
++      /* get Acx111 rate fallback */
++      memset(ratefallback, 0, sizeof(ratefallback));
++      acx_s_interrogate(priv, &ratefallback, ACX1xx_IE_RATE_FALLBACK);
++
++      /* force occurrence of a beacon interrupt */
++      /* TODO: comment why is this necessary */
++      acx_write_reg16(priv, 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]),
++              priv->iobase,
++              priv->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(priv, flags);
++
++      /* dump acx111 internal rx descriptor ring buffer */
++      rxdesc = priv->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 = priv->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 = priv->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 = move_txdesc(priv, txdesc, 1);
++      }
++
++      /* dump host tx descriptor ring buffer */
++
++      txhostdesc = priv->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++;
++      }
++
++      /* acx_write_reg16(priv, 0xb4, 0x4); */
++
++      acx_unlock(priv, flags);
++end_ok:
++
++      acx_sem_unlock(priv);
++#endif /* ACX_DEBUG */
++      return OK;
++}
++
++
++/***********************************************************************
++*/
++int
++acx100pci_ioctl_set_phy_amp_bias(
++      struct net_device *dev,
++      struct iw_request_info *info,
++      struct iw_param *vwrq,
++      char *extra)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++      unsigned long flags;
++      u16 gpio_old;
++
++      if (!IS_ACX100(priv)) {
++              /* 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(priv);
++
++      /* Need to lock accesses to [IO_ACX_GPIO_OUT]:
++       * IRQ handler uses it to update LED */
++      acx_lock(priv, flags);
++      gpio_old = acx_read_reg16(priv, IO_ACX_GPIO_OUT);
++      acx_write_reg16(priv, IO_ACX_GPIO_OUT, (gpio_old & 0xf8ff) | ((u16)*extra << 8));
++      acx_unlock(priv, flags);
++
++      acxlog(L_DEBUG, "gpio_old: 0x%04X\n", gpio_old);
++      printk("%s: PHY power amplifier bias: old:%d, new:%d\n",
++              dev->name,
++              (gpio_old & 0x0700) >> 8, (unsigned char)*extra);
++
++      acx_sem_unlock(priv);
++
++      return OK;
++}
++
++
++/***************************************************************
++** acxpci_l_alloc_tx
++** Actually returns a txdesc_t* ptr
++*/
++tx_t*
++acxpci_l_alloc_tx(wlandevice_t* priv)
++{
++      struct txdesc *txdesc;
++      u8 ctl8;
++
++      FN_ENTER;
++
++      txdesc = get_txdesc(priv, priv->tx_head);
++      ctl8 = txdesc->Ctl_8;
++      if (unlikely(DESC_CTL_HOSTOWN != (ctl8 & DESC_CTL_DONE))) {
++              /* whoops, descr at current index is not free, so probably
++               * ring buffer already full */
++              /* FIXME: this causes a deadlock situation (endless
++               * loop) in case the current descriptor remains busy,
++               * so handle it a bit better in the future!! */
++              printk("acx: BUG: tx_head->Ctl8=0x%02X, (0x%02X & "
++                      "0x"DESC_CTL_DONE_STR") != 0x"DESC_CTL_HOSTOWN_STR
++                      ": failed to find free tx descr\n",
++                      ctl8, ctl8);
++              txdesc = NULL;
++              goto end;
++      }
++
++      priv->tx_free--;
++      acxlog(L_BUFT, "tx: got desc %u, %u remain\n",
++                      priv->tx_head, priv->tx_free);
++
++/*
++ * This comment is probably not entirely correct, needs further discussion
++ * (restored commented-out code below to fix Tx ring buffer overflow,
++ * since it's much better to have a slightly less efficiently used ring
++ * buffer rather than one which easily overflows):
++ *
++ * This doesn't do anything other than limit our maximum number of
++ * buffers used at a single time (we might as well just declare
++ * TX_STOP_QUEUE less descriptors when we open up.) We should just let it
++ * slide here, and back off TX_STOP_QUEUE in acx_l_clean_tx_desc, when given the
++ * opportunity to let the queue start back up.
++ */
++      if (priv->tx_free < TX_STOP_QUEUE) {
++              acxlog(L_BUF, "stop queue (%u tx desc left)\n",
++                              priv->tx_free);
++              acx_stop_queue(priv->netdev, NULL);
++      }
++
++      /* returning current descriptor, so advance to next free one */
++      priv->tx_head = (priv->tx_head + 1) % TX_CNT;
++end:
++      FN_EXIT0;
++
++      return (tx_t*)txdesc;
++}
++
++
++/***********************************************************************
++*/
++void*
++acxpci_l_get_txbuf(wlandevice_t *priv, tx_t* tx_opaque)
++{
++      return acx_get_txhostdesc(priv, (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).
++*/
++void
++acxpci_l_tx_data(wlandevice_t *priv, tx_t* tx_opaque, int len)
++{
++      txdesc_t *txdesc = (txdesc_t*)tx_opaque;
++      txhostdesc_t *hostdesc1, *hostdesc2;
++      client_t *clt;
++      u8 Ctl_8, Ctl2_8;
++
++      FN_ENTER;
++
++      /* fw doesn't tx such packets anyhow */
++      if (len < WLAN_HDR_A3_LEN)
++              goto end;
++
++      hostdesc1 = acx_get_txhostdesc(priv, txdesc);
++      hostdesc2 = hostdesc1 + 1;
++
++      /* 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 = txdesc->Ctl2_8;
++
++      /* 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...
++       * FIXME: what about Ctl2? Equally problematic? */
++
++      /* let chip do RTS/CTS handshaking before sending
++       * in case packet size exceeds threshold */
++      if (len > priv->rts_threshold)
++              SET_BIT(Ctl2_8, DESC_CTL2_RTS);
++      else
++              CLEAR_BIT(Ctl2_8, DESC_CTL2_RTS);
++
++#ifdef DEBUG_WEP
++      if (priv->wep_enabled)
++              SET_BIT(Ctl2_8, DESC_CTL2_WEP);
++      else
++              CLEAR_BIT(Ctl2_8, DESC_CTL2_WEP);
++#endif
++
++      switch (priv->mode) {
++      case ACX_MODE_0_ADHOC:
++      case ACX_MODE_3_AP:
++              clt = acx_l_sta_list_get(priv, ((wlan_hdr_t*)hostdesc1->data)->a1);
++              break;
++      case ACX_MODE_2_STA:
++              clt = priv->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;
++      }
++
++      if (unlikely(clt && !clt->rate_cur)) {
++              printk("acx: driver bug! bad ratemask\n");
++              goto end;
++      }
++
++      /* used in tx cleanup routine for auto rate and accounting: */
++      acx_put_txc(priv, txdesc, clt);
++
++      txdesc->total_length = cpu_to_le16(len);
++      hostdesc2->length = cpu_to_le16(len - WLAN_HDR_A3_LEN);
++      if (IS_ACX111(priv)) {
++              u16 rate_cur = clt ? clt->rate_cur : priv->rate_bcast;
++              /* 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 : priv->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);
++              hostdesc1->length = cpu_to_le16(WLAN_HDR_A3_LEN);
++      }
++      /* don't need to clean ack/rts statistics here, already
++       * done on descr cleanup */
++
++      /* clears Ctl DESC_CTL_HOSTOWN bit, thus telling that the descriptors
++       * are now owned by the acx100; do this as LAST operation */
++      CLEAR_BIT(Ctl_8, DESC_CTL_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); */
++//TODO: should it be a mmiowb() instead? we are protecting against race with write[bwl]()
++      /* flush writes before we tell the adapter that it's its turn now */
++      wmb(); 
++      acx_write_reg16(priv, IO_ACX_INT_TRIG, INT_TRIG_TXPRC);
++      acx_write_flush(priv);
++
++      /* 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(priv))
++                      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)" : "",
++                              priv->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)" : "",
++                              priv->status);
++
++              if (acx_debug & L_DATA) {
++                      printk("tx: 802.11 [%d]: ", len);
++                      acx_dump_bytes(hostdesc1->data, len);
++              }
++      }
++end:
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++*/
++static void
++acx_l_handle_tx_error(wlandevice_t *priv, 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";
++              priv->wstats.discard.fragment++;
++              break;
++      case 0x02:
++              err = "Tx aborted";
++              priv->stats.tx_aborted_errors++;
++              break;
++      case 0x04:
++              err = "Tx desc wrong parameters";
++              priv->wstats.discard.misc++;
++              break;
++      case 0x08:
++              err = "WEP key not found";
++              priv->wstats.discard.misc++;
++              break;
++      case 0x10:
++              err = "MSDU lifetime timeout? - try changing "
++                              "'iwconfig retry lifetime XXX'";
++              priv->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'";
++              priv->wstats.discard.retries++;
++              /* FIXME: set (GETSET_TX|GETSET_RX) here
++               * (this seems to recalib radio on ACX100)
++               * after some more jiffies passed??
++               * But OTOH Tx error 0x20 also seems to occur on
++               * overheating, so I'm not sure whether we
++               * actually want that, 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.
++               * ENABLE_TX|ENABLE_RX helps, so even do
++               * DISABLE_TX and DISABLE_RX in order to perhaps
++               * have more impact. */
++              if (++priv->retry_errors_msg_ratelimit % 4 == 0) {
++                      if (priv->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",
++                                      priv->netdev->name);
++                      if (priv->retry_errors_msg_ratelimit == 20)
++                              printk("disabling above "
++                                      "notification message\n");
++
++                      acx_schedule_after_interrupt_task(priv, ACX_AFTER_IRQ_CMD_RADIO_RECALIB);
++              }
++              break;
++      case 0x40:
++              err = "Tx buffer overflow";
++              priv->stats.tx_fifo_errors++;
++              break;
++      case 0x80:
++              err = "DMA error";
++              priv->wstats.discard.misc++;
++              break;
++      }
++      priv->stats.tx_errors++;
++      if (priv->stats.tx_errors <= 20)
++              printk("%s: tx error 0x%02X, buf %02u! (%s)\n",
++                              priv->netdev->name, error, finger, err);
++      else
++              printk("%s: tx error 0x%02X, buf %02u!\n",
++                              priv->netdev->name, error, finger);
++}
++
++
++/***********************************************************************
++*/
++/* 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_2;
++      }
++}
++
++
++static void
++acx_l_handle_txrate_auto(wlandevice_t *priv, struct client *txc,
++                      unsigned int idx, u8 rate100, u16 rate111, u8 error)
++{
++      u16 sent_rate;
++      u16 cur = txc->rate_cur;
++      int slower_rate_was_used;
++
++      /* FIXME: need to implement some kind of rate success memory
++       * which stores the success percentage per rate, to be taken
++       * into account when considering allowing a new rate, since it
++       * doesn't really help to stupidly count fallback/stepup,
++       * since one invalid rate will spoil the party anyway
++       * (such as 22M in case of 11M-only peers) */
++
++      /* 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 */
++
++      /* do some preparations, i.e. calculate the one rate that was
++       * used to send this packet */
++      if (IS_ACX111(priv)) {
++              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 */
++      acxlog(L_DEBUG, "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, priv->fallback_threshold,
++              txc->stepup_count, priv->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 here only, in order to have the 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 & 0x30)) {
++              txc->stepup_count = 0;
++              if (++txc->fallback_count <= priv->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! */
++                      acxlog(L_XFER, "tx: falling back to ratemask %04X\n", cur);
++                      txc->rate_cur = cur;
++                      txc->ignore_count = TX_CNT - priv->tx_free;
++              }
++      } else if (!slower_rate_was_used) {
++              txc->fallback_count = 0;
++              if (++txc->stepup_count <= priv->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);
++              acxlog(L_XFER, "tx: stepping up to ratemask %04X\n", cur);
++              txc->rate_cur = cur;
++              /* FIXME: totally bogus - we could be sending to many peers at once... */
++              txc->ignore_count = TX_CNT - priv->tx_free;
++      }
++
++      /* calculate acx100 style rate byte if needed */
++      if (IS_ACX100(priv)) {
++              txc->rate_100 = bitpos2rate100[highest_bit(cur)];
++      }
++}
++
++
++/*----------------------------------------------------------------
++* acx_l_log_txbuffer
++*----------------------------------------------------------------*/
++#if !ACX_DEBUG
++static inline void acx_l_log_txbuffer(const wlandevice_t *priv) {}
++#else
++static void
++acx_l_log_txbuffer(wlandevice_t *priv)
++{
++      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 = priv->txdesc_start;
++      if (!txdesc) return;
++      for (i = 0; i < TX_CNT; i++) {
++              if ((txdesc->Ctl_8 & DESC_CTL_DONE) == DESC_CTL_DONE)
++                      printk("tx: buf %d done\n", i);
++              txdesc = move_txdesc(priv, txdesc, 1);
++      }
++}
++#endif
++
++
++/*----------------------------------------------------------------
++* acx_l_clean_tx_desc
++*
++* 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.
++* Oops, now we have our own index, so everytime we get called we know
++* where the next packet to be cleaned is.
++* Hmm, still need to loop through the whole ring buffer now,
++* since we lost sync for some reason when ping flooding or so...
++* (somehow we don't get the IRQ for acx_l_clean_tx_desc any more when
++* too many packets are being sent!)
++* FIXME: currently we only process one packet, but this gets out of
++* sync for some reason when ping flooding, so we need to loop,
++* but the previous smart loop implementation causes the ping latency
++* to rise dramatically (~3000 ms), at least on CardBus PheeNet WL-0022.
++* Dunno what to do :-\
++*----------------------------------------------------------------*/
++unsigned int
++acx_l_clean_tx_desc(wlandevice_t *priv)
++{
++      txdesc_t *txdesc;
++      struct client *txc;
++      int finger;
++      int num_cleaned;
++      int to_process;
++      u16 r111;
++      u8 error, ack_failures, rts_failures, rts_ok, r100;
++
++      FN_ENTER;
++
++      if (unlikely(acx_debug & L_DEBUG))
++              acx_l_log_txbuffer(priv);
++
++      acxlog(L_BUFT, "tx: cleaning up bufs from %u\n", priv->tx_tail);
++
++      finger = priv->tx_tail;
++      num_cleaned = 0;
++      to_process = TX_CNT;
++      do {
++              txdesc = get_txdesc(priv, finger);
++
++              /* abort if txdesc is not marked as "Tx finished" and "owned" */
++              if ((txdesc->Ctl_8 & DESC_CTL_DONE) != DESC_CTL_DONE) {
++                      /* we do need to have at least one cleaned,
++                       * otherwise we wouldn't get called in the first place
++                       */
++                      if (num_cleaned)
++                              break;
++              }
++
++              /* remember descr 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 = txdesc->u.r2.rate111;
++
++#if WIRELESS_EXT > 13 /* wireless_send_event() and IWEVTXDROP are WE13 */
++              /* 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 = acx_get_txhostdesc(priv, txdesc);
++                      hdr = (wlan_hdr_t *)hostdesc->data;
++                      MAC_COPY(wrqu.addr.sa_data, hdr->a1);
++                      wireless_send_event(priv->netdev, IWEVTXDROP, &wrqu, NULL);
++              }
++#endif
++              /* ...and free the descr */
++              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:
++               * if _OWN is set at the beginning instead, our own get_tx
++               * might choose a Tx desc that isn't fully cleared
++               * (in case of bad locking). */
++              txdesc->Ctl_8 = DESC_CTL_HOSTOWN;
++              priv->tx_free++;
++              num_cleaned++;
++
++              if ((priv->tx_free >= TX_START_QUEUE)
++              && (priv->status == ACX_STATUS_4_ASSOCIATED)
++              && (acx_queue_stopped(priv->netdev))
++              ) {
++                      acxlog(L_BUF, "tx: wake queue (avail. Tx desc %u)\n",
++                                      priv->tx_free);
++                      acx_wake_queue(priv->netdev, NULL);
++              }
++
++              /* do error checking, rate handling and logging
++               * AFTER having done the work, it's faster */
++
++              /* do rate handling */
++              txc = acx_get_txc(priv, txdesc);
++              if (txc && priv->rate_auto) {
++                      acx_l_handle_txrate_auto(priv, txc, finger, r100, r111, error);
++              }
++
++              if (unlikely(error))
++                      acx_l_handle_tx_error(priv, error, finger);
++
++              if (IS_ACX111(priv))
++                      acxlog(L_BUFT, "tx: cleaned %u: !ACK=%u !RTS=%u RTS=%u r111=%04X\n",
++                              finger, ack_failures, rts_failures, rts_ok, r111);
++              else
++                      acxlog(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;
++      } while (--to_process);
++
++      /* remember last position */
++      priv->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
++acx_l_clean_tx_desc_emergency(wlandevice_t *priv)
++{
++      txdesc_t *txdesc;
++      unsigned int i;
++
++      FN_ENTER;
++
++      for (i = 0; i < TX_CNT; i++) {
++              txdesc = get_txdesc(priv, i);
++
++              /* free it */
++              txdesc->ack_failures = 0;
++              txdesc->rts_failures = 0;
++              txdesc->rts_ok = 0;
++              txdesc->error = 0;
++              txdesc->Ctl_8 = DESC_CTL_HOSTOWN;
++      }
++
++      priv->tx_free = TX_CNT;
++
++      FN_EXIT0;
++}
++
++
++/*----------------------------------------------------------------
++* acx_l_log_rxbuffer
++*
++* Called from IRQ context only
++*----------------------------------------------------------------*/
++#if !ACX_DEBUG
++static inline void acx_l_log_rxbuffer(const wlandevice_t *priv) {}
++#else
++static void
++acx_l_log_rxbuffer(const wlandevice_t *priv)
++{
++      const struct rxhostdesc *rxhostdesc;
++      int i;
++
++      /* no FN_ENTER here, we don't want that */
++
++      rxhostdesc = priv->rxhostdesc_start;
++      if (!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
++
++
++/***************************************************************
++** acx_l_process_rx_desc
++**
++** Called directly and only from the IRQ handler
++*/
++void
++acx_l_process_rx_desc(wlandevice_t *priv)
++{
++      rxhostdesc_t *hostdesc;
++      /* unsigned int curr_idx; */
++      unsigned int count = 0;
++
++      FN_ENTER;
++
++      if (unlikely(acx_debug & L_BUFR)) {
++              acx_l_log_rxbuffer(priv);
++      }
++
++      /* 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. */
++      while (1) {
++              /* curr_idx = priv->rx_tail; */
++              hostdesc = &priv->rxhostdesc_start[priv->rx_tail];
++              priv->rx_tail = (priv->rx_tail + 1) % RX_CNT;
++              if ((hostdesc->Ctl_16 & cpu_to_le16(DESC_CTL_HOSTOWN))
++               && (hostdesc->Status & cpu_to_le32(DESC_STATUS_FULL))) {
++                      /* found it! */
++                      break;
++              }
++              count++;
++              if (unlikely(count > RX_CNT)) {
++                      /* hmm, no luck: all descriptors empty, bail out */
++                      goto end;
++              }
++      }
++
++      /* now process descriptors, starting with the first we figured out */
++      while (1) {
++              acxlog(L_BUFR, "rx: tail=%u Ctl_16=%04X Status=%08X\n",
++                      priv->rx_tail, hostdesc->Ctl_16, hostdesc->Status);
++
++              acx_l_process_rxbuf(priv, 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 */
++              /* curr_idx = priv->rx_tail; */
++              hostdesc = &priv->rxhostdesc_start[priv->rx_tail];
++
++              /* if next descriptor is empty, then bail out */
++              /* FIXME: is this check really entirely correct?? */
++              /*
++//FIXME: inconsistent with check in prev while() loop
++              if (!(hostdesc->Ctl & cpu_to_le16(DESC_CTL_HOSTOWN))
++               && !(hostdesc->Status & cpu_to_le32(DESC_STATUS_FULL))) */
++              if (!(hostdesc->Status & cpu_to_le32(DESC_STATUS_FULL)))
++                      break;
++
++              priv->rx_tail = (priv->rx_tail + 1) % RX_CNT;
++      }
++end:
++      FN_EXIT0;
++}
++
++
++/*----------------------------------------------------------------
++* acx_s_create_tx_host_desc_queue
++*----------------------------------------------------------------*/
++static inline void*
++acx_alloc_coherent(struct device *dev, size_t size,
++                      dma_addr_t *dma_handle, int flag)
++{
++      printk("Size : %ld\n",size);
++      dev->coherent_dma_mask      = 0xffffffff;
++      return dma_alloc_coherent(dev, size, dma_handle, flag);
++}
++
++static void*
++allocate(wlandevice_t *priv, size_t size, dma_addr_t *phy, const char *msg)
++{
++      void *ptr = acx_alloc_coherent(priv->dev, size, phy, GFP_KERNEL);
++      if (ptr) {
++              acxlog(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
++acx_s_create_tx_host_desc_queue(wlandevice_t *priv)
++{
++      txhostdesc_t *hostdesc;
++      u8 *txbuf;
++      dma_addr_t hostdesc_phy;
++      dma_addr_t txbuf_phy;
++      int i;
++
++      FN_ENTER;
++
++      /* allocate TX buffer */
++      priv->txbuf_area_size = TX_CNT * WLAN_A4FR_MAXLEN_WEP_FCS;
++      priv->txbuf_start = allocate(priv, priv->txbuf_area_size,
++                      &priv->txbuf_startphy, "txbuf_start");
++      if (!priv->txbuf_start)
++              goto fail;
++
++      /* allocate the TX host descriptor queue pool */
++      priv->txhostdesc_area_size = TX_CNT * 2*sizeof(txhostdesc_t);
++      priv->txhostdesc_start = allocate(priv, priv->txhostdesc_area_size,
++                      &priv->txhostdesc_startphy, "txhostdesc_start");
++      if (!priv->txhostdesc_start)
++              goto fail;
++      /* check for proper alignment of TX host descriptor pool */
++      if ((long) priv->txhostdesc_start & 3) {
++              printk("acx: driver bug: dma alloc returns unaligned address\n");
++              goto fail;
++      }
++
++/* Each tx frame buffer is accessed by hardware via
++** txdesc -> txhostdesc(s) -> framebuffer(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 hostdesc.length = 3 (or larger)
++** Storing NULL into hostdesc.desc_phy_next
++** doesn't seem to help.
++*/
++/* It is not known whether we need to have 'extra' second
++** txhostdescs for acx100. Maybe it is acx111-only bug.
++*/
++      hostdesc = priv->txhostdesc_start;
++      hostdesc_phy = priv->txhostdesc_startphy;
++      txbuf = priv->txbuf_start;
++      txbuf_phy = priv->txbuf_startphy;
++
++      for (i = 0; i < TX_CNT*2; i++) {
++              hostdesc_phy += sizeof(txhostdesc_t);
++              if (!(i & 1)) {
++                      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 = ... */
++                      /* below: non-hardware fields */
++                      hostdesc->data = txbuf;
++
++                      txbuf += WLAN_HDR_A3_LEN;
++                      txbuf_phy += WLAN_HDR_A3_LEN;
++              } else {
++                      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 = ... */
++                      /* below: non-hardware fields */
++                      hostdesc->data = txbuf;
++
++                      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(priv->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;
++}
++
++
++/***************************************************************
++** acx_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
++acx_s_create_rx_host_desc_queue(wlandevice_t *priv)
++{
++      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 */
++      priv->rxhostdesc_area_size = RX_CNT * sizeof(rxhostdesc_t);
++      priv->rxhostdesc_start = allocate(priv, priv->rxhostdesc_area_size,
++                      &priv->rxhostdesc_startphy, "rxhostdesc_start");
++      if (!priv->rxhostdesc_start)
++              goto fail;
++      /* check for proper alignment of RX host descriptor pool */
++      if ((long) priv->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 */
++      priv->rxbuf_area_size = RX_CNT * RX_BUFFER_SIZE;
++      priv->rxbuf_start = allocate(priv, priv->rxbuf_area_size,
++                      &priv->rxbuf_startphy, "rxbuf_start");
++      if (!priv->rxbuf_start)
++              goto fail;
++
++      rxbuf = priv->rxbuf_start;
++      rxbuf_phy = priv->rxbuf_startphy;
++      hostdesc = priv->rxhostdesc_start;
++      hostdesc_phy = priv->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(rxbuffer_t);
++              hostdesc_phy += sizeof(rxhostdesc_t);
++              hostdesc->desc_phy_next = cpu2acx(hostdesc_phy);
++              hostdesc++;
++      }
++      hostdesc--;
++      hostdesc->desc_phy_next = cpu2acx(priv->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;
++}
++
++
++/***************************************************************
++** acx_s_create_hostdesc_queues
++*/
++int
++acx_s_create_hostdesc_queues(wlandevice_t *priv)
++{
++      int result;
++      result = acx_s_create_tx_host_desc_queue(priv);
++      if (OK != result) return result;
++      result = acx_s_create_rx_host_desc_queue(priv);
++      return result;
++}
++
++
++/***************************************************************
++** acx_create_tx_desc_queue
++*/
++static void
++acx_create_tx_desc_queue(wlandevice_t *priv, u32 tx_queue_start)
++{
++      txdesc_t *txdesc;
++      txhostdesc_t *hostdesc;
++      dma_addr_t hostmemptr;
++      u32 mem_offs;
++      int i;
++
++      FN_ENTER;
++
++      priv->txdesc_size = sizeof(txdesc_t);
++
++      if (IS_ACX111(priv)) {
++              /* the acx111 txdesc is 4 bytes larger */
++              priv->txdesc_size = sizeof(txdesc_t) + 4;
++      }
++
++#if 0
++      priv->txdesc_start = (txdesc_t *) (priv->iobase2 + tx_queue_start);
++
++      acxlog(L_DEBUG, "priv->iobase2=%p\n"
++                      "tx_queue_start=%08X\n"
++                      "priv->txdesc_start=%p\n",
++                      priv->iobase2,
++                      tx_queue_start,
++                      priv->txdesc_start);
++
++      priv->tx_free = TX_CNT;
++#endif
++      /* done by memset: priv->tx_head = 0; */
++      /* done by memset: priv->tx_tail = 0; */
++      txdesc     = priv->txdesc_start;
++      mem_offs   = tx_queue_start;
++      hostmemptr = priv->txhostdesc_startphy;
++      hostdesc   = priv->txhostdesc_start;
++
++#if 0
++      if (IS_ACX111(priv)) {
++              /* 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(txhostdesc_t);
++                      txdesc = move_txdesc(priv, txdesc, 1);
++              }
++      } else {
++              /* ACX100 Tx buffer needs to be initialized by us */
++              /* clear whole send pool. sizeof is safe here (we are acx100) */
++              memset(priv->txdesc_start, 0, TX_CNT * sizeof(txdesc_t));
++
++              /* loop over whole send pool */
++              for (i = 0; i < TX_CNT; i++) {
++                      acxlog(L_DEBUG, "configure card tx descriptor: 0x%p, "
++                              "size: 0x%X\n", txdesc, priv->txdesc_size);
++
++                      /* pointer to hostdesc memory */
++                      /* FIXME: type-incorrect assignment, might cause trouble
++                       * in some cases */
++                      txdesc->HostMemPtr = ptr2acx(hostmemptr);
++                      /* initialise ctl */
++                      txdesc->Ctl_8   = DESC_CTL_INIT;
++                      txdesc->Ctl2_8  = 0;
++                      /* point to next txdesc */
++                      txdesc->pNextDesc = cpu2acx(mem_offs + priv->txdesc_size);
++                      /* reserve two (hdr desc and payload desc) */
++                      hostdesc   += 2;
++                      hostmemptr += 2 * sizeof(txhostdesc_t);
++                      /* go to the next one */
++                      mem_offs   += priv->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);
++      }
++#endif
++      FN_EXIT0;
++}
++
++
++/***************************************************************
++** acx_create_rx_desc_queue
++*/
++static void
++acx_create_rx_desc_queue(wlandevice_t *priv, u32 rx_queue_start)
++{
++      rxdesc_t *rxdesc;
++      u32 mem_offs;
++      int i;
++
++      FN_ENTER;
++
++      /* done by memset: priv->rx_tail = 0; */
++
++      /* ACX111 doesn't need any further config: preconfigures itself.
++       * Simply print ring buffer for debugging */
++      if (IS_ACX111(priv)) {
++              /* rxdesc_start already set here */
++
++              priv->rxdesc_start = (rxdesc_t *) ((u8 *)priv->iobase2 + rx_queue_start);
++
++              rxdesc = priv->rxdesc_start;
++              for (i = 0; i < RX_CNT; i++) {
++                      acxlog(L_DEBUG, "rx descriptor %d @ 0x%p\n", i, rxdesc);
++                      rxdesc = priv->rxdesc_start = (rxdesc_t *)
++                              (priv->iobase2 + acx2cpu(rxdesc->pNextDesc));
++              }
++      } else {
++              /* we didn't pre-calculate rxdesc_start in case of ACX100 */
++              /* rxdesc_start should be right AFTER Tx pool */
++              priv->rxdesc_start = (rxdesc_t *)
++                      ((u8 *) priv->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(priv->rxdesc_start, 0, RX_CNT * sizeof(rxdesc_t));
++
++              /* loop over whole receive pool */
++              rxdesc = priv->rxdesc_start;
++              mem_offs = rx_queue_start;
++              for (i = 0; i < RX_CNT; i++) {
++                      acxlog(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_t));
++                      /* go to the next one */
++                      mem_offs += sizeof(rxdesc_t);
++                      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;
++}
++
++
++/***************************************************************
++** acx_create_desc_queues
++*/
++void
++acx_create_desc_queues(wlandevice_t *priv, u32 tx_queue_start, u32 rx_queue_start)
++{
++      acx_create_tx_desc_queue(priv, tx_queue_start);
++      acx_create_rx_desc_queue(priv, rx_queue_start);
++}
++
++
++/***************************************************************
++** acxpci_s_proc_diag_output
++*/
++char*
++acxpci_s_proc_diag_output(char *p, wlandevice_t *priv)
++{
++      const char *rtl, *thd, *ttl;
++      rxhostdesc_t *rxhostdesc;
++      txdesc_t *txdesc;
++      int i;
++
++      FN_ENTER;
++
++      p += sprintf(p, "** Rx buf **\n");
++      rxhostdesc = priv->rxhostdesc_start;
++      if (rxhostdesc) for (i = 0; i < RX_CNT; i++) {
++              rtl = (i == priv->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", priv->tx_free,
++                              acx_queue_stopped(priv->netdev) ? "STOPPED" : "running");
++      txdesc = priv->txdesc_start;
++      if (txdesc) for (i = 0; i < TX_CNT; i++) {
++              thd = (i == priv->tx_head) ? " [head]" : "";
++              ttl = (i == priv->tx_tail) ? " [tail]" : "";
++              if (txdesc->Ctl_8 & DESC_CTL_ACXDONE)
++                      p += sprintf(p, "%02u DONE   (%02X)%s%s\n", i, txdesc->Ctl_8, thd, ttl);
++              else
++              if (!(txdesc->Ctl_8 & DESC_CTL_HOSTOWN))
++                      p += sprintf(p, "%02u TxWait (%02X)%s%s\n", i, txdesc->Ctl_8, thd, ttl);
++              else
++                      p += sprintf(p, "%02u empty  (%02X)%s%s\n", i, txdesc->Ctl_8, thd, ttl);
++              txdesc = move_txdesc(priv, 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",
++              priv->txbuf_start, priv->txbuf_area_size, (u64)priv->txbuf_startphy,
++              priv->txdesc_size, priv->txdesc_start,
++              priv->txhostdesc_start, priv->txhostdesc_area_size, (u64)priv->txhostdesc_startphy,
++              priv->rxdesc_start,
++              priv->rxhostdesc_start, priv->rxhostdesc_area_size, (u64)priv->rxhostdesc_startphy,
++              priv->rxbuf_start, priv->rxbuf_area_size, (u64)priv->rxbuf_startphy);
++
++      FN_EXIT0;
++      return p;
++}
++
++
++/***********************************************************************
++*/
++int
++acx_proc_eeprom_output(char *buf, wlandevice_t *priv)
++{
++      char *p = buf;
++      int i;
++
++      FN_ENTER;
++
++      for (i = 0; i < 0x400; i++) {
++              acx_read_eeprom_offset(priv, i, p++);
++      }
++
++      FN_EXIT1(p - buf);
++      return p - buf;
++}
++
++
++/***********************************************************************
++*/
++void
++acx_set_interrupt_mask(wlandevice_t *priv)
++{
++      if (IS_ACX111(priv)) {
++              priv->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        */
++                              );
++              priv->irq_mask_off = (u16)~( HOST_INT_CMD_COMPLETE ); /* 0xfdff */
++      } else {
++              priv->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        */
++                              );
++              priv->irq_mask_off = (u16)~( HOST_INT_UNKNOWN ); /* 0x7fff */
++      }
++}
++
++
++/***********************************************************************
++*/
++int
++acx100_s_set_tx_level(wlandevice_t *priv, 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 (priv->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",
++                              priv->netdev->name);
++              return NOT_OK;
++      }
++      printk("%s: changing radio power level to %u dBm (%u)\n",
++                      priv->netdev->name, level_dbm, table[level_dbm]);
++      acxpci_s_write_phy_reg(priv, 0x11, table[level_dbm]);
++      return OK;
++}
++
++
++/*----------------------------------------------------------------
++* acx_e_init_module
++*
++* Module initialization routine, called once at module load time.
++*
++* Returns:
++*     0       - success
++*     ~0      - failure, module is unloaded.
++*
++* Call context:
++*     process thread (insmod or modprobe)
++----------------------------------------------------------------*/
++int __init
++acxcfi_e_init_module(void)
++{
++      int res;
++
++      FN_ENTER;
++
++      printk("acx: compiled to use 16bit I/O access only "
++              "(compatibility mode)\n");
++
++      acxlog(L_INIT, "running on a little-endian CPU\n");
++
++      acxlog(L_INIT, 
++             "Compact Flash module " WLAN_RELEASE " initialized, "
++              "waiting for cards to probe...\n");
++
++      /*
++         * Now let configure device
++         * GPIOs
++         */
++        pca9535_gpio_direction(GPIO6, GPIO_OUTPUT);
++        pca9535_gpio_direction(GPIO12, GPIO_OUTPUT);
++
++        if ((omap_request_gpio(11)) < 0) {
++                printk("Error requesting gpio 11\n");
++                return -EIO;
++        }
++      omap_set_gpio_direction (11, 1);
++        omap_set_gpio_dataout (11, 1);
++
++        res = driver_register(&acx_driver);
++
++      FN_EXIT1(res);
++      return res;
++}
++
++
++/*----------------------------------------------------------------
++* acx_cleanup_module
++*
++* Called at module unload time.  This is our last chance to
++* clean up after ourselves.
++*
++* Call context:
++*     process thread
++----------------------------------------------------------------*/
++void __exit
++acxcfi_e_cleanup_module(void)
++{
++      struct net_device *dev;
++      unsigned long flags;
++
++      FN_ENTER;
++
++      /* Since the whole module is about to be unloaded,
++       * we recursively shutdown all cards we handled instead
++       * of doing it in remove_pci() (which will be activated by us
++       * via pci_unregister_driver at the end).
++       * remove_pci() might just get called after a card eject,
++       * that's why hardware operations have to be done here instead
++       * when the hardware is available. */
++
++      down(&root_acx_dev_sem);
++
++      dev = root_acx_dev.newest;
++      while (dev != NULL) {
++              /* doh, netdev_priv() doesn't have const! */
++              wlandevice_t *priv = netdev_priv(dev);
++
++              acx_sem_lock(priv);
++
++              /* disable both Tx and Rx to shut radio down properly */
++              acx_s_issue_cmd(priv, ACX1xx_CMD_DISABLE_TX, NULL, 0);
++              acx_s_issue_cmd(priv, 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(priv, ACX100_CMD_SLEEP, NULL, 0);
++#endif
++              acx_lock(priv, flags);
++
++              /* disable power LED to save power :-) */
++              acxlog(L_INIT, "switching off power LED to save power :-)\n");
++              acx_l_power_led(priv, 0);
++
++              /* stop our eCPU */
++              if (IS_ACX111(priv)) {
++                      /* FIXME: does this actually keep halting the eCPU?
++                       * I don't think so...
++                       */
++                      acx_l_reset_mac(priv);
++              } else {
++                      u16 temp;
++
++                      /* halt eCPU */
++                      temp = acx_read_reg16(priv, IO_ACX_ECPU_CTRL) | 0x1;
++                      acx_write_reg16(priv, IO_ACX_ECPU_CTRL, temp);
++                      acx_write_flush(priv);
++              }
++
++              acx_unlock(priv, flags);
++
++              acx_sem_unlock(priv);
++
++              dev = priv->prev_nd;
++      }
++
++      up(&root_acx_dev_sem);
++
++      omap_free_gpio(11);
++        driver_unregister(&acx_driver);
++
++      FN_EXIT0;
++}
+diff -Naur linux-2.6.14-omap2/drivers/net/wireless/tiacx/common.c linux-h6300-omap2-2.6.14.3/drivers/net/wireless/tiacx/common.c
+--- linux-2.6.14-omap2/drivers/net/wireless/tiacx/common.c     1970-01-01 02:00:00.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/drivers/net/wireless/tiacx/common.c     2005-09-28 23:54:23.000000000 +0300
+@@ -0,0 +1,6590 @@
++/***********************************************************************
++** 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/config.h>
++#include <linux/version.h>
++#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 <asm/bug.h>
++#if WIRELESS_EXT >= 13
++#include <net/iw_handler.h>
++#endif /* WE >= 13 */
++
++#include "acx.h"
++
++
++#define rdtscl(a)
++
++/***********************************************************************
++*/
++static client_t *acx_l_sta_list_alloc(wlandevice_t *priv);
++static client_t *acx_l_sta_list_get_from_hash(wlandevice_t *priv, const u8 *address);
++
++static int acx_l_process_data_frame_master(wlandevice_t *priv, rxbuffer_t *rxbuf);
++static int acx_l_process_data_frame_client(wlandevice_t *priv, rxbuffer_t *rxbuf);
++/* static int acx_l_process_NULL_frame(wlandevice_t *priv, rxbuffer_t *rxbuf, int vala); */
++static int acx_l_process_mgmt_frame(wlandevice_t *priv, rxbuffer_t *rxbuf);
++static void acx_l_process_disassoc_from_sta(wlandevice_t *priv, const wlan_fr_disassoc_t *req);
++static void acx_l_process_disassoc_from_ap(wlandevice_t *priv, const wlan_fr_disassoc_t *req);
++static void acx_l_process_deauth_from_sta(wlandevice_t *priv, const wlan_fr_deauthen_t *req);
++static void acx_l_process_deauth_from_ap(wlandevice_t *priv, const wlan_fr_deauthen_t *req);
++static int acx_l_process_probe_response(wlandevice_t *priv, wlan_fr_proberesp_t *req, const rxbuffer_t *rxbuf);
++static int acx_l_process_assocresp(wlandevice_t *priv, const wlan_fr_assocresp_t *req);
++static int acx_l_process_reassocresp(wlandevice_t *priv, const wlan_fr_reassocresp_t *req);
++static int acx_l_process_authen(wlandevice_t *priv, const wlan_fr_authen_t *req);
++static int acx_l_transmit_assocresp(wlandevice_t *priv, const wlan_fr_assocreq_t *req);
++static int acx_l_transmit_reassocresp(wlandevice_t *priv, const wlan_fr_reassocreq_t *req);
++static int acx_l_transmit_deauthen(wlandevice_t *priv, const u8 *addr, u16 reason);
++static int acx_l_transmit_authen1(wlandevice_t *priv);
++static int acx_l_transmit_authen2(wlandevice_t *priv, const wlan_fr_authen_t *req, client_t *clt);
++static int acx_l_transmit_authen3(wlandevice_t *priv, const wlan_fr_authen_t *req);
++static int acx_l_transmit_authen4(wlandevice_t *priv, const wlan_fr_authen_t *req);
++static int acx_l_transmit_assoc_req(wlandevice_t *priv);
++
++
++/***********************************************************************
++*/
++#if ACX_DEBUG
++unsigned int acx_debug = L_ASSOC|L_INIT;
++#endif
++#if USE_FW_LOADER_LEGACY
++static char *firmware_dir;
++#endif
++#if SEPARATE_DRIVER_INSTANCES
++static int card;
++#endif
++
++/* introduced earlier than 2.6.10, but takes more memory, so don't use it
++ * if there's no compile warning by kernel */
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
++
++#if ACX_DEBUG
++/* parameter is 'debug', corresponding var is acx_debug */
++module_param_named(debug, acx_debug, uint, 0);
++#endif
++#if USE_FW_LOADER_LEGACY
++module_param(firmware_dir, charp, 0);
++#endif
++
++#else
++
++#if ACX_DEBUG
++/* doh, 2.6.x screwed up big time: here the define has its own ";"
++ * ("double ; detected"), yet in 2.4.x it DOESN'T (the sane thing to do),
++ * grrrrr! */
++MODULE_PARM(acx_debug, "i");
++#endif
++#if USE_FW_LOADER_LEGACY
++MODULE_PARM(firmware_dir, "s");
++#endif
++
++#endif
++
++#if ACX_DEBUG
++MODULE_PARM_DESC(debug, "Debug level mask (see L_xxx constants)");
++#endif
++#if USE_FW_LOADER_LEGACY
++MODULE_PARM_DESC(firmware_dir, "Directory to load acx100 firmware files from");
++#endif
++#if SEPARATE_DRIVER_INSTANCES
++MODULE_PARM(card, "i");
++MODULE_PARM_DESC(card, "Associate only with card-th acx100 card from this driver instance");
++#endif
++
++/* Shoundn't be needed now, acx.firmware_dir= should work */
++#if 0 /* USE_FW_LOADER_LEGACY */
++static int __init
++acx_get_firmware_dir(const char *str)
++{
++      /* I've seen other drivers just pass the string pointer,
++       * so hopefully that's safe */
++      firmware_dir = str;
++      return OK;
++}
++__setup("acx_firmware_dir=", acx_get_firmware_dir);
++#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 itermediate 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
++
++const u8 reg_domain_ids[] =
++      { 0x10, 0x20, 0x30, 0x31, 0x32, 0x40, 0x41, 0x51 };
++/* stupid workaround for the fact that in C the size of an external array
++ * cannot be determined from within a second file */
++const u8 reg_domain_ids_len = sizeof(reg_domain_ids);
++static const u16 reg_domain_channel_masks[] =
++      { 0x07ff, 0x07ff, 0x1fff, 0x0600, 0x1e00, 0x2000, 0x3fff, 0x01fc };
++
++
++/***********************************************************************
++** 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(wlandevice_t *priv, const char* where)
++{
++      int count = 100*1000*1000;
++      where = sanitize_str(where);
++      while (--count) {
++              if (!spin_is_locked(&priv->lock)) break;
++              cpu_relax();
++      }
++      if (!count) {
++              printk(KERN_EMERG "LOCKUP: already taken at %s!\n", priv->last_lock);
++              BUG();
++      }
++      priv->last_lock = where;
++      rdtscl(priv->lock_time);
++}
++void
++acx_unlock_debug(wlandevice_t *priv, const char* where)
++{
++#ifdef SMP
++      if (!spin_is_locked(&priv->lock)) {
++              where = sanitize_str(where);
++              printk(KERN_EMERG "STRAY UNLOCK at %s!\n", where);
++              BUG();
++      }
++#endif
++      if (acx_debug & L_LOCK) {
++              unsigned diff;
++              rdtscl(diff);
++              diff -= priv->lock_time;
++              if (diff > max_lock_time) {
++                      where = sanitize_str(where);
++                      printk("max lock hold time %d CPU ticks from %s "
++                              "to %s\n", diff, priv->last_lock, where);
++                      max_lock_time = diff;
++              }
++      }
++}
++void
++acx_down_debug(wlandevice_t *priv, const char* where)
++{
++      int sem_count;
++      int count = 5000/5;
++      where = sanitize_str(where);
++
++      while (--count) {
++              sem_count = atomic_read(&priv->sem.count);
++              if (sem_count) break;
++              msleep(5);
++      }
++      if (!count) {
++              printk(KERN_EMERG "D STATE at %s! last sem at %s\n",
++                      where, priv->last_sem);
++              dump_stack();
++      }
++      priv->last_sem = where;
++      priv->sem_time = jiffies;
++      down(&priv->sem);
++      if (acx_debug & L_LOCK) {
++              printk("%s: sem_down %d -> %d\n",
++                      where, sem_count, atomic_read(&priv->sem.count));
++      }
++}
++void
++acx_up_debug(wlandevice_t *priv, const char* where)
++{
++      int sem_count = atomic_read(&priv->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 diff = jiffies - priv->sem_time;
++              if (diff > max_sem_time) {
++                      where = sanitize_str(where);
++                      printk("max sem hold time %d jiffies from %s "
++                              "to %s\n", diff, priv->last_sem, where);
++                      max_sem_time = diff;
++              }
++      }
++      up(&priv->sem);
++      if (acx_debug & L_LOCK) {
++              where = sanitize_str(where);
++              printk("%s: sem_up %d -> %d\n",
++                      where, sem_count, atomic_read(&priv->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??"
++      };
++      return str[(status < VEC_SIZE(str)) ? status : VEC_SIZE(str)-1];
++}
++
++
++/***********************************************************************
++** 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 = "UNKNOWN";
++      u8 fstype = (WF_FC_FSTYPE & fc) >> 4;
++      u8 ctl;
++
++      switch (WF_FC_FTYPE & fc) {
++      case WF_FTYPE_MGMT:
++              str = "MGMT/UNKNOWN";
++              if (fstype < VEC_SIZE(mgmt_arr))
++                      str = mgmt_arr[fstype];
++              break;
++      case WF_FTYPE_CTL:
++              ctl = fstype - 0x0a;
++              str = "CTL/UNKNOWN";
++              if (ctl < VEC_SIZE(ctl_arr))
++                      str = ctl_arr[ctl];
++              break;
++      case WF_FTYPE_DATA:
++              str = "DATA/UNKNOWN";
++              if (fstype < VEC_SIZE(data_arr))
++                      str = data_arr[fstype];
++              break;
++      }
++      return str;
++}
++#endif
++
++
++/***********************************************************************
++** 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] : "UNKNOWN REASON";
++}
++
++
++/***********************************************************************
++** get_status_string
++*/
++static 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",
++      /*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)
++{
++      acxlog(L_ASSOC, "acx: unknown EID %d in mgmt frame at offset %d\n",
++                              ie_ptr->eid, (int) ((u8*)ie_ptr - (u8*)hdr));
++      if (acx_debug & (L_DATA|L_ASSOC)) {
++              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
++
++
++/***********************************************************************
++** maps acx111 tx descr rate field to acx100 one
++*/
++const u8
++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 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
++*/
++static const u16
++CtlLength[] = {
++      0,
++      ACX100_IE_ACX_TIMER_LEN,
++      ACX1xx_IE_POWER_MGMT_LEN,
++      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,
++      ACX1xx_IE_FIRMWARE_STATISTICS_LEN,
++      0,
++      ACX1xx_IE_FEATURE_CONFIG_LEN,
++      ACX111_IE_KEY_CHOOSE_LEN,
++};
++
++static const u16
++CtlLengthDot11[] = {
++      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(wlandevice_t *priv, void *pdr, int type)
++{
++#else
++int
++acx_s_configure_debug(wlandevice_t *priv, void *pdr, int type, const char* typestr)
++{
++#endif
++      u16 len;
++      int res;
++
++      if (type < 0x1000)
++              len = CtlLength[type];
++      else
++              len = CtlLengthDot11[type - 0x1000];
++
++      acxlog(L_CTL, FUNC"(type:%s,len:%u)\n", typestr, len);
++      if (unlikely(!len)) {
++              acxlog(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(priv, ACX1xx_CMD_CONFIGURE, pdr, len + 4);
++      if (OK != res) {
++#if ACX_DEBUG
++              printk("%s: "FUNC"(type:%s) FAILED\n", priv->netdev->name, typestr);
++#else
++              printk("%s: "FUNC"(type:0x%X) FAILED\n", priv->netdev->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(wlandevice_t *priv, void *pdr, int type)
++{
++#else
++int
++acx_s_interrogate_debug(wlandevice_t *priv, void *pdr, int type,
++              const char* typestr)
++{
++#endif
++      u16 len;
++      int res;
++
++      if (type < 0x1000)
++              len = CtlLength[type];
++      else
++              len = CtlLengthDot11[type-0x1000];
++      acxlog(L_CTL, FUNC"(type:%s,len:%u)\n", typestr, len);
++
++      printk("Type : %08x, Len : %04x\n",type,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(priv, ACX1xx_CMD_INTERROGATE, pdr, len + 4);
++      if (OK != res) {
++#if ACX_DEBUG
++              printk("%s: "FUNC"(type:%s) FAILED\n", priv->netdev->name, typestr);
++#else
++              printk("%s: "FUNC"(type:0x%X) FAILED\n", priv->netdev->name, type);
++#endif
++              /* dump_stack() is already done in issue_cmd() */
++      }
++      return res;
++}
++
++#if CMD_DISCOVERY
++void
++great_inquisitor(wlandevice_t *priv)
++{
++      static struct {
++              u16     type ACX_PACKED;
++              u16     len ACX_PACKED;
++              /* 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(priv, 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
++**    priv is the usual pointer to our private struct wlandevice
++** Returns:
++**    number of bytes actually written to buf
++** Side effects:
++**    none
++*/
++static int
++acx_l_proc_output(char *buf, wlandevice_t *priv)
++{
++      char *p = buf;
++      int i;
++
++      FN_ENTER;
++
++      p += sprintf(p,
++              "acx driver version:\t\t" WLAN_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",
++              priv->chip_name, priv->firmware_id,
++              priv->radio_type,
++              priv->form_factor,
++              priv->eeprom_version,
++              priv->firmware_version, priv->firmware_numver);
++
++      for (i = 0; i < VEC_SIZE(priv->sta_list); i++) {
++              struct client *bss = &priv->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",
++                      priv->status, acx_get_status_name(priv->status));
++
++      FN_EXIT1(p - buf);
++      return p - buf;
++}
++
++
++/***********************************************************************
++*/
++static int
++acx_s_proc_diag_output(char *buf, wlandevice_t *priv)
++{
++      char *p = buf;
++      fw_stats_t *fw_stats;
++      unsigned long flags;
++
++      FN_ENTER;
++
++      fw_stats = kmalloc(sizeof(fw_stats_t), GFP_KERNEL);
++      if (!fw_stats) {
++              FN_EXIT1(0);
++              return 0;
++      }
++      memset(fw_stats, 0, sizeof(fw_stats_t));
++
++      acx_lock(priv, flags);
++
++      if (IS_PCI(priv))
++              p = acxpci_s_proc_diag_output(p, priv);
++
++      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, ",
++              priv->dev_state_mask,
++              priv->status, acx_get_status_name(priv->status),
++              priv->mode, priv->channel,
++              priv->reg_dom_id, priv->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",
++              priv->essid, priv->essid_active, (int)priv->essid_len,
++              priv->essid_for_assoc, priv->nick,
++              priv->wep_enabled, priv->wep_restricted,
++              priv->wep_current_index);
++      p += sprintf(p, "dev_addr  "MACSTR"\n", MAC(priv->dev_addr));
++      p += sprintf(p, "bssid     "MACSTR"\n", MAC(priv->bssid));
++      p += sprintf(p, "ap_filter "MACSTR"\n", MAC(priv->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"
++              "rts_threshold %d, short_retry %d, long_retry %d, msdu_lifetime %d, listen_interval %d, beacon_interval %d\n",
++              priv->tx_disabled, priv->tx_level_dbm, /* priv->tx_level_val, priv->tx_level_auto, */
++              priv->sensitivity, priv->antenna, priv->ed_threshold, priv->cca, priv->preamble_mode,
++              priv->rts_threshold, priv->short_retry, priv->long_retry, priv->msdu_lifetime, priv->listen_interval, priv->beacon_interval);
++
++      acx_unlock(priv, flags);
++
++      if (OK != acx_s_interrogate(priv, fw_stats, ACX1xx_IE_FIRMWARE_STATISTICS))
++              p += sprintf(p,
++                      "\n"
++                      "** Firmware **\n"
++                      "QUERY FAILED!!\n");
++      else {
++              p += sprintf(p,
++                      "\n"
++                      "** Firmware **\n"
++                      "version \"%s\"\n"
++                      "tx_desc_overfl %u, rx_OutOfMem %u, rx_hdr_overfl %u, rx_hdr_use_next %u\n"
++                      "rx_dropped_frame %u, rx_frame_ptr_err %u, rx_xfr_hint_trig %u, rx_dma_req %u\n"
++                      "rx_dma_err %u, tx_dma_req %u, tx_dma_err %u, cmd_cplt %u, fiq %u\n"
++                      "rx_hdrs %u, rx_cmplt %u, rx_mem_overfl %u, rx_rdys %u, irqs %u\n"
++                      "acx_trans_procs %u, decrypt_done %u, dma_0_done %u, dma_1_done %u\n",
++                      priv->firmware_version,
++                      le32_to_cpu(fw_stats->tx_desc_of),
++                      le32_to_cpu(fw_stats->rx_oom),
++                      le32_to_cpu(fw_stats->rx_hdr_of),
++                      le32_to_cpu(fw_stats->rx_hdr_use_next),
++                      le32_to_cpu(fw_stats->rx_dropped_frame),
++                      le32_to_cpu(fw_stats->rx_frame_ptr_err),
++                      le32_to_cpu(fw_stats->rx_xfr_hint_trig),
++                      le32_to_cpu(fw_stats->rx_dma_req),
++                      le32_to_cpu(fw_stats->rx_dma_err),
++                      le32_to_cpu(fw_stats->tx_dma_req),
++                      le32_to_cpu(fw_stats->tx_dma_err),
++                      le32_to_cpu(fw_stats->cmd_cplt),
++                      le32_to_cpu(fw_stats->fiq),
++                      le32_to_cpu(fw_stats->rx_hdrs),
++                      le32_to_cpu(fw_stats->rx_cmplt),
++                      le32_to_cpu(fw_stats->rx_mem_of),
++                      le32_to_cpu(fw_stats->rx_rdys),
++                      le32_to_cpu(fw_stats->irqs),
++                      le32_to_cpu(fw_stats->acx_trans_procs),
++                      le32_to_cpu(fw_stats->decrypt_done),
++                      le32_to_cpu(fw_stats->dma_0_done),
++                      le32_to_cpu(fw_stats->dma_1_done));
++              p += sprintf(p,
++                      "tx_exch_complet %u, commands %u, acx_rx_procs %u\n"
++                      "hw_pm_mode_changes %u, host_acks %u, pci_pm %u, acm_wakeups %u\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",
++                      le32_to_cpu(fw_stats->tx_exch_complet),
++                      le32_to_cpu(fw_stats->commands),
++                      le32_to_cpu(fw_stats->acx_rx_procs),
++                      le32_to_cpu(fw_stats->hw_pm_mode_changes),
++                      le32_to_cpu(fw_stats->host_acks),
++                      le32_to_cpu(fw_stats->pci_pm),
++                      le32_to_cpu(fw_stats->acm_wakeups),
++                      le32_to_cpu(fw_stats->wep_key_count),
++                      le32_to_cpu(fw_stats->wep_default_key_count),
++                      le32_to_cpu(fw_stats->dot11_def_key_mib),
++                      le32_to_cpu(fw_stats->wep_key_not_found),
++                      le32_to_cpu(fw_stats->wep_decrypt_fail));
++      }
++
++      kfree(fw_stats);
++
++      FN_EXIT1(p - buf);
++      return p - buf;
++}
++
++
++/***********************************************************************
++*/
++static int
++acx_s_proc_phy_output(char *buf, wlandevice_t *priv)
++{
++      char *p = buf;
++      int i;
++
++      FN_ENTER;
++
++      /*
++      if (RADIO_RFMD_11 != priv->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(priv, 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)
++{
++      wlandevice_t *priv = (wlandevice_t *)data;
++      unsigned long flags;
++      int length;
++
++      FN_ENTER;
++
++      acx_sem_lock(priv);
++      acx_lock(priv, flags);
++      /* fill buf */
++      length = acx_l_proc_output(buf, priv);
++      acx_unlock(priv, flags);
++      acx_sem_unlock(priv);
++
++      /* 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_diag(char *buf, char **start, off_t offset, int count,
++                   int *eof, void *data)
++{
++      wlandevice_t *priv = (wlandevice_t *)data;
++      int length;
++
++      FN_ENTER;
++
++      acx_sem_lock(priv);
++      /* fill buf */
++      length = acx_s_proc_diag_output(buf, priv);
++      acx_sem_unlock(priv);
++
++      /* 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_eeprom(char *buf, char **start, off_t offset, int count,
++                   int *eof, void *data)
++{
++      wlandevice_t *priv = (wlandevice_t *)data;
++      int length;
++
++      FN_ENTER;
++
++      /* fill buf */
++      length = 0;
++      if (IS_PCI(priv)) {
++              acx_sem_lock(priv);
++              length = acx_proc_eeprom_output(buf, priv);
++              acx_sem_unlock(priv);
++      }
++
++      /* 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)
++{
++      wlandevice_t *priv = (wlandevice_t *)data;
++      int length;
++
++      FN_ENTER;
++
++      acx_sem_lock(priv);
++      /* fill buf */
++      length = acx_s_proc_phy_output(buf, priv);
++      acx_sem_unlock(priv);
++
++      /* 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
++acx_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 *dev, int remove)
++{
++      /* doh, netdev_priv() doesn't have const! */
++      wlandevice_t *priv = netdev_priv((struct net_device *)dev);
++      char procbuf[80];
++      int i;
++
++      for (i = 0; i < 4; i++) {
++              sprintf(procbuf, "driver/acx_%s", dev->name);
++              strcat(procbuf, proc_files[i]);
++              if (!remove) {
++                      acxlog(L_INIT, "creating /proc entry %s\n", procbuf);
++                      if (!create_proc_read_entry(procbuf, 0, 0, acx_proc_funcs[i], priv))
++                              return NOT_OK;
++              } else {
++                      acxlog(L_INIT, "removing /proc entry %s\n", procbuf);
++                      remove_proc_entry(procbuf, NULL);
++              }
++      }
++      return OK;
++}
++
++int
++acx_proc_register_entries(const struct net_device *dev)
++{
++      return manage_proc_entries(dev, 0);
++}
++
++int
++acx_proc_unregister_entries(const struct net_device *dev)
++{
++      return manage_proc_entries(dev, 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 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(wlandevice_t *priv, const u8 *bssid)
++{
++      acx_joinbss_t tmp;
++      int dtim_interval;
++      int i;
++
++      FN_ENTER;
++
++      dtim_interval = (ACX_MODE_0_ADHOC == priv->mode) ?
++                      1 : priv->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(priv->beacon_interval);
++
++      /* basic rate set. Control frame responses (such as ACK or CTS frames)
++      ** are sent with one of these rates */
++      if (IS_ACX111(priv)) {
++              /* 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(priv->rate_basic);
++              acxlog(L_ASSOC, "%s rates_basic %04X, rates_supported %04X\n",
++                      __func__, priv->rate_basic, priv->rate_oper);
++      } else {
++              tmp.u.acx100.dtim_interval = dtim_interval;
++              tmp.u.acx100.rates_basic = rate111to5bits(priv->rate_basic);
++              tmp.u.acx100.rates_supported = rate111to5bits(priv->rate_oper);
++              acxlog(L_ASSOC, "%s rates_basic %04X->%02X, "
++                      "rates_supported %04X->%02X\n",
++                      __func__,
++                      priv->rate_basic, tmp.u.acx100.rates_basic,
++                      priv->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.genfrm_txrate = bitpos2genframe_txrate[lowest_bit(priv->rate_basic)];
++      tmp.genfrm_mod_pre = 0; /* FIXME: was = priv->capab_short (which is 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 = (priv->mode != ACX_MODE_MONITOR ? priv->mode : ACX_MODE_2_STA);
++      tmp.channel = priv->channel;
++      tmp.essid_len = priv->essid_len;
++      /* NOTE: the code memcpy'd essid_len + 1 before, which is WRONG! */
++      memcpy(tmp.essid, priv->essid, tmp.essid_len);
++      acx_s_issue_cmd(priv, ACX1xx_CMD_JOIN, &tmp, tmp.essid_len + 0x11);
++
++      acxlog(L_ASSOC|L_DEBUG, "BSS_Type = %u\n", tmp.macmode);
++      acxlog_mac(L_ASSOC|L_DEBUG, "JoinBSSID MAC:", priv->bssid, "\n");
++
++      acx_update_capabilities(priv);
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++** acx_s_cmd_start_scan
++**
++** Issue scan command to the hardware
++*/
++static void
++acx100_s_scan_chan(wlandevice_t *priv)
++{
++      acx100_scan_t s;
++
++      FN_ENTER;
++
++      memset(&s, 0, sizeof(s));
++      s.count = cpu_to_le16(priv->scan_count);
++      s.start_chan = cpu_to_le16(1);
++      s.flags = cpu_to_le16(0x8000);
++      s.max_rate = priv->scan_rate;
++      s.options = priv->scan_mode;
++      s.chan_duration = cpu_to_le16(priv->scan_duration);
++      s.max_probe_delay = cpu_to_le16(priv->scan_probe_delay);
++
++      acx_s_issue_cmd(priv, ACX1xx_CMD_SCAN, &s, sizeof(s));
++      FN_EXIT0;
++}
++
++static void
++acx111_s_scan_chan(wlandevice_t *priv)
++{
++      acx111_scan_t s;
++
++      FN_ENTER;
++
++      memset(&s, 0, sizeof(s));
++      s.count = cpu_to_le16(priv->scan_count);
++      s.channel_list_select = 0; /* scan every allowed channel */
++      /*s.channel_list_select = 1;*/ /* scan given channels */
++      s.rate = priv->scan_rate;
++      s.options = priv->scan_mode;
++      s.chan_duration = cpu_to_le16(priv->scan_duration);
++      s.max_probe_delay = cpu_to_le16(priv->scan_probe_delay);
++      /*s.modulation = 0x40;*/ /* long preamble? OFDM? -> only for active scan */
++      s.modulation = 0;
++      /*s.channel_list[0] = 6;
++      s.channel_list[1] = 4;*/
++
++      acx_s_issue_cmd(priv, ACX1xx_CMD_SCAN, &s, sizeof(s));
++      FN_EXIT0;
++}
++
++void
++acx_s_cmd_start_scan(wlandevice_t *priv)
++{
++      /* time_before check is 'just in case' thing */
++      if (!(priv->irq_status & HOST_INT_SCAN_COMPLETE)
++       && time_before(jiffies, priv->scan_start + 10*HZ)
++      ) {
++              acxlog(L_INIT, "start_scan: seems like previous scan "
++              "is still running. Not starting anew. Please report\n");
++              return;
++      }
++
++      acxlog(L_INIT, "starting radio scan\n");
++      /* remember that fw is commanded to do scan */
++      priv->scan_start = jiffies;
++      CLEAR_BIT(priv->irq_status, HOST_INT_SCAN_COMPLETE);
++      /* issue it */
++      if (IS_ACX100(priv)) {
++              acx100_s_scan_chan(priv);
++      } else {
++              acx111_s_scan_chan(priv);
++      }
++}
++
++
++/***********************************************************************
++** acx111 feature config
++*/
++static int
++acx111_s_get_feature_config(wlandevice_t *priv,
++              u32 *feature_options, u32 *data_flow_options)
++{
++      struct acx111_ie_feature_config fc;
++
++      if (!IS_ACX111(priv)) {
++              return NOT_OK;
++      }
++
++      memset(&fc, 0, sizeof(fc));
++
++      if (OK != acx_s_interrogate(priv, &fc, ACX1xx_IE_FEATURE_CONFIG)) {
++              return NOT_OK;
++      }
++      acxlog(L_DEBUG,
++              "got Feature option:0x%X, DataFlow option: 0x%X\n",
++              fc.feature_options,
++              fc.data_flow_options);
++
++      if (feature_options)
++              *feature_options = le32_to_cpu(fc.feature_options);
++      if (data_flow_options)
++              *data_flow_options = le32_to_cpu(fc.data_flow_options);
++
++      return OK;
++}
++
++static int
++acx111_s_set_feature_config(wlandevice_t *priv,
++      u32 feature_options, u32 data_flow_options,
++      unsigned int mode /* 0 == remove, 1 == add, 2 == set */)
++{
++      struct acx111_ie_feature_config fc;
++
++      if (!IS_ACX111(priv)) {
++              return NOT_OK;
++      }
++
++      if ((mode < 0) || (mode > 2))
++              return NOT_OK;
++
++      if (mode != 2)
++              /* need to modify old data */
++              acx111_s_get_feature_config(priv, &fc.feature_options, &fc.data_flow_options);
++      else {
++              /* need to set a completely new value */
++              fc.feature_options = 0;
++              fc.data_flow_options = 0;
++      }
++
++      if (mode == 0) { /* remove */
++              CLEAR_BIT(fc.feature_options, cpu_to_le32(feature_options));
++              CLEAR_BIT(fc.data_flow_options, cpu_to_le32(data_flow_options));
++      } else { /* add or set */
++              SET_BIT(fc.feature_options, cpu_to_le32(feature_options));
++              SET_BIT(fc.data_flow_options, cpu_to_le32(data_flow_options));
++      }
++
++      acxlog(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(fc.feature_options),
++              le32_to_cpu(fc.data_flow_options));
++
++      if (OK != acx_s_configure(priv, &fc, ACX1xx_IE_FEATURE_CONFIG)) {
++              return NOT_OK;
++      }
++
++      return OK;
++}
++
++static inline int
++acx111_s_feature_off(wlandevice_t *priv, u32 f, u32 d)
++{
++      return acx111_s_set_feature_config(priv, f, d, 0);
++}
++static inline int
++acx111_s_feature_on(wlandevice_t *priv, u32 f, u32 d)
++{
++      return acx111_s_set_feature_config(priv, f, d, 1);
++}
++static inline int
++acx111_s_feature_set(wlandevice_t *priv, u32 f, u32 d)
++{
++      return acx111_s_set_feature_config(priv, f, d, 2);
++}
++
++
++/***********************************************************************
++** acx100_s_init_memory_pools
++*/
++static int
++acx100_s_init_memory_pools(wlandevice_t *priv, 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(priv->memblocksize);
++
++      /* Then we alert the card to our decision of block size */
++      if (OK != acx_s_configure(priv, &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)) / priv->memblocksize;
++
++      acxlog(L_DEBUG, "TotalMemoryBlocks=%u (%u bytes)\n",
++              TotalMemoryBlocks, TotalMemoryBlocks*priv->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      // use local memory block linked list (else what?)
++      0x00010000      // use host indirect descriptors (else host must access ACX memory?)
++      */
++      if (IS_PCI(priv)) {
++              MemoryConfigOption.DMA_config = cpu_to_le32(0x30000);
++              /* Declare start of the Rx host pool */
++              MemoryConfigOption.pRxHostDesc = cpu2acx(priv->rxhostdesc_startphy);
++              acxlog(L_DEBUG, "pRxHostDesc 0x%08X, rxhostdesc_startphy 0x%lX\n",
++                              acx2cpu(MemoryConfigOption.pRxHostDesc),
++                              (long)priv->rxhostdesc_startphy);
++      } else {
++              MemoryConfigOption.DMA_config = cpu_to_le32(0x20000);
++      }
++
++      /* 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 * priv->memblocksize;
++      TotalRxBlockSize = RxBlockNum * priv->memblocksize;
++      acxlog(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);
++      acxlog(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(priv, &MemoryConfigOption, ACX1xx_IE_MEMORY_CONFIG_OPTIONS)) {
++              goto bad;
++      }
++
++      /* and tell the device to kick it into gear */
++      if (OK != acx_s_issue_cmd(priv, ACX100_CMD_INIT_MEMORY, NULL, 0)) {
++              goto bad;
++      }
++      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(wlandevice_t *priv)
++{
++      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(priv, &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);
++
++      acxlog(L_DEBUG, "initializing Queue Indicator\n");
++
++      memset(&queueconf, 0, sizeof(queueconf));
++
++      /* Not needed for PCI, so we can avoid setting them altogether */
++      if (IS_USB(priv)) {
++              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(priv, &queueconf, ACX1xx_IE_QUEUE_CONFIG)) {
++              goto fail;
++      }
++
++#if 0
++      if (IS_PCI(priv)) {
++      /* sets the beginning of the rx descriptor queue, after the tx descrs */
++              if (OK != acx_s_create_hostdesc_queues(priv))
++                      goto fail;
++              acx_create_desc_queues(priv, tx_queue_start, rx_queue_start);
++      }
++#endif
++
++      if (OK != acx_s_interrogate(priv, &memmap, ACX1xx_IE_MEMORY_MAP)) {
++              goto fail;
++      }
++
++      memmap.PoolStart = cpu_to_le32(
++                      (le32_to_cpu(memmap.QueueEnd) + 4 + 0x1f) & ~0x1f
++                      );
++
++      if (OK != acx_s_configure(priv, &memmap, ACX1xx_IE_MEMORY_MAP)) {
++              goto fail;
++      }
++
++      if (OK != acx100_s_init_memory_pools(priv, &memmap)) {
++              goto fail;
++      }
++
++      res = OK;
++      goto end;
++
++fail:
++      acx_s_msleep(1000); /* ? */
++      if (IS_PCI(priv))
++              acx_free_desc_queues(priv);
++end:
++      FN_EXIT1(res);
++      return res;
++}
++
++
++/***********************************************************************
++** acx111_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
++*/
++#define ACX111_PERCENT(percent) ((percent)/5)
++
++static int
++acx111_s_create_dma_regions(wlandevice_t *priv)
++{
++      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 (IS_PCI(priv)) {
++              if (OK != acx_s_create_hostdesc_queues(priv))
++                      goto fail;
++      }
++
++      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(priv->sta_list));
++      /* specify the memory block size. Default is 256 */
++      memconf.memory_block_size = cpu_to_le16(priv->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 (IS_PCI(priv)) {
++              memconf.rx_queue1_host_rx_start = cpu2acx(priv->rxhostdesc_startphy);
++      }
++      /* 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(priv, &memconf, ACX1xx_IE_QUEUE_CONFIG)) {
++              goto fail;
++      }
++
++      acx_s_interrogate(priv, &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);
++
++      acxlog(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 (IS_PCI(priv))
++              acx_create_desc_queues(priv, tx_queue_start, rx_queue_start);
++
++      FN_EXIT1(OK);
++      return OK;
++fail:
++      if (IS_PCI(priv))
++              acx_free_desc_queues(priv);
++
++      FN_EXIT1(NOT_OK);
++      return NOT_OK;
++}
++
++
++/***********************************************************************
++** acx_s_set_defaults
++** Called from acx_s_init_mac
++*/
++int
++acx_s_set_defaults(wlandevice_t *priv)
++{
++      unsigned long flags;
++
++      FN_ENTER;
++
++      /* 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!! */
++      priv->get_mask = GETSET_ANTENNA|GETSET_SENSITIVITY|GETSET_STATION_ID|GETSET_REG_DOMAIN;
++      /* Only ACX100 supports ED and CCA */
++      if (IS_ACX100(priv))
++              priv->get_mask |= GETSET_CCA|GETSET_ED_THRESH;
++
++      acx_s_update_card_settings(priv, 0, 0);
++
++      acx_lock(priv, flags);
++
++      /* set our global interrupt mask */
++      if (IS_PCI(priv))
++              acx_set_interrupt_mask(priv);
++
++      priv->led_power = 1; /* LED is active on startup */
++      priv->brange_max_quality = 60; /* LED blink max quality is 60 */
++      priv->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(priv->dev_addr, priv->netdev->dev_addr);
++      sprintf(priv->essid, "STA%02X%02X%02X",
++              priv->dev_addr[3], priv->dev_addr[4], priv->dev_addr[5]);
++      priv->essid_len = sizeof("STAxxxxxx") - 1; /* make sure to adapt if changed above! */
++      priv->essid_active = 1;
++
++      /* we have a nick field to waste, so why not abuse it
++       * to announce the driver version? ;-) */
++      strncpy(priv->nick, "acx " WLAN_RELEASE, IW_ESSID_MAX_SIZE);
++
++      if (IS_PCI(priv)) {
++              if (IS_ACX111(priv)) {
++                      /* Hope this is correct, only tested with domain 0x30 */
++                      acx_read_eeprom_offset(priv, 0x16F, &priv->reg_dom_id);
++              } else if (priv->eeprom_version < 5) {
++                      acx_read_eeprom_offset(priv, 0x16F, &priv->reg_dom_id);
++              } else {
++                      acx_read_eeprom_offset(priv, 0x171, &priv->reg_dom_id);
++              }
++      }
++
++      priv->channel = 1;
++      /* 0xffff would be better, but then we won't get a "scan complete"
++       * interrupt, so our current infrastructure will fail: */
++      priv->scan_count = 1;
++      priv->scan_mode = ACX_SCAN_OPT_PASSIVE;
++      /* Doesn't work for acx100, do it only for acx111 for now */
++      if (IS_ACX111(priv)) {
++              priv->scan_mode = ACX_SCAN_OPT_ACTIVE;
++      }
++      priv->scan_duration = 100;
++      priv->scan_probe_delay = 200;
++      priv->scan_rate = ACX_SCAN_RATE_1;
++
++      priv->auth_alg = WLAN_AUTH_ALG_OPENSYSTEM;
++      priv->preamble_mode = 2; /* auto */
++      priv->listen_interval = 100;
++      priv->beacon_interval = DEFAULT_BEACON_INTERVAL;
++      priv->mode = ACX_MODE_2_STA;
++      priv->dtim_interval = DEFAULT_DTIM_INTERVAL;
++
++      priv->msdu_lifetime = DEFAULT_MSDU_LIFETIME;
++      SET_BIT(priv->set_mask, SET_MSDU_LIFETIME);
++
++      priv->rts_threshold = DEFAULT_RTS_THRESHOLD;
++
++      /* use standard default values for retry limits */
++      priv->short_retry = 7; /* max. retries for (short) non-RTS packets */
++      priv->long_retry = 4; /* max. retries for long (RTS) packets */
++      SET_BIT(priv->set_mask, GETSET_RETRY);
++
++      priv->fallback_threshold = 3;
++      priv->stepup_threshold = 10;
++      priv->rate_bcast = RATE111_1;
++      priv->rate_bcast100 = RATE100_1;
++      priv->rate_basic = RATE111_1 | RATE111_2;
++      priv->rate_auto = 1;
++      if (IS_ACX111(priv)) {
++              priv->rate_oper = RATE111_ALL;
++      } else {
++              priv->rate_oper = RATE111_ACX100_COMPAT;
++      }
++
++      /* configure card to do rate fallback when in auto rate mode. */
++      SET_BIT(priv->set_mask, SET_RATE_FALLBACK);
++
++      /* 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(priv);
++
++      priv->capab_short = 0;
++      priv->capab_pbcc = 1;
++      priv->capab_agility = 0;
++
++      SET_BIT(priv->set_mask, SET_RXCONFIG);
++
++      /* set some more defaults */
++      if (IS_ACX111(priv)) {
++              /* 30mW (15dBm) is default, at least in my acx111 card: */
++              priv->tx_level_dbm = 15;
++      } else {
++              /* don't use max. level, since it might be dangerous
++               * (e.g. WRT54G people experience
++               * excessive Tx power damage!) */
++              priv->tx_level_dbm = 18;
++      }
++      /* priv->tx_level_auto = 1; */
++      SET_BIT(priv->set_mask, GETSET_TXPOWER);
++
++      if (IS_ACX111(priv)) {
++              /* start with sensitivity level 1 out of 3: */
++              priv->sensitivity = 1;
++      }
++
++      /* better re-init the antenna value we got above */
++      SET_BIT(priv->set_mask, GETSET_ANTENNA);
++
++      priv->ps_wakeup_cfg = 0;
++      priv->ps_listen_interval = 0;
++      priv->ps_options = 0;
++      priv->ps_hangover_period = 0;
++      priv->ps_enhanced_transition_time = 0;
++#ifdef POWER_SAVE_80211
++      SET_BIT(priv->set_mask, GETSET_POWER_80211);
++#endif
++
++      MAC_BCAST(priv->ap);
++
++      acx_unlock(priv, flags);
++      acx_lock_unhold(); // hold time 844814 CPU ticks @2GHz
++
++      acx_s_initialize_rx_config(priv);
++
++      FN_EXIT1(OK);
++      return OK;
++}
++
++
++/***********************************************************************
++** 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(wlandevice_t *priv, 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.
++       * Ideally we would query it here, but we first need a
++       * standard way to query individual configoptions easily. */
++      if (level_dbm <= 12) {
++              tx_level.level = 2; /* 10 dBm */
++              priv->tx_level_dbm = 10;
++      } else {
++              tx_level.level = 1; /* 15 dBm */
++              priv->tx_level_dbm = 15;
++      }
++      if (level_dbm != priv->tx_level_dbm)
++              acxlog(L_INIT, "acx111 firmware has specific "
++                      "power levels only: adjusted %d dBm to %d dBm!\n",
++                      level_dbm, priv->tx_level_dbm);
++
++      return acx_s_configure(priv, &tx_level, ACX1xx_IE_DOT11_TX_POWER_LEVEL);
++}
++
++static int
++acx_s_set_tx_level(wlandevice_t *priv, u8 level_dbm)
++{
++      if (IS_ACX111(priv)) {
++              return acx111_s_set_tx_level(priv, level_dbm);
++      }
++      if (IS_PCI(priv)) {
++              return acx100_s_set_tx_level(priv, level_dbm);
++      }
++      return OK;
++}
++
++
++/***********************************************************************
++*/
++#ifdef UNUSED
++/* Returns the current tx level (ACX111) */
++static u8
++acx111_s_get_tx_level(wlandevice_t *priv)
++{
++      struct acx111_ie_tx_level tx_level;
++
++      tx_level.level = 0;
++      acx_s_interrogate(priv, &tx_level, ACX1xx_IE_DOT11_TX_POWER_LEVEL);
++      return tx_level.level;
++}
++#endif
++
++
++/***********************************************************************
++** acx_s_init_mac
++*/
++int
++acx_s_init_mac(netdevice_t *dev)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++      int result = NOT_OK;
++
++      FN_ENTER;
++
++      if (IS_PCI(priv)) {
++              priv->memblocksize = 256; /* 256 is default */
++              acx_init_mboxes(priv);
++              /* 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 */
++              acx_s_upload_radio(priv);
++      } else {
++              priv->memblocksize = 128;
++      }
++
++      if (IS_ACX111(priv)) {
++              /* 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 != acx111_s_init_packet_templates(priv))
++                      goto fail;
++
++              if (OK != acx111_s_create_dma_regions(priv)) {
++                      printk("%s: acx111_create_dma_regions FAILED\n",
++                                                      dev->name);
++                      goto fail;
++              }
++#ifdef DEBUG_WEP
++              /* don't decrypt WEP in firmware */
++              if (OK != acx111_s_feature_on(priv, 0, FEATURE2_SNIFFER))
++                      goto fail;
++#endif
++      } else {
++              if (OK != acx100_s_init_wep(priv))
++                      goto fail;
++              acxlog(L_DEBUG, "between init_wep and init_packet_templates\n");
++              if (OK != acx100_s_init_packet_templates(priv))
++                      goto fail;
++
++              if (OK != acx100_s_create_dma_regions(priv)) {
++                      printk("%s: acx100_create_dma_regions FAILED\n",
++                                                      dev->name);
++                      goto fail;
++              }
++      }
++
++      MAC_COPY(dev->dev_addr, priv->dev_addr);
++      result = OK;
++
++fail:
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/*----------------------------------------------------------------
++* acx_l_rxmonitor
++* Called from IRQ context only
++*----------------------------------------------------------------*/
++static void
++acx_l_rxmonitor(wlandevice_t *priv, 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(priv, rxbuf) - (u8*)rxbuf);
++      skb_len = RXBUF_BYTES_USED(rxbuf) - payload_offset;
++
++      /* sanity check */
++      if (skb_len > WLAN_A4FR_MAXLEN_WEP) {
++              printk("%s: monitor mode panic: oversized frame!\n",
++                              priv->netdev->name);
++              goto end;
++      }
++
++      if (priv->netdev->type == ARPHRD_IEEE80211_PRISM)
++              skb_len += sizeof(*msg);
++
++      /* allocate skb */
++      skb = dev_alloc_skb(skb_len);
++      if (!skb) {
++              printk("%s: no memory for skb (%u bytes)\n",
++                              priv->netdev->name, skb_len);
++              goto end;
++      }
++
++      skb_put(skb, skb_len);
++
++              /* when in raw 802.11 mode, just copy frame as-is */
++      if (priv->netdev->type == ARPHRD_IEEE80211)
++              datap = skb->data;
++      else { /* otherwise, emulate prism header */
++              msg = (wlansniffrm_t*)skb->data;
++              datap = msg + 1;
++
++              msg->msgcode = WLANSNIFFFRM;
++              msg->msglen = sizeof(*msg);
++              strncpy(msg->devname, priv->netdev->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 = priv->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;
++      }
++
++      memcpy(datap, ((unsigned char*)rxbuf)+payload_offset, skb_len);
++
++      skb->dev = priv->netdev;
++      skb->dev->last_rx = jiffies;
++
++      skb->mac.raw = skb->data;
++      skb->ip_summed = CHECKSUM_NONE;
++      skb->pkt_type = PACKET_OTHERHOST;
++      skb->protocol = htons(ETH_P_80211_RAW);
++      netif_rx(skb);
++
++      priv->stats.rx_packets++;
++      priv->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. */
++static inline int
++acx_l_handle_dup(wlandevice_t *priv, u16 seq)
++{
++      if (priv->dup_count) {
++              priv->nondup_count++;
++              if (time_after(jiffies, priv->dup_msg_expiry)) {
++                      /* Log only if more than 1 dup in 64 packets */
++                      if (priv->nondup_count/64 < priv->dup_count) {
++                              printk(KERN_INFO "%s: rx: %d DUPs in "
++                                      "%d packets received in 10 secs\n",
++                                      priv->netdev->name,
++                                      priv->dup_count,
++                                      priv->nondup_count);
++                      }
++                      priv->dup_count = 0;
++                      priv->nondup_count = 0;
++              }
++      }
++      if (unlikely(seq == priv->last_seq_ctrl)) {
++              if (!priv->dup_count++)
++                      priv->dup_msg_expiry = jiffies + 10*HZ;
++              priv->stats.rx_errors++;
++              return 1; /* a dup */
++      }
++      priv->last_seq_ctrl = seq;
++      return 0;
++}
++
++static int
++acx_l_rx_ieee802_11_frame(wlandevice_t *priv, rxbuffer_t *rxbuf)
++{
++      unsigned int ftype, fstype;
++      const wlan_hdr_t *hdr;
++      int result = NOT_OK;
++
++      FN_ENTER;
++
++      hdr = acx_get_wlan_hdr(priv, rxbuf);
++
++      /* see IEEE 802.11-1999.pdf chapter 7 "MAC frame formats" */
++      if ((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(priv, 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(priv, rxbuf);
++                              break;
++                      }
++                      */
++
++                      switch (priv->mode) {
++                      case ACX_MODE_3_AP:
++                              result = acx_l_process_data_frame_master(priv, rxbuf);
++                              break;
++                      case ACX_MODE_0_ADHOC:
++                      case ACX_MODE_2_STA:
++                              result = acx_l_process_data_frame_client(priv, 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(priv, rxbuf, 3); */
++                      break;
++              case WF_FSTYPE_NULLi:
++                      /* acx_l_process_NULL_frame(priv, 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(priv, 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(priv, 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(wlandevice_t *priv, rxbuffer_t *rxbuf)
++{
++      struct wlan_hdr *hdr;
++      unsigned int buf_len;
++      unsigned int qual;
++      u16 fc;
++
++      hdr = acx_get_wlan_hdr(priv, rxbuf);
++      /* length of frame from control field to last byte of FCS */
++      buf_len = RXBUF_BYTES_RCVD(rxbuf);
++      fc = le16_to_cpu(hdr->fc);
++
++      if ( ((WF_FC_FSTYPE & fc) != WF_FSTYPE_BEACON)
++        || (acx_debug & L_XFER_BEACON)
++      ) {
++              acxlog(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,
++                      priv->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(priv->mode == ACX_MODE_MONITOR)) {
++              acx_l_rxmonitor(priv, rxbuf);
++      } else if (likely(buf_len >= WLAN_HDR_A3_LEN)) {
++              acx_l_rx_ieee802_11_frame(priv, rxbuf);
++      } else {
++              acxlog(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 (priv->ap_client
++       && mac_is_equal(hdr->a2, priv->ap_client->address)) {
++#endif
++              priv->wstats.qual.level = acx_signal_to_winlevel(rxbuf->phy_level);
++              priv->wstats.qual.noise = acx_signal_to_winlevel(rxbuf->phy_snr);
++#ifndef OLD_QUALITY
++              qual = acx_signal_determine_quality(priv->wstats.qual.level,
++                              priv->wstats.qual.noise);
++#else
++              qual = (priv->wstats.qual.noise <= 100) ?
++                              100 - priv->wstats.qual.noise : 0;
++#endif
++              priv->wstats.qual.qual = qual;
++              priv->wstats.qual.updated = 7; /* all 3 indicators updated */
++#ifdef FROM_SCAN_SOURCE_ONLY
++      }
++#endif
++}
++
++
++/***********************************************************************
++** acx_i_start_xmit
++**
++** Called by network core. Can be called outside of process context.
++*/
++int
++acx_i_start_xmit(struct sk_buff *skb, netdevice_t *dev)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++      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(!priv)) {
++              goto end_no_unlock;
++      }
++
++      acx_lock(priv, flags);
++
++      if (unlikely(!(priv->dev_state_mask & ACX_STATE_IFACE_UP))) {
++              goto end;
++      }
++      if (unlikely(priv->mode == ACX_MODE_OFF)) {
++              goto end;
++      }
++      if (unlikely(acx_queue_stopped(dev))) {
++              acxlog(L_DEBUG, "%s: called when queue stopped\n", __func__);
++              goto end;
++      }
++      if (unlikely(ACX_STATUS_4_ASSOCIATED != priv->status)) {
++              acxlog(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 */
++              priv->stats.tx_errors++;
++              goto end;
++      }
++
++      tx = acx_l_alloc_tx(priv);
++      if (unlikely(!tx)) {
++              printk("%s: start_xmit: txdesc ring is full, dropping tx\n",
++                      dev->name);
++              txresult = NOT_OK;
++              goto end;
++      }
++
++      txbuf = acx_l_get_txbuf(priv, tx);
++      if (!txbuf) {
++              /* Card was removed */
++              txresult = NOT_OK;
++              goto end;
++      }
++      len = acx_l_ether_to_txbuf(priv, txbuf, skb);
++      if (len < 0) {
++              /* Error in packet conversion */
++              txresult = NOT_OK;
++              goto end;
++      }
++      acx_l_tx_data(priv, tx, len);
++      dev->trans_start = jiffies;
++
++      txresult = OK;
++      priv->stats.tx_packets++;
++      priv->stats.tx_bytes += skb->len;
++
++end:
++      acx_unlock(priv, flags);
++
++end_no_unlock:
++      if ((txresult == OK) && skb)
++              dev_kfree_skb_any(skb);
++
++      FN_EXIT1(txresult);
++      return txresult;
++}
++
++
++/***********************************************************************
++** acx_l_update_ratevector
++**
++** Updates priv->rate_supported[_len] according to rate_{basic,oper}
++*/
++const u8
++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(wlandevice_t *priv)
++{
++      u16 bcfg = priv->rate_basic;
++      u16 ocfg = priv->rate_oper;
++      u8 *supp = priv->rate_supported;
++      const u8 *dot11 = bitpos2ratebyte;
++
++      FN_ENTER;
++
++      while (ocfg) {
++              if (ocfg & 1) {
++                      *supp = *dot11;
++                      if (bcfg & 1) {
++                              *supp |= 0x80;
++                      }
++                      supp++;
++              }
++              dot11++;
++              ocfg >>= 1;
++              bcfg >>= 1;
++      }
++      priv->rate_supported_len = supp - priv->rate_supported;
++      if (acx_debug & L_ASSOC) {
++              printk("new ratevector: ");
++              acx_dump_bytes(priv->rate_supported, priv->rate_supported_len);
++      }
++      FN_EXIT0;
++}
++
++
++/*----------------------------------------------------------------
++* acx_l_sta_list_init
++*----------------------------------------------------------------*/
++static void
++acx_l_sta_list_init(wlandevice_t *priv)
++{
++      FN_ENTER;
++      memset(priv->sta_hash_tab, 0, sizeof(priv->sta_hash_tab));
++      memset(priv->sta_list, 0, sizeof(priv->sta_list));
++      FN_EXIT0;
++}
++
++
++/*----------------------------------------------------------------
++* acx_l_sta_list_get_from_hash
++*----------------------------------------------------------------*/
++static inline client_t*
++acx_l_sta_list_get_from_hash(wlandevice_t *priv, const u8 *address)
++{
++      return priv->sta_hash_tab[address[5] % VEC_SIZE(priv->sta_hash_tab)];
++}
++
++
++/*----------------------------------------------------------------
++* acx_l_sta_list_get
++*----------------------------------------------------------------*/
++client_t*
++acx_l_sta_list_get(wlandevice_t *priv, const u8 *address)
++{
++      client_t *client;
++      FN_ENTER;
++      client = acx_l_sta_list_get_from_hash(priv, 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(wlandevice_t *priv, client_t *victim)
++{
++      client_t *client, *next;
++
++      client = acx_l_sta_list_get_from_hash(priv, 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(wlandevice_t *priv)
++{
++      int i;
++      unsigned long age, oldest_age;
++      client_t *client, *oldest;
++
++      FN_ENTER;
++
++      oldest = &priv->sta_list[0];
++      oldest_age = 0;
++      for (i = 0; i < VEC_SIZE(priv->sta_list); i++) {
++              client = &priv->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(priv, 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(wlandevice_t *priv, const u8 *address)
++{
++      client_t *client;
++      int index;
++
++      FN_ENTER;
++
++      client = acx_l_sta_list_alloc(priv);
++
++      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 = priv->rate_basic;
++      client->rate_cfg = priv->rate_basic;
++      client->rate_cur = 1 << lowest_bit(priv->rate_basic);
++
++      index = address[5] % VEC_SIZE(priv->sta_hash_tab);
++      client->next = priv->sta_hash_tab[index];
++      priv->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(wlandevice_t *priv, const u8 *address)
++{
++      client_t *client = acx_l_sta_list_get(priv, address);
++      if (!client)
++              client = acx_l_sta_list_add(priv, 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(wlandevice_t *priv, u16 new_status)
++{
++#define QUEUE_OPEN_AFTER_ASSOC 1 /* this really seems to be needed now */
++      u16 old_status = priv->status;
++
++      FN_ENTER;
++
++      acxlog(L_ASSOC, "%s(%d):%s\n",
++             __func__, new_status, acx_get_status_name(new_status));
++
++#if WIRELESS_EXT > 13 /* wireless_send_event() and SIOCGIWSCAN */
++      /* 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(priv->netdev, SIOCGIWSCAN, &wrqu, NULL);
++
++              wrqu.data.length = 0;
++              wrqu.data.flags = 0;
++              MAC_COPY(wrqu.ap_addr.sa_data, priv->bssid);
++              wrqu.ap_addr.sa_family = ARPHRD_ETHER;
++              wireless_send_event(priv->netdev, 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(priv->netdev, SIOCGIWAP, &wrqu, NULL);
++      }
++#endif
++
++      priv->status = new_status;
++
++      switch (new_status) {
++      case ACX_STATUS_1_SCANNING:
++              priv->scan_retries = 0;
++              /* 1.0 s initial scan time */
++              acx_set_timer(priv, 1000000);
++              break;
++      case ACX_STATUS_2_WAIT_AUTH:
++      case ACX_STATUS_3_AUTHENTICATED:
++              priv->auth_or_assoc_retries = 0;
++              acx_set_timer(priv, 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(priv->netdev, "after association");
++                      acx_wake_queue(priv->netdev, "after association");
++              }
++      } else {
++              /* not associated any more, so let's kill carrier */
++              if (old_status >= ACX_STATUS_4_ASSOCIATED) {
++                      acx_carrier_off(priv->netdev, "after losing association");
++                      acx_stop_queue(priv->netdev, "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;
++      wlandevice_t *priv = (wlandevice_t *)address;
++
++      FN_ENTER;
++
++      acx_lock(priv, flags);
++
++      acxlog(L_DEBUG|L_ASSOC, "%s: priv->status=%d (%s)\n",
++              __func__, priv->status, acx_get_status_name(priv->status));
++
++      switch (priv->status) {
++      case ACX_STATUS_1_SCANNING:
++              /* was set to 0 by set_status() */
++              if (++priv->scan_retries < 7) {
++                      acx_set_timer(priv, 1000000);
++                      /* used to interrogate for scan status.
++                      ** We rely on SCAN_COMPLETE IRQ instead */
++                      acxlog(L_ASSOC, "continuing scan (%d sec)\n",
++                                      priv->scan_retries);
++              } else {
++                      acxlog(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_after_interrupt_task(priv,
++                              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 (++priv->auth_or_assoc_retries < 10) {
++                      acxlog(L_ASSOC, "resend authen1 request (attempt %d)\n",
++                                      priv->auth_or_assoc_retries + 1);
++                      acx_l_transmit_authen1(priv);
++              } else {
++                      /* time exceeded: fall back to scanning mode */
++                      acxlog(L_ASSOC,
++                             "authen1 request reply timeout, giving up\n");
++                      /* we are a STA, need to find AP anyhow */
++                      acx_set_status(priv, ACX_STATUS_1_SCANNING);
++                      acx_schedule_after_interrupt_task(priv, ACX_AFTER_IRQ_RESTART_SCAN);
++              }
++              /* used to be 1500000, but some other driver uses 2.5s */
++              acx_set_timer(priv, 2500000);
++              break;
++      case ACX_STATUS_3_AUTHENTICATED:
++              /* was set to 0 by set_status() */
++              if (++priv->auth_or_assoc_retries < 10) {
++                      acxlog(L_ASSOC, "resend assoc request (attempt %d)\n",
++                                      priv->auth_or_assoc_retries + 1);
++                      acx_l_transmit_assoc_req(priv);
++              } else {
++                      /* time exceeded: give up */
++                      acxlog(L_ASSOC,
++                              "association request reply timeout, giving up\n");
++                      /* we are a STA, need to find AP anyhow */
++                      acx_set_status(priv, ACX_STATUS_1_SCANNING);
++                      acx_schedule_after_interrupt_task(priv, ACX_AFTER_IRQ_RESTART_SCAN);
++              }
++              acx_set_timer(priv, 2500000); /* see above */
++              break;
++      case ACX_STATUS_4_ASSOCIATED:
++      default:
++              break;
++      }
++
++      acx_unlock(priv, flags);
++
++      FN_EXIT0;
++}
++
++
++/*------------------------------------------------------------------------------
++ * acx_set_timer
++ *
++ * Sets the 802.11 state management timer's timeout.
++ *----------------------------------------------------------------------------*/
++void
++acx_set_timer(wlandevice_t *priv, int timeout_us)
++{
++      FN_ENTER;
++
++      acxlog(L_DEBUG|L_IRQ, "%s(%u ms)\n", __func__, timeout_us/1000);
++      if (!(priv->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 (priv->mgmt_timer.function) {
++              mod_timer(&priv->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 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(wlandevice_t *priv, 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(priv, 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(priv, da, WLAN_MGMT_REASON_CLASS2_NONAUTH);
++              goto bad;
++      }
++
++      clt->used = CLIENT_ASSOCIATED_3;
++
++      if (clt->aid == 0) {
++              clt->aid = ++priv->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 & priv->rate_oper;
++      if (!clt->rate_cfg) clt->rate_cfg = 1 << lowest_bit(priv->rate_oper);
++      clt->rate_cur = 1 << lowest_bit(clt->rate_cfg);
++      clt->fallback_count = clt->stepup_count = 0;
++      clt->ignore_count = 16;
++
++      tx = acx_l_alloc_tx(priv);
++      if (!tx)
++              goto bad;
++      head = acx_l_get_txbuf(priv, tx);
++      if (!head)
++              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, sa); */
++      MAC_COPY(head->sa, priv->dev_addr);
++      MAC_COPY(head->bssid, bssid);
++      head->seq = req->hdr->seq;
++
++      body->cap_info = host2ieee16(priv->capabilities);
++      body->status = host2ieee16(0);
++      body->aid = host2ieee16(clt->aid);
++      p = wlan_fill_ie_rates((u8*)&body->rates, priv->rate_supported_len,
++                                                      priv->rate_supported);
++      p = wlan_fill_ie_rates_ext(p, priv->rate_supported_len,
++                                                      priv->rate_supported);
++
++      acx_l_tx_data(priv, 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 a hell is ReAuth.
++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(wlandevice_t *priv, 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(priv, 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(priv, da, WLAN_MGMT_REASON_CLASS2_NONAUTH);
++              goto bad;
++      }
++
++      clt->used = CLIENT_ASSOCIATED_3;
++      if (clt->aid == 0) {
++              clt->aid = ++priv->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 & priv->rate_oper;
++      if (!clt->rate_cfg) clt->rate_cfg = 1 << lowest_bit(priv->rate_oper);
++      clt->rate_cur = 1 << lowest_bit(clt->rate_cfg);
++      clt->fallback_count = clt->stepup_count = 0;
++      clt->ignore_count = 16;
++
++      tx = acx_l_alloc_tx(priv);
++      if (!tx)
++              goto ok;
++      head = acx_l_get_txbuf(priv, tx);
++      if (!head)
++              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, sa); */
++      MAC_COPY(head->sa, priv->dev_addr);
++      MAC_COPY(head->bssid, bssid);
++      head->seq = req->hdr->seq;
++
++      /* IEs: 1. caps */
++      body->cap_info = host2ieee16(priv->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, priv->rate_supported_len,
++                                                      priv->rate_supported);
++      /* 5. ext supp rates */
++      p = wlan_fill_ie_rates_ext(p, priv->rate_supported_len,
++                                                      priv->rate_supported);
++
++      acx_l_tx_data(priv, 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(wlandevice_t *priv, const wlan_fr_disassoc_t *req)
++{
++      const u8 *ta;
++      client_t *clt;
++
++      FN_ENTER;
++
++      ta = req->hdr->a2;
++      clt = acx_l_sta_list_get(priv, 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(priv, 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(wlandevice_t *priv, 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("DEAUTHEN priv->addr=", priv->dev_addr, " ");
++              acx_print_mac("a1", hdr->a1, " ");
++              acx_print_mac("a2", hdr->a2, " ");
++              acx_print_mac("a3", hdr->a3, " ");
++              acx_print_mac("priv->bssid", priv->bssid, "\n");
++      }
++
++      if (!mac_is_equal(priv->dev_addr, hdr->a1)) {
++              goto end;
++      }
++
++      acxlog_mac(L_DEBUG, "STA ", hdr->a2, " sent us deauthen packet\n");
++
++      client = acx_l_sta_list_get(priv, 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(wlandevice_t *priv, const wlan_fr_disassoc_t *req)
++{
++      FN_ENTER;
++
++      if (!priv->ap_client) {
++              /* Hrm, we aren't assoc'ed yet anyhow... */
++              goto end;
++      }
++      if (mac_is_equal(priv->dev_addr, req->hdr->a1)) {
++              acx_l_transmit_deauthen(priv, priv->bssid,
++                              WLAN_MGMT_REASON_DEAUTH_LEAVING);
++              /* Start scan anew */
++              SET_BIT(priv->set_mask, GETSET_RESCAN);
++              acx_schedule_after_interrupt_task(priv, ACX_AFTER_IRQ_UPDATE_CARD_CFG);
++      }
++end:
++      FN_EXIT0;
++}
++
++
++/*----------------------------------------------------------------
++* acx_l_process_deauth_from_ap
++*----------------------------------------------------------------*/
++static void
++acx_l_process_deauth_from_ap(wlandevice_t *priv, const wlan_fr_deauthen_t *req)
++{
++      FN_ENTER;
++
++      if (!priv->ap_client) {
++              /* Hrm, we aren't assoc'ed yet anyhow... */
++              goto end;
++      }
++      /* Chk: is ta is verified to be from our AP? */
++      if (mac_is_equal(priv->dev_addr, req->hdr->a1)) {
++              acxlog(L_DEBUG, "AP sent us deauth packet\n");
++              /* not needed: acx_set_status(priv, ACX_STATUS_1_SCANNING) */
++              SET_BIT(priv->set_mask, GETSET_RESCAN);
++              acx_schedule_after_interrupt_task(priv, 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().
++ *
++ * Arguments:
++ *    rxdesc: the rxhostdesc to pull the data from
++ *    priv:   the acx100 private struct of the interface
++ *----------------------------------------------------------------------------*/
++static void
++acx_l_rx(wlandevice_t *priv, rxbuffer_t *rxbuf)
++{
++      FN_ENTER;
++      if (likely(priv->dev_state_mask & ACX_STATE_IFACE_UP)) {
++              struct sk_buff *skb;
++              skb = acx_rxbuf_to_ether(priv, rxbuf);
++              if (likely(skb)) {
++                      netif_rx(skb);
++                      priv->netdev->last_rx = jiffies;
++                      priv->stats.rx_packets++;
++                      priv->stats.rx_bytes += skb->len;
++              }
++      }
++      FN_EXIT0;
++}
++
++
++/*----------------------------------------------------------------
++* acx_l_process_data_frame_master
++*----------------------------------------------------------------*/
++static int
++acx_l_process_data_frame_master(wlandevice_t *priv, 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(priv, rxbuf);
++
++      switch (WF_FC_FROMTODSi & hdr->fc) {
++      case 0:
++      case WF_FC_FROMDSi:
++              acxlog(L_DEBUG, "ap->sta or adhoc->adhoc data frame ignored\n");
++              goto done;
++      case WF_FC_TODSi:
++              break;
++      default: /* WF_FC_FROMTODSi */
++              acxlog(L_DEBUG, "wds data frame ignored (todo)\n");
++              goto done;
++      }
++
++      /* check if it is our BSSID, if not, leave */
++      if (!mac_is_equal(priv->bssid, hdr->a1)) {
++              goto done;
++      }
++
++      if (mac_is_equal(priv->dev_addr, hdr->a3)) {
++              /* this one is for us */
++              acx_l_rx(priv, rxbuf);
++      } else {
++              if (mac_is_bcast(hdr->a3)) {
++                      /* this one is bcast, rx it too */
++                      acx_l_rx(priv, rxbuf);
++              }
++              tx = acx_l_alloc_tx(priv);
++              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, priv->bssid);
++              /* To_DS = 0, From_DS = 1 */
++              hdr->fc = WF_FC_FROMDSi + WF_FTYPE_DATAi;
++
++              len = RXBUF_BYTES_RCVD(rxbuf);
++              txbuf = acx_l_get_txbuf(priv, tx);
++              if (txbuf) {
++                      memcpy(txbuf, &rxbuf->hdr_a3, len);
++                      acx_l_tx_data(priv, tx, len);
++              }
++      }
++done:
++      result = OK;
++fail:
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/*----------------------------------------------------------------
++* acx_l_process_data_frame_client
++*----------------------------------------------------------------*/
++static int
++acx_l_process_data_frame_client(wlandevice_t *priv, rxbuffer_t *rxbuf)
++{
++      const u8 *da, *bssid;
++      const wlan_hdr_t *hdr;
++      netdevice_t *dev = priv->netdev;
++      int result = NOT_OK;
++
++      FN_ENTER;
++
++      if (ACX_STATUS_4_ASSOCIATED != priv->status)
++              goto drop;
++
++      hdr = acx_get_wlan_hdr(priv, rxbuf);
++
++      switch (WF_FC_FROMTODSi & hdr->fc) {
++      case 0:
++              if (priv->mode != ACX_MODE_0_ADHOC) {
++                      acxlog(L_DEBUG, "adhoc->adhoc data frame ignored\n");
++                      goto drop;
++              }
++              bssid = hdr->a3;
++              break;
++      case WF_FC_FROMDSi:
++              if (priv->mode != ACX_MODE_2_STA) {
++                      acxlog(L_DEBUG, "ap->sta data frame ignored\n");
++                      goto drop;
++              }
++              bssid = hdr->a2;
++              break;
++      case WF_FC_TODSi:
++              acxlog(L_DEBUG, "sta->ap data frame ignored\n");
++              goto drop;
++      default: /* WF_FC_FROMTODSi: wds->wds */
++              acxlog(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(" priv->bssid=", priv->bssid, "");
++              acx_print_mac(" priv->addr=", priv->dev_addr, "\n");
++      }
++
++      /* promiscuous mode --> receive all packets */
++      if (unlikely(dev->flags & IFF_PROMISC))
++              goto process;
++
++      /* FIRST, check if it is our BSSID */
++      if (!mac_is_equal(priv->bssid, bssid)) {
++              /* is not our BSSID, so bail out */
++              goto drop;
++      }
++
++      /* then, check if it is our address */
++      if (mac_is_equal(priv->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 (dev->flags & IFF_ALLMULTI)
++                      goto process;
++
++              /* FIXME: check against the list of
++               * multicast addresses that are configured
++               * for the interface (ifconfig) */
++              acxlog(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;
++      }
++
++      acxlog(L_DEBUG, "rx: foreign packet, dropping\n");
++      goto drop;
++process:
++      /* receive packet */
++      acx_l_rx(priv, 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.
++* NB: wlan_mgmt_decode_XXX are dev-independent (shoudnt have been named acx_XXX)
++*----------------------------------------------------------------*/
++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(wlandevice_t *priv, 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(priv, rxbuf);
++
++      /* Management frames never have these set */
++      if (WF_FC_FROMTODSi & hdr->fc) {
++              FN_EXIT1(NOT_OK);
++              return NOT_OK;
++      }
++
++      len = RXBUF_BYTES_RCVD(rxbuf);
++      if (WF_FC_ISWEPi & hdr->fc)
++              len -= 0x10;
++
++      adhoc = (priv->mode == ACX_MODE_0_ADHOC);
++      sta_scan = ((priv->mode == ACX_MODE_2_STA)
++               && (priv->status != ACX_STATUS_4_ASSOCIATED));
++      sta = ((priv->mode == ACX_MODE_2_STA)
++          && (priv->status == ACX_STATUS_4_ASSOCIATED));
++      ap = (priv->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(priv, &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, priv->bssid)
++               && mac_is_equal(hdr->a3, priv->bssid)) {
++                      acx_l_transmit_assocresp(priv, &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(priv, &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(priv, &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(priv, &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(priv, &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(priv, &parsed.disassoc);
++              else
++                      acx_l_process_disassoc_from_sta(priv, &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(priv, &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(priv, &parsed.deauthen);
++              else
++                      acx_l_process_deauth_from_sta(priv, &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(wlandevice_t *priv, 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(wlandevice_t *priv, 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(priv, 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(priv, ebx);
++      if (client)
++              result = NOT_OK;
++      else {
++#ifdef IS_IT_BROKEN
++              acxlog(L_DEBUG|L_XFER, "<transmit_deauth 7>\n");
++              acx_l_transmit_deauthen(priv, ebx,
++                      WLAN_MGMT_REASON_CLASS2_NONAUTH);
++#else
++              acxlog(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(wlandevice_t *priv, 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, priv->dev_addr)) {
++              acxlog(L_ASSOC, "huh, scan found our own MAC!?\n");
++              goto ok; /* just skip this one silently */
++      }
++
++      bss = acx_l_sta_list_get_or_add(priv, hdr->a2);
++
++      /* NB: be careful modifying bss data! It may be one
++      ** of already known clients (like our AP is 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_after_interrupt_task(priv, ACX_AFTER_IRQ_CMD_STOP_SCAN);
++              /* TODO: a nice comment what below call achieves --vda */
++              acx_set_status(priv, 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",
++                                                  priv->netdev->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 = priv->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 */
++      acxlog(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(wlandevice_t *priv, const wlan_fr_assocresp_t *req)
++{
++      const wlan_hdr_t *hdr;
++      int res = OK;
++
++      FN_ENTER;
++      hdr = req->hdr;
++
++      if ((ACX_MODE_2_STA == priv->mode)
++       && mac_is_equal(priv->dev_addr, hdr->a1)) {
++              u16 st = ieee2host16(*(req->status));
++              if (WLAN_MGMT_STATUS_SUCCESS == st) {
++                      priv->aid = ieee2host16(*(req->aid));
++                      /* tell the card we are associated when we are out of interrupt context */
++                      acx_schedule_after_interrupt_task(priv, ACX_AFTER_IRQ_CMD_ASSOCIATE);
++              } else {
++
++                      /* TODO: we shall delete peer from sta_list, and try other candidates... */
++
++                      printk("%s: association FAILED: peer sent "
++                              "response code %d (%s)\n",
++                              priv->netdev->name, st, get_status_string(st));
++                      res = NOT_OK;
++              }
++      }
++
++      FN_EXIT1(res);
++      return res;
++}
++
++
++/*----------------------------------------------------------------
++* acx_l_process_reassocresp
++*----------------------------------------------------------------*/
++static int
++acx_l_process_reassocresp(wlandevice_t *priv, 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(priv->dev_addr, hdr->a1)) {
++              goto end;
++      }
++      st = ieee2host16(*(req->status));
++      if (st == WLAN_MGMT_STATUS_SUCCESS) {
++              acx_set_status(priv, ACX_STATUS_4_ASSOCIATED);
++              result = OK;
++      } else {
++              printk("%s: reassociation FAILED: peer sent "
++                      "response code %d (%s)\n",
++                      priv->netdev->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(wlandevice_t *priv, 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 priv->addr=", priv->dev_addr, " ");
++              acx_print_mac("a1=", hdr->a1, " ");
++              acx_print_mac("a2=", hdr->a2, " ");
++              acx_print_mac("a3=", hdr->a3, " ");
++              acx_print_mac("priv->bssid=", priv->bssid, "\n");
++      }
++
++      if (!mac_is_equal(priv->dev_addr, hdr->a1)
++       || !mac_is_equal(priv->bssid, hdr->a3)) {
++              result = OK;
++              goto end;
++      }
++
++      alg = ieee2host16(*(req->auth_alg));
++      seq = ieee2host16(*(req->auth_seq));
++      status = ieee2host16(*(req->status));
++
++      ap = (priv->mode == ACX_MODE_3_AP);
++
++      if (priv->auth_alg <= 1) {
++              if (priv->auth_alg != alg) {
++                      acxlog(L_ASSOC, "authentication algorithm mismatch: "
++                              "want: %d, req: %d\n", priv->auth_alg, alg);
++                      result = NOT_OK;
++                      goto end;
++              }
++      }
++      acxlog(L_ASSOC, "algorithm is ok\n");
++
++      if (ap) {
++              clt = acx_l_sta_list_get_or_add(priv, hdr->a2);
++              if (STA_LIST_ADD_CAN_FAIL && !clt) {
++                      acxlog(L_ASSOC, "could not allocate room for client\n");
++                      result = NOT_OK;
++                      goto end;
++              }
++      } else {
++              clt = priv->ap_client;
++              if (!mac_is_equal(clt->address, hdr->a2)) {
++                      printk("%s: malformed auth frame from AP?!\n",
++                                      priv->netdev->name);
++                      result = NOT_OK;
++                      goto end;
++              }
++      }
++
++      /* now check which step in the authentication sequence we are
++       * currently in, and act accordingly */
++      acxlog(L_ASSOC, "acx_process_authen auth seq step %d\n", seq);
++      switch (seq) {
++      case 1:
++              if (!ap)
++                      break;
++              acx_l_transmit_authen2(priv, req, clt);
++              break;
++      case 2:
++              if (ap)
++                      break;
++              if (status == WLAN_MGMT_STATUS_SUCCESS) {
++                      if (alg == WLAN_AUTH_ALG_OPENSYSTEM) {
++                              acx_set_status(priv, ACX_STATUS_3_AUTHENTICATED);
++                              acx_l_transmit_assoc_req(priv);
++                      } else
++                      if (alg == WLAN_AUTH_ALG_SHAREDKEY) {
++                              acx_l_transmit_authen3(priv, req);
++                      }
++              } else {
++                      printk("%s: auth FAILED: peer sent "
++                              "response code %d (%s), "
++                              "still waiting for authentication\n",
++                              priv->netdev->name,
++                              status, get_status_string(status));
++                      acx_set_status(priv, 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(priv, 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(priv, ACX_STATUS_3_AUTHENTICATED);
++              acxlog(L_ASSOC, "Authenticated!\n");
++              /* now that we're authenticated, request association */
++              acx_l_transmit_assoc_req(priv);
++              break;
++      }
++      result = NOT_OK;
++end:
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/*----------------------------------------------------------------
++* acx_gen_challenge
++*----------------------------------------------------------------*/
++static 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(wlandevice_t *priv, 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(priv);
++      if (!tx)
++              goto bad;
++      head = acx_l_get_txbuf(priv, tx);
++      if (!head)
++              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, priv->dev_addr);
++      MAC_COPY(head->bssid, priv->bssid);
++      head->seq = 0;
++
++      acxlog(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(priv, 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(wlandevice_t *priv)
++{
++      struct tx *tx;
++      struct wlan_hdr_mgmt *head;
++      struct auth_frame_body *body;
++
++      FN_ENTER;
++
++      acxlog(L_ASSOC, "Sending authentication1 request, "
++              "awaiting response!\n");
++
++      tx = acx_l_alloc_tx(priv);
++      if (!tx)
++              goto bad;
++      head = acx_l_get_txbuf(priv, tx);
++      if (!head)
++              goto bad;
++      body = (void*)(head + 1);
++
++      head->fc = WF_FSTYPE_AUTHENi;
++      head->dur = host2ieee16(0x8000);
++      MAC_COPY(head->da, priv->bssid);
++      MAC_COPY(head->sa, priv->dev_addr);
++      MAC_COPY(head->bssid, priv->bssid);
++      head->seq = 0;
++
++      body->auth_alg = host2ieee16(priv->auth_alg);
++      body->auth_seq = host2ieee16(1);
++      body->status = host2ieee16(0);
++
++      acx_l_tx_data(priv, 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(wlandevice_t *priv, 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(priv);
++      if (!tx)
++              goto bad;
++      head = acx_l_get_txbuf(priv, tx);
++      if (!head)
++              goto bad;
++      body = (void*)(head + 1);
++
++      head->fc = WF_FSTYPE_AUTHENi; /* 0xb0 */
++      head->dur = req->hdr->dur;
++      MAC_COPY(head->da, req->hdr->a2);
++      /* MAC_COPY(head->sa, req->hdr->a1); */
++      MAC_COPY(head->sa, priv->dev_addr);
++      MAC_COPY(head->bssid, req->hdr->a3);
++      head->seq = 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(priv, 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(wlandevice_t *priv, 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(priv);
++      if (!tx)
++              goto ok;
++      head = acx_l_get_txbuf(priv, tx);
++      if (!head)
++              goto ok;
++      body = (void*)(head + 1);
++
++      head->fc = WF_FC_ISWEPi + WF_FSTYPE_AUTHENi;
++      /* FIXME: is this needed?? authen4 does it...
++      head->dur = req->hdr->dur;
++      head->seq = req->hdr->seq;
++      */
++      MAC_COPY(head->da, priv->bssid);
++      MAC_COPY(head->sa, priv->dev_addr);
++      MAC_COPY(head->bssid, priv->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;
++
++      acxlog(L_ASSOC|L_XFER, "transmit_authen3!\n");
++
++      acx_l_tx_data(priv, tx, packet_len);
++ok:
++      FN_EXIT1(OK);
++      return OK;
++}
++
++
++/*----------------------------------------------------------------
++* acx_l_transmit_authen4
++*----------------------------------------------------------------*/
++static int
++acx_l_transmit_authen4(wlandevice_t *priv, 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(priv);
++      if (!tx)
++              goto ok;
++      head = acx_l_get_txbuf(priv, tx);
++      if (!head)
++              goto ok;
++      body = (void*)(head + 1);
++
++      head->fc = WF_FSTYPE_AUTHENi; /* 0xb0 */
++      head->dur = req->hdr->dur;
++      MAC_COPY(head->da, req->hdr->a2);
++      /* MAC_COPY(head->sa, req->hdr->a1); */
++      MAC_COPY(head->sa, priv->dev_addr);
++      MAC_COPY(head->bssid, req->hdr->a3);
++      head->seq = 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(priv, tx, WLAN_HDR_A3_LEN + 2 + 2 + 2);
++ok:
++      FN_EXIT1(OK);
++      return OK;
++}
++
++
++/*----------------------------------------------------------------
++* acx_l_transmit_assoc_req
++*
++* priv->ap_client is a current candidate AP here
++*----------------------------------------------------------------*/
++static int
++acx_l_transmit_assoc_req(wlandevice_t *priv)
++{
++      struct tx *tx;
++      struct wlan_hdr_mgmt *head;
++      u8 *body, *p, *prate;
++      unsigned int packet_len;
++      u16 cap;
++
++      FN_ENTER;
++
++      acxlog(L_ASSOC, "sending association request, "
++                      "awaiting response. NOT ASSOCIATED YET\n");
++      tx = acx_l_alloc_tx(priv);
++      if (!tx)
++              goto bad;
++      head = acx_l_get_txbuf(priv, tx);
++      if (!head)
++              goto bad;
++      body = (void*)(head + 1);
++
++      head->fc = WF_FSTYPE_ASSOCREQi;
++      head->dur = host2ieee16(0x8000);
++      MAC_COPY(head->da, priv->bssid);
++      MAC_COPY(head->sa, priv->dev_addr);
++      MAC_COPY(head->bssid, priv->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 (priv->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 (priv->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 (priv->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(priv->listen_interval); p += 2;
++      /* 3. ESSID */
++      p = wlan_fill_ie_ssid(p,
++                      strlen(priv->essid_for_assoc), priv->essid_for_assoc);
++      /* 4. supp rates */
++      prate = p;
++      p = wlan_fill_ie_rates(p,
++                      priv->rate_supported_len, priv->rate_supported);
++      /* 5. ext supp rates */
++      p = wlan_fill_ie_rates_ext(p,
++                      priv->rate_supported_len, priv->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);
++
++      acxlog(L_ASSOC, "association: requesting caps 0x%04X, ESSID '%s'\n",
++              cap, priv->essid_for_assoc);
++
++      acx_l_tx_data(priv, 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(priv, clt) - kick this client (we're an AP)
++* acx_l_transmit_disassoc(priv, NULL) - leave BSSID (we're a STA)
++*----------------------------------------------------------------*/
++#ifdef BROKEN
++int
++acx_l_transmit_disassoc(wlandevice_t *priv, 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(priv);
++              if (!tx)
++                      goto bad;
++              head = acx_l_get_txbuf(priv, tx);
++              if (!head)
++                      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, priv->bssid);
++              MAC_COPY(head->sa, priv->dev_addr);
++              MAC_COPY(head->bssid, priv->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(priv, 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 priv->sta_list:
++*     if priv->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 priv->ap_client to the chosen struct client
++*     sets priv->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(wlandevice_t *priv)
++{
++      struct client *bss;
++      unsigned long flags;
++      u16 needed_cap;
++      int i;
++      int idx_found = -1;
++      int result = OK;
++
++      FN_ENTER;
++
++      switch (priv->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", priv->mode);
++              dump_stack();
++              goto end;
++      }
++
++      acx_lock(priv, flags);
++
++      /* TODO: sta_iterator hiding implementation would be nice here... */
++
++      for (i = 0; i < VEC_SIZE(priv->sta_list); i++) {
++              bss = &priv->sta_list[i];
++              if (!bss->used) continue;
++
++              acxlog(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(priv->ap))
++                      if (!mac_is_equal(bss->bssid, priv->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",
++                              priv->netdev->name, MAC(bss->address));
++                      continue;
++              }
++              acxlog(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",
++                              priv->netdev->name, MAC(bss->address));
++                      continue;
++              }
++
++              /* do we support all basic rates of this peer? */
++              if ((bss->rate_bas & priv->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",
++                              priv->netdev->name, MAC(bss->address),
++                              bss->rate_bas, priv->rate_oper);
++                      continue;
++#else
++                      printk("%s: peer "MACSTR": incompatible basic rates "
++                              "(AP requests 0x%04X, we have 0x%04X). "
++                              "Considering anyway...\n",
++                              priv->netdev->name, MAC(bss->address),
++                              bss->rate_bas, priv->rate_oper);
++#endif
++              }
++
++              if ( !(priv->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",
++                              priv->netdev->name, MAC(bss->address),
++                              bss->channel);
++                      continue; /* keep looking */
++              }
++
++              if (!priv->essid_active || !strcmp(bss->essid, priv->essid)) {
++                      acxlog(L_ASSOC,
++                             "found station with matching ESSID! ('%s' "
++                             "station, '%s' config)\n",
++                             bss->essid,
++                             (priv->essid_active) ? priv->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 == priv->channel)
++                              break;
++              } else
++              if (!bss->essid[0]
++               || ((' ' == bss->essid[0]) && !bss->essid[1])
++              ) {
++                      /* 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;
++                      acxlog(L_ASSOC, "found station with empty or "
++                              "single-space (hidden) SSID, considering "
++                              "for assoc attempt\n");
++                      /* ...and keep looking for better matches */
++              } else {
++                      acxlog(L_ASSOC, "ESSID doesn't match! ('%s' "
++                              "station, '%s' config)\n",
++                              bss->essid,
++                              (priv->essid_active) ? priv->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 = &priv->sta_list[idx_found];
++              priv->ap_client = bss;
++
++              if (bss->essid[0] == '\0') {
++                      /* if the ESSID of the station we found is empty
++                       * (no broadcast), then use user configured ESSID
++                       * instead */
++                      essid_src = priv->essid;
++                      essid_len = priv->essid_len;
++              } else {
++                      essid_src = bss->essid;
++                      essid_len = strlen(bss->essid);
++              }
++
++              acx_update_capabilities(priv);
++
++              memcpy(priv->essid_for_assoc, essid_src, essid_len);
++              priv->essid_for_assoc[essid_len] = '\0';
++              priv->channel = bss->channel;
++              MAC_COPY(priv->bssid, bss->bssid);
++
++              bss->rate_cfg = (bss->rate_cap & priv->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: ", priv->bssid, ", joining\n");
++
++              /* TODO: do we need to switch to the peer's channel first? */
++
++              if (ACX_MODE_0_ADHOC == priv->mode) {
++                      acx_set_status(priv, ACX_STATUS_4_ASSOCIATED);
++              } else {
++                      acx_l_transmit_authen1(priv);
++                      acx_set_status(priv, ACX_STATUS_2_WAIT_AUTH);
++              }
++      } else { /* idx_found == -1 */
++              /* uh oh, no station found in range */
++              if (ACX_MODE_0_ADHOC == priv->mode) {
++                      printk("%s: no matching station found in range, "
++                              "generating our own IBSS instead\n",
++                              priv->netdev->name);
++                      /* we do it hostap way: */
++                      MAC_COPY(priv->bssid, priv->dev_addr);
++                      priv->bssid[0] |= 0x02; /* 'local assigned addr' bit */
++                      /* add IBSS bit to our caps... */
++                      acx_update_capabilities(priv);
++                      acx_set_status(priv, 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 */
++                      acxlog(L_ASSOC,
++                              "no matching station found in range yet\n");
++                      acx_set_status(priv, ACX_STATUS_1_SCANNING);
++                      result = NOT_OK;
++              }
++      }
++
++      acx_unlock(priv, flags);
++
++      if (idx_found != -1) {
++              if (ACX_MODE_0_ADHOC == priv->mode) {
++                      /* need to update channel in beacon template */
++                      SET_BIT(priv->set_mask, SET_TEMPLATES);
++                      if (ACX_STATE_IFACE_UP & priv->dev_state_mask)
++                              acx_s_update_card_settings(priv, 0, 0);
++              }
++              /* Inform firmware on our decision to start or join BSS */
++              acx_s_cmd_join_bssid(priv, priv->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
++*/
++#if USE_FW_LOADER_26
++firmware_image_t*
++acx_s_read_fw(struct device *dev, const char *file, u32 *size)
++#else
++#undef acx_s_read_fw
++firmware_image_t*
++acx_s_read_fw(const char *file, u32 *size)
++#endif
++{
++      firmware_image_t *res;
++
++#if USE_FW_LOADER_LEGACY
++      mm_segment_t orgfs;
++      unsigned long page;
++      char *buffer;
++      struct file *inf;
++      int retval;
++      int offset;
++      char *filename;
++#endif
++
++#if USE_FW_LOADER_26
++      const struct firmware *fw_entry;
++
++      res = NULL;
++      acxlog(L_DEBUG, "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);
++#endif
++
++#if USE_FW_LOADER_LEGACY
++      printk("acx: firmware upload via firmware_dir module parameter "
++              "is deprecated. Switch to using hotplug\n");
++
++      res = NULL;
++      orgfs = get_fs(); /* store original fs */
++      set_fs(KERNEL_DS);
++
++      /* Read in whole file then check the size */
++      page = __get_free_page(GFP_KERNEL);
++      if (unlikely(0 == page)) {
++              printk("acx: no memory for firmware upload\n");
++              goto fail;
++      }
++
++      filename = kmalloc(PATH_MAX, GFP_KERNEL);
++      if (unlikely(!filename)) {
++              printk("acx: no memory for firmware upload\n");
++              goto fail;
++      }
++      if (!firmware_dir) {
++              firmware_dir = "/usr/share/acx";
++              acxlog(L_DEBUG, "no firmware directory specified "
++                      "via module parameter firmware_dir, "
++                      "using default %s\n", firmware_dir);
++      }
++      snprintf(filename, PATH_MAX, "%s/%s", firmware_dir, file);
++      acxlog(L_DEBUG, "reading firmware image '%s'\n", filename);
++
++      buffer = (char*)page;
++
++      /* Note that file must be given as absolute path:
++       * a relative path works on first loading,
++       * but any subsequent firmware loading during card
++       * eject/insert will fail, most likely since the first
++       * module loading happens in user space (and thus
++       * filp_open can figure out the absolute path from a
++       * relative path) whereas the card reinsert processing
++       * probably happens in kernel space where you don't have
++       * a current directory to be able to figure out an
++       * absolute path from a relative path... */
++      inf = filp_open(filename, O_RDONLY, 0);
++      kfree(filename);
++      if (OK != IS_ERR(inf)) {
++              const char *err;
++
++              switch (-PTR_ERR(inf)) {
++                      case 2: err = "file not found";
++                              break;
++                      default:
++                              err = "unknown error";
++                              break;
++              }
++              printk("acx: error %ld trying to open file '%s': %s\n",
++                                      -PTR_ERR(inf), file, err);
++              goto fail;
++      }
++
++      if (unlikely((NULL == inf->f_op) || (NULL == inf->f_op->read))) {
++              printk("acx: %s does not have a read method?!\n", file);
++              goto fail_close;
++      }
++
++      offset = 0;
++      do {
++              retval = inf->f_op->read(inf, buffer, PAGE_SIZE, &inf->f_pos);
++
++              if (unlikely(0 > retval)) {
++                      printk("acx: error %d reading file '%s'\n",
++                                                      -retval, file);
++                      vfree(res);
++                      res = NULL;
++              } else if (0 == retval) {
++                      if (0 == offset) {
++                              printk("acx: firmware image file "
++                                      "'%s' is empty?!\n", file);
++                      }
++              } else if (0 < retval) {
++                      /* allocate result buffer here if needed,
++                       * since we don't want to waste resources/time
++                       * (in case file opening/reading fails)
++                       * by doing allocation in front of the loop instead. */
++                      if (NULL == res) {
++                              *size = 8 + le32_to_cpu(*(u32 *)(4 + buffer));
++
++                              res = vmalloc(*size);
++                              if (NULL == res) {
++                                      printk("acx: unable to "
++                                              "allocate %u bytes for "
++                                              "firmware module upload\n",
++                                              *size);
++                                      goto fail_close;
++                              }
++                              acxlog(L_DEBUG, "allocated %u bytes "
++                                      "for firmware module loading\n",
++                                      *size);
++                      }
++                      if ((unlikely(offset + retval > *size))) {
++                              printk("acx: ERROR: allocation "
++                                      "was less than firmware image size?!\n");
++                              goto fail_close;
++                      }
++                      memcpy((u8*)res + offset, buffer, retval);
++                      offset += retval;
++              }
++      } while (0 < retval);
++
++fail_close:
++      retval = filp_close(inf, NULL);
++
++      if (unlikely(retval)) {
++              printk("acx: error %d closing file '%s'\n", -retval, file);
++      }
++
++      if (unlikely((NULL != res) && (offset != le32_to_cpu(res->size) + 8))) {
++              printk("acx: firmware is reporting a different size "
++                      "(0x%08X; 0x%08X was read)\n",
++                      le32_to_cpu(res->size) + 8, offset);
++              vfree(res);
++              res = NULL;
++      }
++
++fail:
++      if (page)
++              free_page(page);
++      set_fs(orgfs);
++#endif
++
++      /* checksum will be verified in write_fw, so don't bother here */
++      return res;
++}
++
++
++#ifdef POWER_SAVE_80211
++/*----------------------------------------------------------------
++* acx_s_activate_power_save_mode
++*----------------------------------------------------------------*/
++static void
++acx_s_activate_power_save_mode(wlandevice_t *priv)
++{
++      acx100_ie_powermgmt_t pm;
++
++      FN_ENTER;
++
++      acx_s_interrogate(priv, &pm, ACX1xx_IE_POWER_MGMT);
++      if (pm.wakeup_cfg != 0x81)
++              goto end;
++
++      pm.wakeup_cfg = 0;
++      pm.options = 0;
++      pm.hangover_period = 0;
++      acx_s_configure(priv, &pm, ACX1xx_IE_POWER_MGMT);
++end:
++      FN_EXIT0;
++}
++#endif
++
++
++/***********************************************************************
++** acx_s_set_wepkey
++*/
++static void
++acx100_s_set_wepkey(wlandevice_t *priv)
++{
++      ie_dot11WEPDefaultKey_t dk;
++      int i;
++
++      for (i = 0; i < DOT11_MAX_DEFAULT_WEP_KEYS; i++) {
++              if (priv->wep_keys[i].size != 0) {
++                      acxlog(L_INIT, "setting WEP key: %d with "
++                              "total size: %d\n", i, (int) priv->wep_keys[i].size);
++                      dk.action = 1;
++                      dk.keySize = priv->wep_keys[i].size;
++                      dk.defaultKeyNum = i;
++                      memcpy(dk.key, priv->wep_keys[i].key, dk.keySize);
++                      acx_s_configure(priv, &dk, ACX100_IE_DOT11_WEP_DEFAULT_KEY_WRITE);
++              }
++      }
++}
++
++static void
++acx111_s_set_wepkey(wlandevice_t *priv)
++{
++      acx111WEPDefaultKey_t dk;
++      int i;
++
++      for (i = 0; i < DOT11_MAX_DEFAULT_WEP_KEYS; i++) {
++              if (priv->wep_keys[i].size != 0) {
++                      acxlog(L_INIT, "setting WEP key: %d with "
++                              "total size: %d\n", i, (int) priv->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 = priv->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, priv->wep_keys[i].key, dk.keySize);
++                      acx_s_issue_cmd(priv, ACX1xx_CMD_WEP_MGMT, &dk, sizeof(dk));
++              }
++      }
++}
++
++static void
++acx_s_set_wepkey(wlandevice_t *priv)
++{
++      if (IS_ACX111(priv))
++              acx111_s_set_wepkey(priv);
++      else
++              acx100_s_set_wepkey(priv);
++}
++
++
++/***********************************************************************
++** 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...
++*/
++int
++acx100_s_init_wep(wlandevice_t *priv)
++{
++/*    int i;
++      acx100_cmd_wep_mgmt_t wep_mgmt;           size = 37 bytes */
++      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(priv, &pt, ACX1xx_IE_MEMORY_MAP)) {
++              goto fail;
++      }
++
++      acxlog(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(priv, &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;
++
++      acxlog(L_ASSOC, "%s: writing WEP options\n", __func__);
++      acx_s_configure(priv, &options, ACX100_IE_WEP_OPTIONS);
++
++      acx100_s_set_wepkey(priv);
++
++      if (priv->wep_keys[priv->wep_current_index].size != 0) {
++              acxlog(L_ASSOC, "setting active default WEP key number: %d\n",
++                              priv->wep_current_index);
++              dk.KeyID = priv->wep_current_index;
++              acx_s_configure(priv, &dk, ACX1xx_IE_DOT11_WEP_DEFAULT_KEY_SET); /* 0x1010 */
++      }
++      /* FIXME!!! wep_key_struct is filled nowhere! But priv
++       * is initialized to 0, and we don't REALLY need those keys either */
++/*            for (i = 0; i < 10; i++) {
++              if (priv->wep_key_struct[i].len != 0) {
++                      MAC_COPY(wep_mgmt.MacAddr, priv->wep_key_struct[i].addr);
++                      wep_mgmt.KeySize = cpu_to_le16(priv->wep_key_struct[i].len);
++                      memcpy(&wep_mgmt.Key, priv->wep_key_struct[i].key, le16_to_cpu(wep_mgmt.KeySize));
++                      wep_mgmt.Action = cpu_to_le16(1);
++                      acxlog(L_ASSOC, "writing WEP key %d (len %d)\n", i, le16_to_cpu(wep_mgmt.KeySize));
++                      if (OK == acx_s_issue_cmd(priv, ACX1xx_CMD_WEP_MGMT, &wep_mgmt, sizeof(wep_mgmt))) {
++                              priv->wep_key_struct[i].index = i;
++                      }
++              }
++      } */
++
++      /* now retrieve the updated WEPCacheEnd pointer... */
++      if (OK != acx_s_interrogate(priv, &pt, ACX1xx_IE_MEMORY_MAP)) {
++              printk("%s: ACX1xx_IE_MEMORY_MAP read #2 FAILED\n",
++                              priv->netdev->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(priv, &pt, ACX1xx_IE_MEMORY_MAP)) {
++              printk("%s: ACX1xx_IE_MEMORY_MAP write #2 FAILED\n",
++                              priv->netdev->name);
++              goto fail;
++      }
++      res = OK;
++
++fail:
++      FN_EXIT1(res);
++      return res;
++}
++
++
++/***********************************************************************
++*/
++static int
++acx_s_init_max_null_data_template(wlandevice_t *priv)
++{
++      struct acx_template_nullframe b;
++      int result;
++
++      FN_ENTER;
++      memset(&b, 0, sizeof(b));
++      b.size = cpu_to_le16(sizeof(b) - 2);
++      result = acx_s_issue_cmd(priv, ACX1xx_CMD_CONFIG_NULL_DATA, &b, sizeof(b));
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/***********************************************************************
++** acx_s_init_max_beacon_template
++*/
++static int
++acx_s_init_max_beacon_template(wlandevice_t *priv)
++{
++      struct acx_template_beacon b;
++      int result;
++
++      FN_ENTER;
++      memset(&b, 0, sizeof(b));
++      b.size = cpu_to_le16(sizeof(b) - 2);
++      result = acx_s_issue_cmd(priv, ACX1xx_CMD_CONFIG_BEACON, &b, sizeof(b));
++
++      FN_EXIT1(result);
++      return result;
++}
++
++/***********************************************************************
++** acx_s_init_max_tim_template
++*/
++static int
++acx_s_init_max_tim_template(wlandevice_t *priv)
++{
++      acx_template_tim_t t;
++
++      memset(&t, 0, sizeof(t));
++      t.size = cpu_to_le16(sizeof(t) - 2);
++      return acx_s_issue_cmd(priv, ACX1xx_CMD_CONFIG_TIM, &t, sizeof(t));
++}
++
++
++/***********************************************************************
++** acx_s_init_max_probe_response_template
++*/
++static int
++acx_s_init_max_probe_response_template(wlandevice_t *priv)
++{
++      struct acx_template_proberesp pr;
++
++      memset(&pr, 0, sizeof(pr));
++      pr.size = cpu_to_le16(sizeof(pr) - 2);
++
++      return acx_s_issue_cmd(priv, ACX1xx_CMD_CONFIG_PROBE_RESPONSE, &pr, sizeof(pr));
++}
++
++
++/***********************************************************************
++** acx_s_init_max_probe_request_template
++*/
++static int
++acx_s_init_max_probe_request_template(wlandevice_t *priv)
++{
++      union {
++              acx100_template_probereq_t p100;
++              acx111_template_probereq_t p111;
++      } pr;
++      int res;
++
++      FN_ENTER;
++      memset(&pr, 0, sizeof(pr));
++      pr.p100.size = cpu_to_le16(sizeof(pr) - 2);
++      res = acx_s_issue_cmd(priv, ACX1xx_CMD_CONFIG_PROBE_REQUEST, &pr, sizeof(pr));
++      FN_EXIT1(res);
++      return res;
++}
++
++
++/***********************************************************************
++** acx_s_set_tim_template
++**
++** 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(wlandevice_t *priv)
++{
++/* 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(priv, 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(wlandevice_t *priv,
++                                      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, priv->dev_addr);
++      MAC_COPY(templ->bssid, priv->bssid);
++
++      templ->beacon_interval = cpu_to_le16(priv->beacon_interval);
++      acx_update_capabilities(priv);
++      templ->cap = cpu_to_le16(priv->capabilities);
++
++      p = templ->variable;
++      p = wlan_fill_ie_ssid(p, priv->essid_len, priv->essid);
++      p = wlan_fill_ie_rates(p, priv->rate_supported_len, priv->rate_supported);
++      p = wlan_fill_ie_ds_parms(p, priv->channel);
++      /* NB: should go AFTER tim, but acx seem to keep tim last always */
++      p = wlan_fill_ie_rates_ext(p, priv->rate_supported_len, priv->rate_supported);
++
++      switch (priv->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;
++}
++
++
++/***********************************************************************
++** acx_s_set_beacon_template
++*/
++static int
++acx_s_set_beacon_template(wlandevice_t *priv)
++{
++      struct acx_template_beacon bcn;
++      int len, result;
++
++      FN_ENTER;
++
++      len = acx_fill_beacon_or_proberesp_template(priv, &bcn, WF_FSTYPE_BEACON);
++      result = acx_s_issue_cmd(priv, 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(wlandevice_t *priv)
++{
++      struct acx_template_proberesp pr;
++      int len, result;
++
++      FN_ENTER;
++
++      len = acx_fill_beacon_or_proberesp_template(priv, &pr, WF_FSTYPE_PROBERESP);
++      result = acx_s_issue_cmd(priv, ACX1xx_CMD_CONFIG_PROBE_RESPONSE, &pr, len);
++
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/***********************************************************************
++** acx100_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.
++*/
++int
++acx100_s_init_packet_templates(wlandevice_t *priv)
++{
++      acx_ie_memmap_t mm;
++      int result = NOT_OK;
++
++      FN_ENTER;
++
++      acxlog(L_DEBUG, "sizeof(memmap)=%d bytes\n", (int)sizeof(mm));
++
++      /* acx100 still do not emit probe requests, thus this call
++      ** is sourt of not needed. But we want it to work someday */
++      if (OK != acx_s_init_max_probe_request_template(priv))
++              goto failed;
++
++#ifdef NOT_WORKING_YET
++      /* FIXME: creating the NULL data template breaks
++       * communication right now, needs further testing.
++       * Also, need to set the template once we're joining a network. */
++      if (OK != acx_s_init_max_null_data_template(priv))
++              goto failed;
++#endif
++
++      if (OK != acx_s_init_max_beacon_template(priv))
++              goto failed;
++
++      if (OK != acx_s_init_max_tim_template(priv))
++              goto failed;
++
++      if (OK != acx_s_init_max_probe_response_template(priv))
++              goto failed;
++
++      if (OK != acx_s_set_tim_template(priv))
++              goto failed;
++
++      if (OK != acx_s_interrogate(priv, &mm, ACX1xx_IE_MEMORY_MAP)) {
++              goto failed;
++      }
++
++      mm.QueueStart = cpu_to_le32(le32_to_cpu(mm.PacketTemplateEnd) + 4);
++      if (OK != acx_s_configure(priv, &mm, ACX1xx_IE_MEMORY_MAP)) {
++              goto failed;
++      }
++
++      result = OK;
++      goto success;
++
++failed:
++      acxlog(L_DEBUG|L_INIT,
++              /* "cb=0x%X\n" */
++              "pACXMemoryMap:\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));
++
++success:
++      FN_EXIT1(result);
++      return result;
++}
++
++int
++acx111_s_init_packet_templates(wlandevice_t *priv)
++{
++      int result = NOT_OK;
++
++      FN_ENTER;
++
++      acxlog(L_DEBUG|L_INIT, "initializing max packet templates\n");
++
++      if (OK != acx_s_init_max_probe_request_template(priv))
++              goto failed;
++
++      if (OK != acx_s_init_max_null_data_template(priv))
++              goto failed;
++
++      if (OK != acx_s_init_max_beacon_template(priv))
++              goto failed;
++
++      if (OK != acx_s_init_max_tim_template(priv))
++              goto failed;
++
++      if (OK != acx_s_init_max_probe_response_template(priv))
++              goto failed;
++
++      /* the other templates will be set later (acx_start) */
++      /*
++      if (OK != acx_s_set_tim_template(priv))
++              goto failed;*/
++
++      result = OK;
++      goto success;
++
++failed:
++      printk("%s: acx111_init_packet_templates() FAILED\n", priv->netdev->name);
++
++success:
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/***********************************************************************
++*/
++static int
++acx100_s_set_probe_request_template(wlandevice_t *priv)
++{
++      struct acx100_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, priv->dev_addr);
++      MAC_BCAST(probereq.bssid);
++
++      probereq.beacon_interval = cpu_to_le16(priv->beacon_interval);
++      acx_update_capabilities(priv);
++      probereq.cap = cpu_to_le16(priv->capabilities);
++
++      p = probereq.variable;
++      acxlog(L_ASSOC, "SSID='%s' len=%d\n", priv->essid, priv->essid_len);
++      p = wlan_fill_ie_ssid(p, priv->essid_len, priv->essid);
++      p = wlan_fill_ie_rates(p, priv->rate_supported_len, priv->rate_supported);
++      /* FIXME: should these be here or AFTER ds_parms? */
++      p = wlan_fill_ie_rates_ext(p, priv->rate_supported_len, priv->rate_supported);
++      /* HUH?? who said it must be here? I've found nothing in 802.11! --vda*/
++      /* p = wlan_fill_ie_ds_parms(p, priv->channel); */
++      frame_len = p - (char*)&probereq;
++      probereq.size = frame_len - 2;
++
++      res = acx_s_issue_cmd(priv, ACX1xx_CMD_CONFIG_PROBE_REQUEST, &probereq, frame_len);
++      FN_EXIT0;
++      return res;
++}
++
++static int
++acx111_s_set_probe_request_template(wlandevice_t *priv)
++{
++      struct acx111_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, priv->dev_addr);
++      MAC_BCAST(probereq.bssid);
++
++      p = probereq.variable;
++      p = wlan_fill_ie_ssid(p, priv->essid_len, priv->essid);
++      p = wlan_fill_ie_rates(p, priv->rate_supported_len, priv->rate_supported);
++      p = wlan_fill_ie_rates_ext(p, priv->rate_supported_len, priv->rate_supported);
++      frame_len = p - (char*)&probereq;
++      probereq.size = frame_len - 2;
++
++      res = acx_s_issue_cmd(priv, ACX1xx_CMD_CONFIG_PROBE_REQUEST, &probereq, frame_len);
++      FN_EXIT0;
++      return res;
++}
++
++static int
++acx_s_set_probe_request_template(wlandevice_t *priv)
++{
++      if (IS_ACX111(priv)) {
++              return acx111_s_set_probe_request_template(priv);
++      } else {
++              return acx100_s_set_probe_request_template(priv);
++      }
++}
++
++
++/***********************************************************************
++** acx_s_update_card_settings
++**
++** Applies accumulated changes in various priv->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(wlandevice_t *priv)
++{
++      u32 feature1, feature2;
++
++      if ((priv->sensitivity < 1) || (priv->sensitivity > 3)) {
++              printk("%s: invalid sensitivity setting (1..3), "
++                      "setting to 1\n", priv->netdev->name);
++              priv->sensitivity = 1;
++      }
++      acx111_s_get_feature_config(priv, &feature1, &feature2);
++      CLEAR_BIT(feature1, FEATURE1_LOW_RX|FEATURE1_EXTRA_LOW_RX);
++      if (priv->sensitivity > 1)
++              SET_BIT(feature1, FEATURE1_LOW_RX);
++      if (priv->sensitivity > 2)
++              SET_BIT(feature1, FEATURE1_EXTRA_LOW_RX);
++      acx111_s_feature_set(priv, feature1, feature2);
++}
++
++void
++acx_s_update_card_settings(wlandevice_t *priv, int get_all, int set_all)
++{
++      unsigned long flags;
++      unsigned int start_scan = 0;
++      int i;
++
++      FN_ENTER;
++
++      if (get_all)
++              SET_BIT(priv->get_mask, GETSET_ALL);
++      if (set_all)
++              SET_BIT(priv->set_mask, GETSET_ALL);
++      /* Why not just set masks to 0xffffffff? We can get rid of GETSET_ALL */
++
++      acxlog(L_INIT, "get_mask 0x%08X, set_mask 0x%08X\n",
++                      priv->get_mask, priv->set_mask);
++
++      /* Track dependencies betweed various settings */
++
++      if (priv->set_mask & (GETSET_MODE|GETSET_RESCAN|GETSET_WEP)) {
++              acxlog(L_INIT, "important setting has been changed. "
++                      "Need to update packet templates, too\n");
++              SET_BIT(priv->set_mask, SET_TEMPLATES);
++      }
++      if (priv->set_mask & (GETSET_CHANNEL|GETSET_ALL)) {
++              /* This will actually tune RX/TX to the channel */
++              SET_BIT(priv->set_mask, GETSET_RX|GETSET_TX);
++              switch (priv->mode) {
++              case ACX_MODE_0_ADHOC:
++              case ACX_MODE_3_AP:
++                      /* Beacons contain channel# - update them */
++                      SET_BIT(priv->set_mask, SET_TEMPLATES);
++              }
++              switch (priv->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 (priv->set_mask & (GETSET_MODE|GETSET_RESCAN|GETSET_CHANNEL|GETSET_WEP|GETSET_ALL)) {
++              if (ACX_MODE_2_STA == priv->mode) {
++                      if (ACX_STATUS_4_ASSOCIATED == priv->status) {
++                              acxlog(L_ASSOC, "we were ASSOCIATED - "
++                                      "sending disassoc request\n");
++                              acx_lock(priv, flags);
++                              acx_l_transmit_disassoc(priv, NULL);
++                              /* FIXME: deauth? */
++                              acx_unlock(priv, flags);
++                      }
++                      /* need to reset some other stuff as well */
++                      acxlog(L_DEBUG, "resetting bssid\n");
++                      MAC_ZERO(priv->bssid);
++                      SET_BIT(priv->set_mask, SET_TEMPLATES|SET_STA_LIST);
++                      /* FIXME: should start scanning */
++                      start_scan = 1;
++              }
++      }
++#endif
++
++      if (priv->get_mask & (GETSET_STATION_ID|GETSET_ALL)) {
++              u8 stationID[4 + ACX1xx_IE_DOT11_STATION_ID_LEN];
++              const u8 *paddr;
++
++              acx_s_interrogate(priv, 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 iwpriv->dev_addr */
++                      priv->netdev->dev_addr[ETH_ALEN - 1 - i] = paddr[i];
++              }
++              CLEAR_BIT(priv->get_mask, GETSET_STATION_ID);
++      }
++
++      if (priv->get_mask & (GETSET_SENSITIVITY|GETSET_ALL)) {
++              if ((RADIO_RFMD_11 == priv->radio_type)
++              || (RADIO_MAXIM_0D == priv->radio_type)
++              || (RADIO_RALINK_15 == priv->radio_type)) {
++                      acx_s_read_phy_reg(priv, 0x30, &priv->sensitivity);
++              } else {
++                      acxlog(L_INIT, "don't know how to get sensitivity "
++                              "for radio type 0x%02X\n", priv->radio_type);
++                      priv->sensitivity = 0;
++              }
++              acxlog(L_INIT, "got sensitivity value %u\n", priv->sensitivity);
++
++              CLEAR_BIT(priv->get_mask, GETSET_SENSITIVITY);
++      }
++
++      if (priv->get_mask & (GETSET_ANTENNA|GETSET_ALL)) {
++              u8 antenna[4 + ACX1xx_IE_DOT11_CURRENT_ANTENNA_LEN];
++
++              memset(antenna, 0, sizeof(antenna));
++              acx_s_interrogate(priv, antenna, ACX1xx_IE_DOT11_CURRENT_ANTENNA);
++              priv->antenna = antenna[4];
++              acxlog(L_INIT, "got antenna value 0x%02X\n", priv->antenna);
++              CLEAR_BIT(priv->get_mask, GETSET_ANTENNA);
++      }
++
++      if (priv->get_mask & (GETSET_ED_THRESH|GETSET_ALL)) {
++              if (IS_ACX100(priv))    {
++                      u8 ed_threshold[4 + ACX100_IE_DOT11_ED_THRESHOLD_LEN];
++
++                      memset(ed_threshold, 0, sizeof(ed_threshold));
++                      acx_s_interrogate(priv, ed_threshold, ACX100_IE_DOT11_ED_THRESHOLD);
++                      priv->ed_threshold = ed_threshold[4];
++              } else {
++                      acxlog(L_INIT, "acx111 doesn't support ED\n");
++                      priv->ed_threshold = 0;
++              }
++              acxlog(L_INIT, "got Energy Detect (ED) threshold %u\n", priv->ed_threshold);
++              CLEAR_BIT(priv->get_mask, GETSET_ED_THRESH);
++      }
++
++      if (priv->get_mask & (GETSET_CCA|GETSET_ALL)) {
++              if (IS_ACX100(priv))    {
++                      u8 cca[4 + ACX1xx_IE_DOT11_CURRENT_CCA_MODE_LEN];
++
++                      memset(cca, 0, sizeof(priv->cca));
++                      acx_s_interrogate(priv, cca, ACX1xx_IE_DOT11_CURRENT_CCA_MODE);
++                      priv->cca = cca[4];
++              } else {
++                      acxlog(L_INIT, "acx111 doesn't support CCA\n");
++                      priv->cca = 0;
++              }
++              acxlog(L_INIT, "got Channel Clear Assessment (CCA) value %u\n", priv->cca);
++              CLEAR_BIT(priv->get_mask, GETSET_CCA);
++      }
++
++      if (priv->get_mask & (GETSET_REG_DOMAIN|GETSET_ALL)) {
++              acx_ie_generic_t dom;
++
++              acx_s_interrogate(priv, &dom, ACX1xx_IE_DOT11_CURRENT_REG_DOMAIN);
++              priv->reg_dom_id = dom.m.bytes[0];
++              /* FIXME: should also set chanmask somehow */
++              acxlog(L_INIT, "got regulatory domain 0x%02X\n", priv->reg_dom_id);
++              CLEAR_BIT(priv->get_mask, GETSET_REG_DOMAIN);
++      }
++
++      if (priv->set_mask & (GETSET_STATION_ID|GETSET_ALL)) {
++              u8 stationID[4 + ACX1xx_IE_DOT11_STATION_ID_LEN];
++              u8 *paddr;
++
++              paddr = &stationID[4];
++              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] = priv->dev_addr[ETH_ALEN - 1 - i];
++              }
++              acx_s_configure(priv, &stationID, ACX1xx_IE_DOT11_STATION_ID);
++              CLEAR_BIT(priv->set_mask, GETSET_STATION_ID);
++      }
++
++      if (priv->set_mask & (SET_TEMPLATES|GETSET_ALL)) {
++              acxlog(L_INIT, "updating packet templates\n");
++              /* Doesn't work for acx100, do it only for acx111 for now */
++              if (IS_ACX111(priv)) {
++                      switch (priv->mode) {
++                      case ACX_MODE_0_ADHOC:
++                      case ACX_MODE_2_STA:
++                              acx_s_set_probe_request_template(priv);
++                      }
++              }
++              switch (priv->mode) {
++              case ACX_MODE_0_ADHOC:
++              case ACX_MODE_3_AP:
++                      /* FIXME: why only for AP? STA need probe req templates... */
++                      acx_s_set_beacon_template(priv);
++                      acx_s_set_tim_template(priv);
++                      /* 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(priv);
++              }
++              /* Needed if generated frames are to be emitted at different tx rate now */
++              acxlog(L_IRQ, "redoing cmd_join_bssid() after template cfg\n");
++              acx_s_cmd_join_bssid(priv, priv->bssid);
++              CLEAR_BIT(priv->set_mask, SET_TEMPLATES);
++      }
++      if (priv->set_mask & (SET_STA_LIST|GETSET_ALL)) {
++              acx_lock(priv, flags);
++              acx_l_sta_list_init(priv);
++              CLEAR_BIT(priv->set_mask, SET_STA_LIST);
++              acx_unlock(priv, flags);
++      }
++      if (priv->set_mask & (SET_RATE_FALLBACK|GETSET_ALL)) {
++              u8 rate[4 + ACX1xx_IE_RATE_FALLBACK_LEN];
++
++              /* configure to not do fallbacks when not in auto rate mode */
++              rate[4] = (priv->rate_auto) ? /* priv->txrate_fallback_retries */ 1 : 0;
++              acxlog(L_INIT, "updating Tx fallback to %u retries\n", rate[4]);
++              acx_s_configure(priv, &rate, ACX1xx_IE_RATE_FALLBACK);
++              CLEAR_BIT(priv->set_mask, SET_RATE_FALLBACK);
++      }
++      if (priv->set_mask & (GETSET_TXPOWER|GETSET_ALL)) {
++              acxlog(L_INIT, "updating transmit power: %u dBm\n",
++                                      priv->tx_level_dbm);
++              acx_s_set_tx_level(priv, priv->tx_level_dbm);
++              CLEAR_BIT(priv->set_mask, GETSET_TXPOWER);
++      }
++
++      if (priv->set_mask & (GETSET_SENSITIVITY|GETSET_ALL)) {
++              acxlog(L_INIT, "updating sensitivity value: %u\n",
++                                      priv->sensitivity);
++              switch (priv->radio_type) {
++              case RADIO_RFMD_11:
++              case RADIO_MAXIM_0D:
++              case RADIO_RALINK_15:
++                      acx_s_write_phy_reg(priv, 0x30, priv->sensitivity);
++                      break;
++              case RADIO_RADIA_16:
++              case RADIO_UNKNOWN_17:
++                      acx111_s_sens_radio_16_17(priv);
++                      break;
++              default:
++                      acxlog(L_INIT, "don't know how to modify sensitivity "
++                              "for radio type 0x%02X\n", priv->radio_type);
++              }
++              CLEAR_BIT(priv->set_mask, GETSET_SENSITIVITY);
++      }
++
++      if (priv->set_mask & (GETSET_ANTENNA|GETSET_ALL)) {
++              /* antenna */
++              u8 antenna[4 + ACX1xx_IE_DOT11_CURRENT_ANTENNA_LEN];
++
++              memset(antenna, 0, sizeof(antenna));
++              antenna[4] = priv->antenna;
++              acxlog(L_INIT, "updating antenna value: 0x%02X\n",
++                                      priv->antenna);
++              acx_s_configure(priv, &antenna, ACX1xx_IE_DOT11_CURRENT_ANTENNA);
++              CLEAR_BIT(priv->set_mask, GETSET_ANTENNA);
++      }
++
++      if (priv->set_mask & (GETSET_ED_THRESH|GETSET_ALL)) {
++              /* ed_threshold */
++              acxlog(L_INIT, "updating Energy Detect (ED) threshold: %u\n",
++                                      priv->ed_threshold);
++              if (IS_ACX100(priv)) {
++                      u8 ed_threshold[4 + ACX100_IE_DOT11_ED_THRESHOLD_LEN];
++
++                      memset(ed_threshold, 0, sizeof(ed_threshold));
++                      ed_threshold[4] = priv->ed_threshold;
++                      acx_s_configure(priv, &ed_threshold, ACX100_IE_DOT11_ED_THRESHOLD);
++              }
++              else
++                      acxlog(L_INIT, "acx111 doesn't support ED!\n");
++              CLEAR_BIT(priv->set_mask, GETSET_ED_THRESH);
++      }
++
++      if (priv->set_mask & (GETSET_CCA|GETSET_ALL)) {
++              /* CCA value */
++              acxlog(L_INIT, "updating Channel Clear Assessment "
++                              "(CCA) value: 0x%02X\n", priv->cca);
++              if (IS_ACX100(priv))    {
++                      u8 cca[4 + ACX1xx_IE_DOT11_CURRENT_CCA_MODE_LEN];
++
++                      memset(cca, 0, sizeof(cca));
++                      cca[4] = priv->cca;
++                      acx_s_configure(priv, &cca, ACX1xx_IE_DOT11_CURRENT_CCA_MODE);
++              }
++              else
++                      acxlog(L_INIT, "acx111 doesn't support CCA!\n");
++              CLEAR_BIT(priv->set_mask, GETSET_CCA);
++      }
++
++      if (priv->set_mask & (GETSET_LED_POWER|GETSET_ALL)) {
++              /* Enable Tx */
++              acxlog(L_INIT, "updating power LED status: %u\n", priv->led_power);
++
++              acx_lock(priv, flags);
++              if (IS_PCI(priv))
++                      acx_l_power_led(priv, priv->led_power);
++              CLEAR_BIT(priv->set_mask, GETSET_LED_POWER);
++              acx_unlock(priv, flags);
++      }
++
++/* this seems to cause Tx lockup after some random time (Tx error 0x20),
++ * so let's disable it for now until further investigation */
++/* Maybe fixed now after locking is fixed. Need to retest */
++#ifdef POWER_SAVE_80211
++      if (priv->set_mask & (GETSET_POWER_80211|GETSET_ALL)) {
++              acx100_ie_powermgmt_t pm;
++
++              /* change 802.11 power save mode settings */
++              acxlog(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 %d\n",
++                      priv->ps_wakeup_cfg, priv->ps_listen_interval,
++                      priv->ps_options, priv->ps_hangover_period,
++                      priv->ps_enhanced_transition_time);
++              acx_s_interrogate(priv, &pm, ACX100_IE_POWER_MGMT);
++              acxlog(L_INIT, "Previous PS mode settings: wakeup_cfg 0x%02X, "
++                      "listen interval %u, options 0x%02X, "
++                      "hangover period %u, "
++                      "enhanced_ps_transition_time %d\n",
++                      pm.wakeup_cfg, pm.listen_interval, pm.options,
++                      pm.hangover_period, pm.enhanced_ps_transition_time);
++              pm.wakeup_cfg = priv->ps_wakeup_cfg;
++              pm.listen_interval = priv->ps_listen_interval;
++              pm.options = priv->ps_options;
++              pm.hangover_period = priv->ps_hangover_period;
++              pm.enhanced_ps_transition_time = cpu_to_le16(priv->ps_enhanced_transition_time);
++              acx_s_configure(priv, &pm, ACX100_IE_POWER_MGMT);
++              acx_s_interrogate(priv, &pm, ACX100_IE_POWER_MGMT);
++              acxlog(L_INIT, "wakeup_cfg: 0x%02X\n", pm.wakeup_cfg);
++              acx_s_msleep(40);
++              acx_s_interrogate(priv, &pm, ACX100_IE_POWER_MGMT);
++              acxlog(L_INIT, "power save mode change %s\n",
++                      (pm.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). Does this need locking?? */
++              CLEAR_BIT(priv->set_mask, GETSET_POWER_80211);
++      }
++#endif
++
++      if (priv->set_mask & (GETSET_CHANNEL|GETSET_ALL)) {
++              /* channel */
++              acxlog(L_INIT, "updating channel to: %u\n", priv->channel);
++              CLEAR_BIT(priv->set_mask, GETSET_CHANNEL);
++      }
++
++      if (priv->set_mask & (GETSET_TX|GETSET_ALL)) {
++              /* set Tx */
++              acxlog(L_INIT, "updating: %s Tx\n",
++                              priv->tx_disabled ? "disable" : "enable");
++              if (priv->tx_disabled)
++                      acx_s_issue_cmd(priv, ACX1xx_CMD_DISABLE_TX, NULL, 0);
++                      /*                                                 ^ */
++                      /* FIXME: this used to be 1, but since we don't transfer a parameter... */
++              else
++                      acx_s_issue_cmd(priv, ACX1xx_CMD_ENABLE_TX, &(priv->channel), 1);
++              CLEAR_BIT(priv->set_mask, GETSET_TX);
++      }
++
++      if (priv->set_mask & (GETSET_RX|GETSET_ALL)) {
++              /* Enable Rx */
++              acxlog(L_INIT, "updating: enable Rx on channel: %u\n",
++                              priv->channel);
++              acx_s_issue_cmd(priv, ACX1xx_CMD_ENABLE_RX, &(priv->channel), 1);
++              CLEAR_BIT(priv->set_mask, GETSET_RX);
++      }
++
++      if (priv->set_mask & (GETSET_RETRY|GETSET_ALL)) {
++              u8 short_retry[4 + ACX1xx_IE_DOT11_SHORT_RETRY_LIMIT_LEN];
++              u8 long_retry[4 + ACX1xx_IE_DOT11_LONG_RETRY_LIMIT_LEN];
++
++              acxlog(L_INIT, "updating short retry limit: %u, long retry limit: %u\n",
++                                      priv->short_retry, priv->long_retry);
++              short_retry[0x4] = priv->short_retry;
++              long_retry[0x4] = priv->long_retry;
++              acx_s_configure(priv, &short_retry, ACX1xx_IE_DOT11_SHORT_RETRY_LIMIT);
++              acx_s_configure(priv, &long_retry, ACX1xx_IE_DOT11_LONG_RETRY_LIMIT);
++              CLEAR_BIT(priv->set_mask, GETSET_RETRY);
++      }
++
++      if (priv->set_mask & (SET_MSDU_LIFETIME|GETSET_ALL)) {
++              u8 xmt_msdu_lifetime[4 + ACX1xx_IE_DOT11_MAX_XMIT_MSDU_LIFETIME_LEN];
++
++              acxlog(L_INIT, "updating tx MSDU lifetime: %u\n",
++                                      priv->msdu_lifetime);
++              *(u32 *)&xmt_msdu_lifetime[4] = cpu_to_le32((u32)priv->msdu_lifetime);
++              acx_s_configure(priv, &xmt_msdu_lifetime, ACX1xx_IE_DOT11_MAX_XMIT_MSDU_LIFETIME);
++              CLEAR_BIT(priv->set_mask, SET_MSDU_LIFETIME);
++      }
++
++      if (priv->set_mask & (GETSET_REG_DOMAIN|GETSET_ALL)) {
++              /* reg_domain */
++              acx_ie_generic_t dom;
++              unsigned mask;
++
++              acxlog(L_INIT, "updating regulatory domain: 0x%02X\n",
++                                      priv->reg_dom_id);
++              for (i = 0; i < sizeof(reg_domain_ids); i++)
++                      if (reg_domain_ids[i] == priv->reg_dom_id)
++                              break;
++
++              if (sizeof(reg_domain_ids) == i) {
++                      acxlog(L_INIT, "Invalid or unsupported regulatory "
++                              "domain 0x%02X specified, falling back to "
++                              "FCC (USA)! Please report if this sounds "
++                              "fishy!\n", priv->reg_dom_id);
++                      i = 0;
++                      priv->reg_dom_id = reg_domain_ids[i];
++              }
++
++              priv->reg_dom_chanmask = reg_domain_channel_masks[i];
++              dom.m.bytes[0] = priv->reg_dom_id;
++              acx_s_configure(priv, &dom, ACX1xx_IE_DOT11_CURRENT_REG_DOMAIN);
++
++              mask = (1 << (priv->channel - 1));
++              if (!(priv->reg_dom_chanmask & mask)) {
++              /* hmm, need to adjust our channel to reside within domain */
++                      mask = 1;
++                      for (i = 1; i <= 14; i++) {
++                              if (priv->reg_dom_chanmask & mask) {
++                                      printk("%s: adjusting "
++                                              "selected channel from %d "
++                                              "to %d due to new regulatory "
++                                              "domain\n", priv->netdev->name,
++                                              priv->channel, i);
++                                      priv->channel = i;
++                                      break;
++                              }
++                              mask <<= 1;
++                      }
++              }
++              CLEAR_BIT(priv->set_mask, GETSET_REG_DOMAIN);
++      }
++
++      if (priv->set_mask & (GETSET_MODE|GETSET_ALL)) {
++              priv->netdev->type = ARPHRD_ETHER;
++
++              switch (priv->mode) {
++              case ACX_MODE_3_AP:
++
++                      acx_lock(priv, flags);
++                      acx_l_sta_list_init(priv);
++                      priv->aid = 0;
++                      priv->ap_client = NULL;
++                      MAC_COPY(priv->bssid, priv->dev_addr);
++                      /* this basically says "we're connected" */
++                      acx_set_status(priv, ACX_STATUS_4_ASSOCIATED);
++                      acx_unlock(priv, flags);
++
++                      acx111_s_feature_off(priv, 0, FEATURE2_NO_TXCRYPT|FEATURE2_SNIFFER);
++                      /* start sending beacons */
++                      acx_s_cmd_join_bssid(priv, priv->bssid);
++                      break;
++              case ACX_MODE_MONITOR:
++                      /* priv->netdev->type = ARPHRD_ETHER; */
++                      /* priv->netdev->type = ARPHRD_IEEE80211; */
++                      priv->netdev->type = ARPHRD_IEEE80211_PRISM;
++                      acx111_s_feature_on(priv, 0, FEATURE2_NO_TXCRYPT|FEATURE2_SNIFFER);
++                      /* this stops beacons */
++                      acx_s_cmd_join_bssid(priv, priv->bssid);
++                      /* this basically says "we're connected" */
++                      acx_set_status(priv, ACX_STATUS_4_ASSOCIATED);
++                      SET_BIT(priv->set_mask, SET_RXCONFIG|SET_WEP_OPTIONS);
++                      break;
++              case ACX_MODE_0_ADHOC:
++              case ACX_MODE_2_STA:
++                      acx111_s_feature_off(priv, 0, FEATURE2_NO_TXCRYPT|FEATURE2_SNIFFER);
++                      priv->aid = 0;
++                      priv->ap_client = NULL;
++                      /* 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: */
++                      /* priv->tx_disabled = 1; */
++                      /* SET_BIT(priv->set_mask, GETSET_RX|GETSET_TX); */
++
++                      /* This stops beacons (invalid macmode...) */
++                      acx_s_cmd_join_bssid(priv, priv->bssid);
++                      acx_set_status(priv, ACX_STATUS_0_STOPPED);
++                      break;
++              }
++              CLEAR_BIT(priv->set_mask, GETSET_MODE);
++      }
++
++      if (priv->set_mask & (SET_RXCONFIG|GETSET_ALL)) {
++              acx_s_initialize_rx_config(priv);
++              CLEAR_BIT(priv->set_mask, SET_RXCONFIG);
++      }
++
++      if (priv->set_mask & (GETSET_RESCAN|GETSET_ALL)) {
++              switch (priv->mode) {
++              case ACX_MODE_0_ADHOC:
++              case ACX_MODE_2_STA:
++                      start_scan = 1;
++                      break;
++              }
++              CLEAR_BIT(priv->set_mask, GETSET_RESCAN);
++      }
++
++      if (priv->set_mask & (GETSET_WEP|GETSET_ALL)) {
++              /* encode */
++
++              ie_dot11WEPDefaultKeyID_t dkey;
++#ifdef DEBUG_WEP
++              struct {
++                      u16 type ACX_PACKED;
++                      u16 len ACX_PACKED;
++                      u8  val ACX_PACKED;
++              } keyindic;
++#endif
++              acxlog(L_INIT, "updating WEP key settings\n");
++
++              acx_s_set_wepkey(priv);
++
++              dkey.KeyID = priv->wep_current_index;
++              acxlog(L_INIT, "setting WEP key %u as default\n", dkey.KeyID);
++              acx_s_configure(priv, &dkey, ACX1xx_IE_DOT11_WEP_DEFAULT_KEY_SET);
++#ifdef DEBUG_WEP
++              keyindic.val = 3;
++              acx_s_configure(priv, &keyindic, ACX111_IE_KEY_CHOOSE);
++#endif
++              start_scan = 1;
++              CLEAR_BIT(priv->set_mask, GETSET_WEP);
++      }
++
++      if (priv->set_mask & (SET_WEP_OPTIONS|GETSET_ALL)) {
++              acx100_ie_wep_options_t options;
++
++              if (IS_ACX111(priv)) {
++                      acxlog(L_DEBUG, "setting WEP Options for acx111 is not supported\n");
++              } else {
++                      acxlog(L_INIT, "setting WEP Options\n");
++
++                      /* 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 (priv->mode == ACX_MODE_MONITOR) {
++                              /* don't decrypt default key only,
++                               * override decryption mechanism: */
++                              options.WEPOption = 2;
++                      }
++
++                      acx_s_configure(priv, &options, ACX100_IE_WEP_OPTIONS);
++              }
++              CLEAR_BIT(priv->set_mask, SET_WEP_OPTIONS);
++      }
++
++      /* Rescan was requested */
++      if (start_scan) {
++              switch (priv->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(priv, flags);
++                      priv->ap_client = NULL;
++                      acx_l_sta_list_init(priv);
++                      acx_set_status(priv, ACX_STATUS_1_SCANNING);
++                      acx_unlock(priv, flags);
++
++                      acx_s_cmd_start_scan(priv);
++              }
++      }
++
++      /* debug, rate, and nick don't need any handling */
++      /* what about sniffing mode?? */
++
++      acxlog(L_INIT, "get_mask 0x%08X, set_mask 0x%08X - after update\n",
++                      priv->get_mask, priv->set_mask);
++
++/* end: */
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++*/
++void
++acx_s_initialize_rx_config(wlandevice_t *priv)
++{
++      struct {
++              u16     id ACX_PACKED;
++              u16     len ACX_PACKED;
++              u16     rx_cfg1 ACX_PACKED;
++              u16     rx_cfg2 ACX_PACKED;
++      } cfg;
++
++      switch (priv->mode) {
++      case ACX_MODE_OFF:
++              priv->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    */
++                      );
++              priv->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:
++              priv->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    */
++                      );
++              priv->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:
++              priv->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    */
++                      );
++              priv->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;
++      }
++#ifdef DEBUG_WEP
++      if (IS_ACX100(priv))
++              /* only ACX100 supports that */
++#endif
++              priv->rx_config_1 |= RX_CFG1_INCLUDE_RXBUF_HDR;
++
++      acxlog(L_INIT, "setting RXconfig to %04X:%04X\n",
++                      priv->rx_config_1, priv->rx_config_2);
++      cfg.rx_cfg1 = cpu_to_le16(priv->rx_config_1);
++      cfg.rx_cfg2 = cpu_to_le16(priv->rx_config_2);
++      acx_s_configure(priv, &cfg, ACX1xx_IE_RXCONFIG);
++}
++
++
++/***********************************************************************
++** acx_e_after_interrupt_task
++*/
++static int
++acx_s_recalib_radio(wlandevice_t *priv)
++{
++      if (IS_ACX111(priv)) {
++              acx111_cmd_radiocalib_t cal;
++
++              printk("%s: recalibrating radio\n", priv->netdev->name);
++              /* automatic recalibration, choose all methods: */
++              cal.methods = cpu_to_le32(0x8000000f);
++              /* automatic recalibration every 60 seconds (value in TUs)
++               * FIXME: what is the firmware default here?? */
++              cal.interval = cpu_to_le32(58594);
++              return acx_s_issue_cmd_timeo(priv, ACX111_CMD_RADIOCALIB,
++                      &cal, sizeof(cal), CMD_TIMEOUT_MS(100));
++      } else {
++              if (/* (OK == acx_s_issue_cmd(priv, ACX1xx_CMD_DISABLE_TX, NULL, 0)) &&
++                  (OK == acx_s_issue_cmd(priv, ACX1xx_CMD_DISABLE_RX, NULL, 0)) && */
++                  (OK == acx_s_issue_cmd(priv, ACX1xx_CMD_ENABLE_TX, &(priv->channel), 1)) &&
++                  (OK == acx_s_issue_cmd(priv, ACX1xx_CMD_ENABLE_RX, &(priv->channel), 1)) )
++                      return OK;
++              return NOT_OK;
++      }
++}
++
++static void
++acx_s_after_interrupt_recalib(wlandevice_t *priv)
++{
++      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(priv->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 (priv->recalib_time_last_success
++       && time_before(jiffies, priv->recalib_time_last_success
++                                      + RECALIB_PAUSE * 60 * HZ)) {
++              priv->recalib_msg_ratelimit++;
++              if (priv->recalib_msg_ratelimit <= 5)
++                      printk("%s: less than " STRING(RECALIB_PAUSE)
++                              " minutes since last radio recalibration, "
++                              "not recalibrating (maybe card is too hot?)\n",
++                              priv->netdev->name);
++              if (priv->recalib_msg_ratelimit == 5)
++                      printk("disabling above message\n");
++              return;
++      }
++
++      priv->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(priv);
++      if (res == OK) {
++              printk("%s: successfully recalibrated radio\n",
++                                              priv->netdev->name);
++              priv->recalib_time_last_success = jiffies;
++              priv->recalib_failure_count = 0;
++      } else {
++              /* failed: resubmit, but only limited
++               * amount of times within some time range
++               * to prevent endless loop */
++
++              priv->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, priv->recalib_time_last_attempt + HZ))
++                      priv->recalib_failure_count = 0;
++
++              if (++priv->recalib_failure_count <= 5) {
++                      priv->recalib_time_last_attempt = jiffies;
++                      acx_schedule_after_interrupt_task(priv, ACX_AFTER_IRQ_CMD_RADIO_RECALIB);
++              }
++      }
++}
++
++static void
++acx_e_after_interrupt_task(void *data)
++{
++      netdevice_t *dev = (netdevice_t *) data;
++      wlandevice_t *priv = netdev_priv(dev);
++
++      FN_ENTER;
++
++      acx_sem_lock(priv);
++
++      if (!priv->after_interrupt_jobs)
++              goto end; /* no jobs to do */
++
++#if TX_CLEANUP_IN_SOFTIRQ
++      if (priv->after_interrupt_jobs & ACX_AFTER_IRQ_TX_CLEANUP) {
++              acx_lock(priv, flags);
++              acx_l_clean_tx_desc(priv);
++              CLEAR_BIT(priv->after_interrupt_jobs, ACX_AFTER_IRQ_TX_CLEANUP);
++              acx_unlock(priv, flags);
++      }
++#endif
++      /* we see lotsa tx errors */
++      if (priv->after_interrupt_jobs & ACX_AFTER_IRQ_CMD_RADIO_RECALIB) {
++              acx_s_after_interrupt_recalib(priv);
++      }
++
++      /* a poor interrupt code wanted to do update_card_settings() */
++      if (priv->after_interrupt_jobs & ACX_AFTER_IRQ_UPDATE_CARD_CFG) {
++              if (ACX_STATE_IFACE_UP & priv->dev_state_mask)
++                      acx_s_update_card_settings(priv, 0, 0);
++              CLEAR_BIT(priv->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 (priv->after_interrupt_jobs & ACX_AFTER_IRQ_CMD_STOP_SCAN) {
++              acxlog(L_IRQ, "sending a stop scan cmd...\n");
++              acx_s_issue_cmd(priv, 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(priv->irq_status, HOST_INT_SCAN_COMPLETE);
++              CLEAR_BIT(priv->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 (priv->after_interrupt_jobs & ACX_AFTER_IRQ_COMPLETE_SCAN) {
++              if (priv->status == ACX_STATUS_1_SCANNING) {
++                      if (OK != acx_s_complete_scan(priv)) {
++                              SET_BIT(priv->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 (priv->mode) {
++                      case ACX_MODE_0_ADHOC:
++                      case ACX_MODE_3_AP:
++                              acxlog(L_IRQ, "redoing cmd_join_bssid() after scan\n");
++                              acx_s_cmd_join_bssid(priv, priv->bssid);
++                      }
++              }
++              CLEAR_BIT(priv->after_interrupt_jobs, ACX_AFTER_IRQ_COMPLETE_SCAN);
++      }
++
++      /* STA auth or assoc timed out, start over again */
++      if (priv->after_interrupt_jobs & ACX_AFTER_IRQ_RESTART_SCAN) {
++              acxlog(L_IRQ, "sending a start_scan cmd...\n");
++              acx_s_cmd_start_scan(priv);
++              CLEAR_BIT(priv->after_interrupt_jobs, ACX_AFTER_IRQ_RESTART_SCAN);
++      }
++
++      /* whee, we got positive assoc response! 8) */
++      if (priv->after_interrupt_jobs & ACX_AFTER_IRQ_CMD_ASSOCIATE) {
++              acx_ie_generic_t pdr;
++              /* tiny race window exists, checking that we still a STA */
++              switch (priv->mode) {
++              case ACX_MODE_2_STA:
++                      pdr.m.aid = cpu_to_le16(priv->aid);
++                      acx_s_configure(priv, &pdr, ACX1xx_IE_ASSOC_ID);
++                      acx_set_status(priv, ACX_STATUS_4_ASSOCIATED);
++                      acxlog(L_ASSOC|L_DEBUG, "ASSOCIATED!\n");
++                      CLEAR_BIT(priv->after_interrupt_jobs, ACX_AFTER_IRQ_CMD_ASSOCIATE);
++              }
++      }
++end:
++      acx_sem_unlock(priv);
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++** acx_schedule_after_interrupt_task
++**
++** Schedule the call of the after_interrupt method after leaving
++** the interrupt context.
++*/
++void
++acx_schedule_after_interrupt_task(wlandevice_t *priv, unsigned int set_flag)
++{
++      SET_BIT(priv->after_interrupt_jobs, set_flag);
++      SCHEDULE_WORK(&priv->after_interrupt_task);
++}
++
++
++/***********************************************************************
++*/
++void
++acx_init_task_scheduler(wlandevice_t *priv)
++{
++      /* configure task scheduler */
++      INIT_WORK(&priv->after_interrupt_task, acx_e_after_interrupt_task,
++                      priv->netdev);
++}
++
++
++/***********************************************************************
++** acx_s_start
++*/
++void
++acx_s_start(wlandevice_t *priv)
++{
++      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(priv->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);
++
++      acxlog(L_INIT, "updating initial settings on iface activation...\n");
++      acx_s_update_card_settings(priv, 0, 0);
++
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++** acx_update_capabilities
++*/
++void
++acx_update_capabilities(wlandevice_t *priv)
++{
++      u16 cap = 0;
++
++      switch (priv->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 (priv->wep_restricted) {
++              SET_BIT(cap, WF_MGMT_CAP_PRIVACY);
++      }
++      if (priv->capab_short) {
++              SET_BIT(cap, WF_MGMT_CAP_SHORT);
++      }
++      if (priv->capab_pbcc) {
++              SET_BIT(cap, WF_MGMT_CAP_PBCC);
++      }
++      if (priv->capab_agility) {
++              SET_BIT(cap, WF_MGMT_CAP_AGILITY);
++      }
++      acxlog(L_DEBUG, "caps updated from 0x%04X to 0x%04X\n",
++                              priv->capabilities, cap);
++      priv->capabilities = cap;
++}
++
++#ifdef UNUSED
++/***********************************************************************
++** FIXME: check whether this function is indeed acx111 only,
++** rename ALL relevant definitions to indicate actual card scope!
++*/
++void
++acx111_s_read_configoption(wlandevice_t *priv)
++{
++      acx111_ie_configoption_t co, co2;
++      int i;
++      const u8 *pEle;
++
++      if (OK != acx_s_interrogate(priv, &co, ACX111_IE_CONFIG_OPTIONS) ) {
++              return;
++      };
++      if (!(acx_debug & L_DEBUG))
++              return;
++
++      memcpy(&co2.configoption_fixed, &co.configoption_fixed,
++                      sizeof(co.configoption_fixed));
++
++      pEle = (u8 *)&co.configoption_fixed + sizeof(co.configoption_fixed) - 4;
++
++      co2.antennas.type = pEle[0];
++      co2.antennas.len = pEle[1];
++      printk("AntennaID:%02X Len:%02X Data:",
++                      co2.antennas.type, co2.antennas.len);
++      for (i = 0; i < pEle[1]; i++) {
++              co2.antennas.list[i] = pEle[i+2];
++              printk("%02X ", pEle[i+2]);
++      }
++      printk("\n");
++
++      pEle += pEle[1] + 2;
++      co2.power_levels.type = pEle[0];
++      co2.power_levels.len = pEle[1];
++      printk("PowerLevelID:%02X Len:%02X Data:",
++                      co2.power_levels.type, co2.power_levels.len);
++      for (i = 0; i < pEle[1]*2; i++) {
++              co2.power_levels.list[i] = pEle[i+2];
++              printk("%02X ", pEle[i+2]);
++      }
++      printk("\n");
++
++      pEle += pEle[1]*2 + 2;
++      co2.data_rates.type = pEle[0];
++      co2.data_rates.len = pEle[1];
++      printk("DataRatesID:%02X Len:%02X Data:",
++                      co2.data_rates.type, co2.data_rates.len);
++      for (i = 0; i < pEle[1]; i++) {
++              co2.data_rates.list[i] = pEle[i+2];
++              printk("%02X ", pEle[i+2]);
++      }
++      printk("\n");
++
++      pEle += pEle[1] + 2;
++      co2.domains.type = pEle[0];
++      co2.domains.len = pEle[1];
++      printk("DomainID:%02X Len:%02X Data:",
++                      co2.domains.type, co2.domains.len);
++      for (i = 0; i < pEle[1]; i++) {
++              co2.domains.list[i] = pEle[i+2];
++              printk("%02X ", pEle[i+2]);
++      }
++      printk("\n");
++
++      pEle += pEle[1] + 2;
++      co2.product_id.type = pEle[0];
++      co2.product_id.len = pEle[1];
++      for (i = 0; i < pEle[1]; i++) {
++              co2.product_id.list[i] = pEle[i+2];
++      }
++      printk("ProductID:%02X Len:%02X Data:%.*s\n",
++                      co2.product_id.type, co2.product_id.len,
++                      co2.product_id.len, (char *)co2.product_id.list);
++
++      pEle += pEle[1] + 2;
++      co2.manufacturer.type = pEle[0];
++      co2.manufacturer.len = pEle[1];
++      for (i = 0; i < pEle[1]; i++) {
++              co2.manufacturer.list[i] = pEle[i+2];
++      }
++      printk("ManufacturerID:%02X Len:%02X Data:%.*s\n",
++                      co2.manufacturer.type, co2.manufacturer.len,
++                      co2.manufacturer.len, (char *)co2.manufacturer.list);
++/*
++      printk("EEPROM part:\n");
++      for (i=0; i<58; i++) {
++              printk("%02X =======>  0x%02X\n",
++                          i, (u8 *)co.configoption_fixed.NVSv[i-2]);
++      }
++*/
++}
++#endif
++
++
++/***********************************************************************
++*/
++static int __init
++acx_e_init_module(void)
++{
++      int r1;
++
++      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_CFI)
++      r1 = acxcfi_e_init_module();
++#elif defined(CONFIG_ACX_PCI)
++      r1 = acxpci_e_init_module();
++#elif defined(CONFIG_ACX_USB)
++      r1 = acxusb_e_init_module();
++#else
++      r1 = -EINVAL;
++#endif
++      if (r1) /* both failed! */
++              return r1;
++      /* return success if at least one succeeded */
++      return 0;
++}
++
++static void __exit
++acx_e_cleanup_module(void)
++{
++#if defined(CONFIG_ACX_PCI)
++      acxcfi_e_cleanup_module();
++#elif defined(CONFIG_ACX_PCI)
++      acxpci_e_cleanup_module();
++#elif defined(CONFIG_ACX_USB)
++      acxusb_e_cleanup_module();
++#endif
++}
++
++module_init(acx_e_init_module)
++module_exit(acx_e_cleanup_module)
+diff -Naur linux-2.6.14-omap2/drivers/net/wireless/tiacx/conv.c linux-h6300-omap2-2.6.14.3/drivers/net/wireless/tiacx/conv.c
+--- linux-2.6.14-omap2/drivers/net/wireless/tiacx/conv.c       1970-01-01 02:00:00.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/drivers/net/wireless/tiacx/conv.c       2005-09-28 23:54:23.000000000 +0300
+@@ -0,0 +1,508 @@
++/***********************************************************************
++** 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/config.h>
++#include <linux/version.h>
++#include <linux/skbuff.h>
++#include <linux/if_arp.h>
++#include <linux/etherdevice.h>
++#include <linux/wireless.h>
++#if WIRELESS_EXT >= 13
++#include <net/iw_handler.h>
++#endif
++
++#include "acx.h"
++
++
++/*----------------------------------------------------------------
++* proto_is_stt
++*
++* Searches the 802.1h Selective Translation Table for a given
++* protocol.
++*
++* Arguments:
++*     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.
++*
++* Comment:
++*     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_l_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.
++*
++* Comment:
++*     Based largely on p80211conv.c of the linux-wlan-ng project
++*----------------------------------------------------------------*/
++int
++acx_l_ether_to_txbuf(wlandevice_t *priv, 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;
++      int result = -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)) {
++              acxlog(L_DEBUG, "zero-length skb!\n");
++              goto end;
++      }
++
++      w_hdr = (struct wlan_hdr_a3*)txbuf;
++
++      switch (priv->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 (skb->len >= WLAN_A4FR_MAXLEN_WEP_FCS - WLAN_FCS_LEN) {
++                      printk("%s: can't tx oversized frame (%d bytes)\n",
++                              priv->netdev->name, skb->len);
++                      goto end;
++              }
++              memcpy(w_hdr, skb->data, skb->len);
++              result = 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) {
++              acxlog(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. */
++
++              acxlog(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;
++      result = payload_len;
++
++      /* Set up the 802.11 header */
++      switch (priv->mode) {
++      case ACX_MODE_0_ADHOC:
++              fc = (WF_FTYPE_DATAi | WF_FSTYPE_DATAONLYi);
++              a1 = e_hdr->daddr;
++              a3 = priv->bssid;
++              break;
++      case ACX_MODE_2_STA:
++              fc = (WF_FTYPE_DATAi | WF_FSTYPE_DATAONLYi | WF_FC_TODSi);
++              a1 = priv->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",
++                              priv->netdev->name);
++              result = -1;
++              goto end;
++      }
++      if (priv->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, priv->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(result);
++      return result;
++}
++
++
++/*----------------------------------------------------------------
++* 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(wlandevice_t *priv, 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(priv, 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(priv)) {
++              /* chop off the IV+ICV WEP header and footer */
++              acxlog(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", priv->netdev->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);
++      e_payload = (u8*) (e_snap + 1);
++      mtu = priv->netdev->mtu;
++
++      acxlog(L_DATA, "rx: payload_offset %d, payload_length %d\n",
++              payload_offset, payload_length);
++      acxlog(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) */
++              acxlog(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",
++                              priv->netdev->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) */)) {
++                      acxlog(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",
++                                      priv->netdev->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 */
++                      acxlog(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",
++                                      priv->netdev->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 {
++              acxlog(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",
++                              priv->netdev->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 = priv->netdev;
++      skb->protocol = eth_type_trans(skb, priv->netdev);
++
++#ifdef DEBUG_CONVERT
++      if (acx_debug & L_DATA) {
++              printk("p802.11 frame [%d]: ", RXBUF_BYTES_RCVD(rxbuf));
++              acx_dump_bytes(w_hdr, RXBUF_BYTES_RCVD(rxbuf));
++              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",
++                      priv->netdev->name, buflen + 2);
++ret_null:
++      FN_EXIT1((int)NULL);
++      return NULL;
++}
+diff -Naur linux-2.6.14-omap2/drivers/net/wireless/tiacx/ioctl.c linux-h6300-omap2-2.6.14.3/drivers/net/wireless/tiacx/ioctl.c
+--- linux-2.6.14-omap2/drivers/net/wireless/tiacx/ioctl.c      1970-01-01 02:00:00.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/drivers/net/wireless/tiacx/ioctl.c      2005-09-28 23:54:23.000000000 +0300
+@@ -0,0 +1,3060 @@
++/***********************************************************************
++** 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/config.h>
++#include <linux/version.h>
++#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>
++#if WIRELESS_EXT >= 13
++#include <net/iw_handler.h>
++#endif /* WE >= 13 */
++
++#include "acx.h"
++
++
++/*================================================================*/
++
++/* if you plan to reorder something, make sure to reorder all other places
++ * accordingly! */
++/* someone broke 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
++};
++
++/* 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,
++};
++
++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" },
++};
++
++
++/*------------------------------------------------------------------------------
++ * acx_ioctl_commit
++ *----------------------------------------------------------------------------*/
++static int
++acx_ioctl_commit(struct net_device *dev,
++                                    struct iw_request_info *info,
++                                    void *zwrq, char *extra)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++
++      FN_ENTER;
++
++      acx_sem_lock(priv);
++      if (ACX_STATE_IFACE_UP & priv->dev_state_mask)
++              acx_s_update_card_settings(priv, 0, 0);
++      acx_sem_unlock(priv);
++
++      FN_EXIT0;
++      return OK;
++}
++
++
++/***********************************************************************
++*/
++static int
++acx_ioctl_get_name(
++      struct net_device *dev,
++      struct iw_request_info *info,
++      char *cwrq,
++      char *extra)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++      static const char * const names[] = { "IEEE 802.11b+/g+", "IEEE 802.11b+" };
++
++      strcpy(cwrq, names[IS_ACX111(priv) ? 0 : 1]);
++
++      return OK;
++}
++
++
++/*----------------------------------------------------------------
++* acx_ioctl_set_freq
++*----------------------------------------------------------------*/
++static int
++acx_ioctl_set_freq(
++      struct net_device *dev,
++      struct iw_request_info *info,
++      struct iw_freq *fwrq,
++      char *extra)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++      int channel = -1;
++      unsigned int mult = 1;
++      int result;
++
++      FN_ENTER;
++
++      if (fwrq->e == 0 && fwrq->m <= 1000) {
++              /* Setting by channel number */
++              channel = fwrq->m;
++      } else {
++              /* If setting by frequency, convert to a channel */
++              int i;
++
++              for (i = 0; i < (6 - fwrq->e); i++)
++                      mult *= 10;
++
++              for (i = 1; i <= 14; i++)
++                      if (fwrq->m == acx_channel_freq[i - 1] * mult)
++                              channel = i;
++      }
++
++      if (channel > 14) {
++              result = -EINVAL;
++              goto end;
++      }
++
++      acx_sem_lock(priv);
++
++      priv->channel = channel;
++      /* hmm, the following code part is strange, but this is how
++       * it was being done before... */
++      acxlog(L_IOCTL, "Changing to channel %d\n", channel);
++      SET_BIT(priv->set_mask, GETSET_CHANNEL);
++
++      result = -EINPROGRESS; /* need to call commit handler */
++
++      acx_sem_unlock(priv);
++end:
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/***********************************************************************
++*/
++static inline int
++acx_ioctl_get_freq(
++      struct net_device *dev,
++      struct iw_request_info *info,
++      struct iw_freq *fwrq,
++      char *extra)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++      fwrq->e = 0;
++      fwrq->m = priv->channel;
++      return OK;
++}
++
++
++/*----------------------------------------------------------------
++* acx_ioctl_set_mode
++*----------------------------------------------------------------*/
++static int
++acx_ioctl_set_mode(
++      struct net_device *dev,
++      struct iw_request_info *info,
++      u32 *uwrq,
++      char *extra)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++      int result;
++
++      FN_ENTER;
++
++      acx_sem_lock(priv);
++
++      switch (*uwrq) {
++      case IW_MODE_AUTO:
++              priv->mode = ACX_MODE_OFF;
++              break;
++#if WIRELESS_EXT > 14
++      case IW_MODE_MONITOR:
++              priv->mode = ACX_MODE_MONITOR;
++              break;
++#endif /* WIRELESS_EXT > 14 */
++      case IW_MODE_ADHOC:
++              priv->mode = ACX_MODE_0_ADHOC;
++              break;
++      case IW_MODE_INFRA:
++              priv->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");
++              priv->mode = ACX_MODE_3_AP;
++              break;
++      case IW_MODE_REPEAT:
++      case IW_MODE_SECOND:
++      default:
++              result = -EOPNOTSUPP;
++              goto end_unlock;
++      }
++
++      acxlog(L_ASSOC, "new priv->mode=%d\n", priv->mode);
++      SET_BIT(priv->set_mask, GETSET_MODE);
++      result = -EINPROGRESS;
++
++end_unlock:
++      acx_sem_unlock(priv);
++
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/***********************************************************************
++*/
++static int
++acx_ioctl_get_mode(
++      struct net_device *dev,
++      struct iw_request_info *info,
++      u32 *uwrq,
++      char *extra)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++      int result = 0;
++
++      switch (priv->mode) {
++      case ACX_MODE_OFF:
++              *uwrq = IW_MODE_AUTO; break;
++#if WIRELESS_EXT > 14
++      case ACX_MODE_MONITOR:
++              *uwrq = IW_MODE_MONITOR; break;
++#endif /* WIRELESS_EXT > 14 */
++      case ACX_MODE_0_ADHOC:
++              *uwrq = IW_MODE_ADHOC; break;
++      case ACX_MODE_2_STA:
++              *uwrq = IW_MODE_INFRA; break;
++      case ACX_MODE_3_AP:
++              *uwrq = IW_MODE_MASTER; break;
++      default:
++              result = -EOPNOTSUPP;
++      }
++      return result;
++}
++
++
++/***********************************************************************
++*/
++static int
++acx_ioctl_set_sens(
++      struct net_device *dev,
++      struct iw_request_info *info,
++      struct iw_param *vwrq,
++      char *extra)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++
++      acx_sem_lock(priv);
++
++      priv->sensitivity = (1 == vwrq->disabled) ? 0 : vwrq->value;
++      SET_BIT(priv->set_mask, GETSET_SENSITIVITY);
++
++      acx_sem_unlock(priv);
++
++      return -EINPROGRESS;
++}
++
++
++/***********************************************************************
++*/
++static int
++acx_ioctl_get_sens(
++      struct net_device *dev,
++      struct iw_request_info *info,
++      struct iw_param *vwrq,
++      char *extra)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++
++      /* acx_sem_lock(priv); */
++
++      vwrq->value = priv->sensitivity;
++      vwrq->disabled = (vwrq->value == 0);
++      vwrq->fixed = 1;
++
++      /* acx_sem_unlock(priv); */
++
++      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 *dev,
++      struct iw_request_info *info,
++      struct sockaddr *awrq,
++      char *extra)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++      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(priv->ap, ap);
++
++      /* We want to start rescan in managed or ad-hoc mode,
++      ** otherwise just set priv->ap.
++      ** "iwconfig <if> ap <mac> mode managed": we must be able
++      ** to set ap _first_ and _then_ set mode */
++      switch (priv->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(priv->ap);
++                      acxlog(L_IOCTL, "Not reassociating\n");
++              } else {
++                      acxlog(L_IOCTL, "Forcing reassociation\n");
++                      SET_BIT(priv->set_mask, GETSET_RESCAN);
++              }
++              break;
++      }
++      result = -EINPROGRESS;
++end:
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/***********************************************************************
++*/
++static int
++acx_ioctl_get_ap(
++      struct net_device *dev,
++      struct iw_request_info *info,
++      struct sockaddr *awrq,
++      char *extra)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++
++      if (ACX_STATUS_4_ASSOCIATED == priv->status) {
++              /* as seen in Aironet driver, airo.c */
++              MAC_COPY(awrq->sa_data, priv->bssid);
++      } else {
++              MAC_ZERO(awrq->sa_data);
++      }
++      awrq->sa_family = ARPHRD_ETHER;
++      return OK;
++}
++
++
++/*----------------------------------------------------------------
++* acx_ioctl_get_aplist
++*
++* Comment: deprecated in favour 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 *dev,
++      struct iw_request_info *info,
++      struct iw_point *dwrq,
++      char *extra)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++      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 != priv->mode) {
++              result = -EOPNOTSUPP;
++              goto end;
++      }
++
++      cur = 0;
++      for (i = 0; i < VEC_SIZE(priv->sta_list); i++) {
++              struct client *bss = &priv->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 *dev,
++      struct iw_request_info *info,
++      struct iw_param *vwrq,
++      char *extra)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++      int result;
++
++      FN_ENTER;
++
++      acx_sem_lock(priv);
++
++      /* don't start scan if device is not up yet */
++      if (!(priv->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(priv);
++      result = OK;
++
++end_unlock:
++      acx_sem_unlock(priv);
++/* end: */
++      FN_EXIT1(result);
++      return result;
++}
++
++
++#if WIRELESS_EXT > 13
++/***********************************************************************
++** acx_s_scan_add_station
++*/
++/* helper. not sure wheter it's really a _s_leeping fn */
++static char*
++acx_s_scan_add_station(
++      wlandevice_t *priv,
++      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;
++      acxlog(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;
++              acxlog(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;
++      acxlog(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;
++      acxlog(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;
++      acxlog(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 = bitpos2ratebyte;
++      while (rate) {
++              if (rate & 1) {
++                      iwe.u.bitrate.value = *p * 500000; /* units of 500kb/s */
++                      acxlog(L_IOCTL, "scan, rate: %d\n", iwe.u.bitrate.value);
++                      ptr = 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 *dev,
++      struct iw_request_info *info,
++      struct iw_point *dwrq,
++      char *extra)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++      char *ptr = extra;
++      int i;
++      int result = OK;
++
++      FN_ENTER;
++
++      acx_sem_lock(priv);
++
++      /* no scan available if device is not up yet */
++      if (!(priv->dev_state_mask & ACX_STATE_IFACE_UP)) {
++              acxlog(L_IOCTL, "iface not up yet\n");
++              result = -EAGAIN;
++              goto end_unlock;
++      }
++#if 0 /* Why is this needed? If needed, add a comment */
++      if (priv->scan_start && time_before(jiffies, priv->scan_start + 3*HZ)) {
++              acxlog(L_IOCTL, "scan in progress, no results yet\n");
++              result = -EAGAIN;
++              goto end_unlock;
++      }
++#endif
++
++#ifdef ENODATA_TO_BE_USED_AFTER_SCAN_ERROR_ONLY
++      if (priv->bss_table_count == 0) {
++              /* no stations found */
++              result = -ENODATA;
++              goto end_unlock;
++      }
++#endif
++
++      for (i = 0; i < VEC_SIZE(priv->sta_list); i++) {
++              struct client *bss = &priv->sta_list[i];
++              if (!bss->used) continue;
++              ptr = acx_s_scan_add_station(priv, ptr,
++                      extra + IW_SCAN_MAX_DATA, bss);
++      }
++      dwrq->length = ptr - extra;
++      dwrq->flags = 0;
++
++end_unlock:
++      acx_sem_unlock(priv);
++/* end: */
++      FN_EXIT1(result);
++      return result;
++}
++#endif /* WIRELESS_EXT > 13 */
++
++
++/*----------------------------------------------------------------
++* acx_ioctl_set_essid
++*----------------------------------------------------------------*/
++static int
++acx_ioctl_set_essid(
++      struct net_device *dev,
++      struct iw_request_info *info,
++      struct iw_point *dwrq,
++      char *extra)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++      int len = dwrq->length;
++      int result;
++
++      FN_ENTER;
++
++      acxlog(L_IOCTL, "Set ESSID '%*s', length %d, flags 0x%04X\n",
++                                      len, extra, len, dwrq->flags);
++
++      if (len < 0) {
++              result = -EINVAL;
++              goto end;
++      }
++
++      acx_sem_lock(priv);
++
++      /* ESSID disabled? */
++      if (0 == dwrq->flags) {
++              priv->essid_active = 0;
++
++      } else {
++              if (dwrq->length > IW_ESSID_MAX_SIZE+1) {
++                      result = -E2BIG;
++                      goto end_unlock;
++              }
++
++              if (len > sizeof(priv->essid))
++                      len = sizeof(priv->essid);
++              memcpy(priv->essid, extra, len-1);
++              priv->essid[len-1] = '\0';
++              /* Paranoia: just in case there is a '\0'... */
++              priv->essid_len = strlen(priv->essid);
++              priv->essid_active = 1;
++      }
++
++      SET_BIT(priv->set_mask, GETSET_RESCAN);
++
++      result = -EINPROGRESS;
++
++end_unlock:
++      acx_sem_unlock(priv);
++end:
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/***********************************************************************
++*/
++static int
++acx_ioctl_get_essid(
++      struct net_device *dev,
++      struct iw_request_info *info,
++      struct iw_point *dwrq,
++      char *extra)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++
++      dwrq->flags = priv->essid_active;
++      if (priv->essid_active) {
++              memcpy(extra, priv->essid, priv->essid_len);
++              extra[priv->essid_len] = '\0';
++              dwrq->length = priv->essid_len + 1;
++              dwrq->flags = 1;
++      }
++      return OK;
++}
++
++
++/*----------------------------------------------------------------
++* acx_l_update_client_rates
++*----------------------------------------------------------------*/
++static void
++acx_l_update_client_rates(wlandevice_t *priv, u16 rate)
++{
++      int i;
++      for (i = 0; i < VEC_SIZE(priv->sta_list); i++) {
++              client_t *clt = &priv->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(priv, 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);
++              }
++              clt->fallback_count = clt->stepup_count = 0;
++              clt->ignore_count = 16;
++      }
++      switch (priv->mode) {
++      case ACX_MODE_2_STA:
++              if (priv->ap_client && !priv->ap_client->used) {
++                      /* Owwww... we kicked our AP!! :) */
++                      SET_BIT(priv->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 *dev,
++      struct iw_request_info *info,
++      struct iw_param *vwrq,
++      char *extra)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++      u16 txrate_cfg = 1;
++      unsigned long flags;
++      int autorate;
++      int result = -EINVAL;
++
++      FN_ENTER;
++      acxlog(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(priv) ? 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(priv)) {
++              txrate_cfg &= RATE111_ACX100_COMPAT;
++              if (!txrate_cfg) {
++                      result = -ENOTSUPP; /* rate is not supported by acx100 */
++                      goto end;
++              }
++      }
++
++      acx_sem_lock(priv);
++      acx_lock(priv, flags);
++
++      priv->rate_auto = autorate;
++      priv->rate_oper = txrate_cfg;
++      priv->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 */
++              priv->rate_basic &= RATE111_80211B_COMPAT;
++      }
++      priv->rate_bcast = 1 << lowest_bit(txrate_cfg);
++      if (IS_ACX100(priv))
++              priv->rate_bcast100 = acx_rate111to100(priv->rate_bcast);
++      acx_l_update_ratevector(priv);
++      acx_l_update_client_rates(priv, txrate_cfg);
++
++      /* Do/don't do tx rate fallback; beacon contents and rate */
++      SET_BIT(priv->set_mask, SET_RATE_FALLBACK|SET_TEMPLATES);
++      result = -EINPROGRESS;
++
++      acx_unlock(priv, flags);
++      acx_sem_unlock(priv);
++end:
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/*----------------------------------------------------------------
++* acx_ioctl_get_rate
++*----------------------------------------------------------------*/
++static int
++acx_ioctl_get_rate(
++      struct net_device *dev,
++      struct iw_request_info *info,
++      struct iw_param *vwrq,
++      char *extra)
++{
++      /* TODO: remember rate of last tx, show it. think about multiple peers... */
++      wlandevice_t *priv = netdev_priv(dev);
++      vwrq->value = acx111_rate_tbl[highest_bit(priv->rate_oper)];
++      vwrq->fixed = !priv->rate_auto;
++      vwrq->disabled = 0;
++      return OK;
++}
++
++static int
++acx_ioctl_set_rts(
++      struct net_device *dev,
++      struct iw_request_info *info,
++      struct iw_param *vwrq,
++      char *extra)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++      int val = vwrq->value;
++
++      if (vwrq->disabled)
++              val = 2312;
++      if ((val < 0) || (val > 2312))
++              return -EINVAL;
++
++      priv->rts_threshold = val;
++      return OK;
++}
++
++static inline int
++acx_ioctl_get_rts(
++      struct net_device *dev,
++      struct iw_request_info *info,
++      struct iw_param *vwrq,
++      char *extra)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++
++      vwrq->value = priv->rts_threshold;
++      vwrq->disabled = (vwrq->value >= 2312);
++      vwrq->fixed = 1;
++      return OK;
++}
++
++
++/*----------------------------------------------------------------
++* acx_ioctl_set_encode
++*----------------------------------------------------------------*/
++static int
++acx_ioctl_set_encode(
++      struct net_device *dev,
++      struct iw_request_info *info,
++      struct iw_point *dwrq,
++      char *extra)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++      int index;
++      int result;
++
++      FN_ENTER;
++      acxlog(L_IOCTL,
++             "Set Encoding flags=0x%04X, size=%d, key: %s\n",
++             dwrq->flags, dwrq->length, extra ? "set" : "No key");
++
++      acx_sem_lock(priv);
++
++      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)priv->wep_current_index;
++
++              if (0 == (dwrq->flags & IW_ENCODE_NOKEY)) {
++                      if (dwrq->length > 29)
++                              dwrq->length = 29; /* restrict it */
++
++                      if (dwrq->length > 13)
++                              priv->wep_keys[index].size = 29; /* 29*8 == 232, WEP256 */
++                      else
++                      if (dwrq->length > 5)
++                              priv->wep_keys[index].size = 13; /* 13*8 == 104bit, WEP128 */
++                      else
++                      if (dwrq->length > 0)
++                              priv->wep_keys[index].size = 5; /* 5*8 == 40bit, WEP64 */
++                      else
++                              /* disable key */
++                              priv->wep_keys[index].size = 0;
++
++                      memset(priv->wep_keys[index].key, 0, sizeof(priv->wep_keys[index].key));
++                      memcpy(priv->wep_keys[index].key, extra, dwrq->length);
++              }
++
++      } else {
++              /* set transmit key */
++              if ((index >= 0) && (index <= 3))
++                      priv->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;
++                      }
++      }
++
++      priv->wep_enabled = !(dwrq->flags & IW_ENCODE_DISABLED);
++
++      if (dwrq->flags & IW_ENCODE_OPEN) {
++              priv->auth_alg = WLAN_AUTH_ALG_OPENSYSTEM;
++              priv->wep_restricted = 0;
++
++      } else if (dwrq->flags & IW_ENCODE_RESTRICTED) {
++              priv->auth_alg = WLAN_AUTH_ALG_SHAREDKEY;
++              priv->wep_restricted = 1;
++      }
++
++      /* set flag to make sure the card WEP settings get updated */
++      SET_BIT(priv->set_mask, GETSET_WEP);
++
++      acxlog(L_IOCTL, "len=%d, key at 0x%p, flags=0x%X\n",
++             dwrq->length, extra,
++             dwrq->flags);
++
++      for (index = 0; index <= 3; index++) {
++              if (priv->wep_keys[index].size) {
++                      acxlog(L_IOCTL,
++                              "index=%d, size=%d, key at 0x%p\n",
++                              priv->wep_keys[index].index,
++                              (int) priv->wep_keys[index].size,
++                              priv->wep_keys[index].key);
++              }
++      }
++      result = -EINPROGRESS;
++
++end_unlock:
++      acx_sem_unlock(priv);
++
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/*----------------------------------------------------------------
++* acx_ioctl_get_encode
++*----------------------------------------------------------------*/
++static int
++acx_ioctl_get_encode(
++      struct net_device *dev,
++      struct iw_request_info *info,
++      struct iw_point *dwrq,
++      char *extra)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++      int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
++
++      if (priv->wep_enabled == 0) {
++              dwrq->flags = IW_ENCODE_DISABLED;
++
++      } else {
++              if ((index < 0) || (index > 3))
++                      index = (int)priv->wep_current_index;
++
++              dwrq->flags =
++                      (priv->wep_restricted == 1) ? IW_ENCODE_RESTRICTED : IW_ENCODE_OPEN;
++              dwrq->length = priv->wep_keys[index].size;
++
++              memcpy(extra,
++                           priv->wep_keys[index].key,
++                           priv->wep_keys[index].size);
++      }
++
++      /* set the current index */
++      SET_BIT(dwrq->flags, index + 1);
++
++      acxlog(L_IOCTL, "len=%d, key=%p, flags=0x%X\n",
++             dwrq->length, dwrq->pointer,
++             dwrq->flags);
++
++      return OK;
++}
++
++
++/***********************************************************************
++*/
++static int
++acx_ioctl_set_power(
++      struct net_device *dev,
++      struct iw_request_info *info,
++      struct iw_param *vwrq,
++      char *extra)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++
++      acxlog(L_IOCTL, "Set 802.11 Power Save flags=0x%04X\n", vwrq->flags);
++      if (vwrq->disabled) {
++              CLEAR_BIT(priv->ps_wakeup_cfg, PS_CFG_ENABLE);
++              SET_BIT(priv->set_mask, GETSET_POWER_80211);
++              return -EINPROGRESS;
++      }
++      if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
++              u16 ps_timeout = (vwrq->value * 1024) / 1000;
++
++              if (ps_timeout > 255)
++                      ps_timeout = 255;
++              acxlog(L_IOCTL, "setting PS timeout value to %d time units "
++                              "due to %dus\n", ps_timeout, vwrq->value);
++              priv->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;
++              acxlog(L_IOCTL, "setting PS period value to %d periods "
++                              "due to %dus\n", ps_periods, vwrq->value);
++              priv->ps_listen_interval = ps_periods;
++              CLEAR_BIT(priv->ps_wakeup_cfg, PS_CFG_WAKEUP_MODE_MASK);
++              SET_BIT(priv->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(priv->ps_options, PS_OPT_STILL_RCV_BCASTS);
++                      break;
++              case IW_POWER_MULTICAST_R:
++                      SET_BIT(priv->ps_options, PS_OPT_STILL_RCV_BCASTS);
++                      break;
++              case IW_POWER_ALL_R:
++                      SET_BIT(priv->ps_options, PS_OPT_STILL_RCV_BCASTS);
++                      break;
++              case IW_POWER_ON:
++                      break;
++              default:
++                      acxlog(L_IOCTL, "unknown PS mode\n");
++                      return -EINVAL;
++      }
++
++      SET_BIT(priv->ps_wakeup_cfg, PS_CFG_ENABLE);
++      SET_BIT(priv->set_mask, GETSET_POWER_80211);
++
++      return -EINPROGRESS;
++
++}
++
++
++/***********************************************************************
++*/
++static int
++acx_ioctl_get_power(
++      struct net_device *dev,
++      struct iw_request_info *info,
++      struct iw_param *vwrq,
++      char *extra)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++
++      acxlog(L_IOCTL, "Get 802.11 Power Save flags = 0x%04X\n", vwrq->flags);
++      vwrq->disabled = ((priv->ps_wakeup_cfg & PS_CFG_ENABLE) == 0);
++      if (vwrq->disabled)
++              return OK;
++      if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
++              vwrq->value = priv->ps_hangover_period * 1000 / 1024;
++              vwrq->flags = IW_POWER_TIMEOUT;
++      } else {
++              vwrq->value = priv->ps_listen_interval * 1000000;
++              vwrq->flags = IW_POWER_PERIOD|IW_POWER_RELATIVE;
++      }
++      if (priv->ps_options & PS_OPT_STILL_RCV_BCASTS)
++              SET_BIT(vwrq->flags, IW_POWER_ALL_R);
++      else
++              SET_BIT(vwrq->flags, IW_POWER_UNICAST_R);
++
++      return OK;
++}
++
++
++/*----------------------------------------------------------------
++* acx_ioctl_get_txpow
++*----------------------------------------------------------------*/
++static inline int
++acx_ioctl_get_txpow(
++      struct net_device *dev,
++      struct iw_request_info *info,
++      struct iw_param *vwrq,
++      char *extra)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++
++      vwrq->flags = IW_TXPOW_DBM;
++      vwrq->disabled = 0;
++      vwrq->fixed = 1;
++      vwrq->value = priv->tx_level_dbm;
++
++      acxlog(L_IOCTL, "get txpower:%d dBm\n", priv->tx_level_dbm);
++
++      return OK;
++}
++
++
++/*----------------------------------------------------------------
++* acx_ioctl_set_txpow
++*----------------------------------------------------------------*/
++static int
++acx_ioctl_set_txpow(
++      struct net_device *dev,
++      struct iw_request_info *info,
++      struct iw_param *vwrq,
++      char *extra)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++      int result;
++
++      FN_ENTER;
++      acxlog(L_IOCTL, "set txpower:%d, disabled:%d, flags:0x%04X\n",
++                      vwrq->value, vwrq->disabled, vwrq->flags);
++
++      acx_sem_lock(priv);
++
++      if (vwrq->disabled != priv->tx_disabled) {
++              SET_BIT(priv->set_mask, GETSET_TX); /* Tx status needs update later */
++      }
++
++      priv->tx_disabled = vwrq->disabled;
++      if (vwrq->value == -1) {
++              if (vwrq->disabled) {
++                      priv->tx_level_dbm = 0;
++                      acxlog(L_IOCTL, "disable radio tx\n");
++              } else {
++                      /* priv->tx_level_auto = 1; */
++                      acxlog(L_IOCTL, "set tx power auto (NIY)\n");
++              }
++      } else {
++              priv->tx_level_dbm = vwrq->value <= 20 ? vwrq->value : 20;
++              /* priv->tx_level_auto = 0; */
++              acxlog(L_IOCTL, "set txpower=%d dBm\n", priv->tx_level_dbm);
++      }
++      SET_BIT(priv->set_mask, GETSET_TXPOWER);
++
++      result = -EINPROGRESS;
++
++      acx_sem_unlock(priv);
++
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/*----------------------------------------------------------------
++* acx_ioctl_get_range
++*----------------------------------------------------------------*/
++static int
++acx_ioctl_get_range(
++      struct net_device *dev,
++      struct iw_request_info *info,
++      struct iw_point *dwrq,
++      char *extra)
++{
++      if (dwrq->pointer != NULL) {
++              struct iw_range *range = (struct iw_range *)extra;
++              wlandevice_t *priv = netdev_priv(dev);
++              unsigned int i;
++
++              dwrq->length = sizeof(struct iw_range);
++              memset(range, 0, sizeof(struct iw_range));
++              range->num_channels = 0;
++              for (i = 1; i <= 14; i++) {
++                      if (priv->reg_dom_chanmask & (1 << (i - 1))) {
++                              range->freq[range->num_channels].i = i;
++                              range->freq[range->num_channels].m = acx_channel_freq[i - 1] * 100000;
++                              range->freq[range->num_channels++].e = 1; /* MHz values */
++                      }
++              }
++              range->num_frequency = range->num_channels;
++
++              range->min_rts = 0;
++              range->max_rts = 2312;
++              /* range->min_frag = 256;
++               * range->max_frag = 2312;
++               */
++
++              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;
++
++              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;
++
++              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(priv))
++                      range->sensitivity = 0;
++              else if (IS_ACX111(priv))
++                      range->sensitivity = 3;
++              else
++                      range->sensitivity = 255;
++
++              for (i=0; i < priv->rate_supported_len; i++) {
++                      range->bitrate[i] = (priv->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;
++      }
++
++      return OK;
++}
++
++
++/*================================================================*/
++/* Private functions                                            */
++/*================================================================*/
++
++#if WIRELESS_EXT < 13
++/*----------------------------------------------------------------
++* acx_ioctl_get_iw_priv
++*
++* Comment: I added the monitor mode and changed the stuff below
++* to look more like the orinoco driver
++*----------------------------------------------------------------*/
++static int
++acx_ioctl_get_iw_priv(struct iwreq *iwr)
++{
++      int result = -EINVAL;
++
++      if (!iwr->u.data.pointer)
++              return -EINVAL;
++      result = verify_area(VERIFY_WRITE, iwr->u.data.pointer,
++                      sizeof(acx_ioctl_private_args));
++      if (result)
++              return result;
++
++      iwr->u.data.length = VEC_SIZE(acx_ioctl_private_args);
++      if (copy_to_user(iwr->u.data.pointer, acx_ioctl_private_args, sizeof(acx_ioctl_private_args)) != 0)
++              result = -EFAULT;
++
++      return result;
++}
++#endif
++
++
++/*----------------------------------------------------------------
++* acx_ioctl_get_nick
++*----------------------------------------------------------------*/
++static inline int
++acx_ioctl_get_nick(
++      struct net_device *dev,
++      struct iw_request_info *info,
++      struct iw_point *dwrq,
++      char *extra)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++
++      /* FIXME : consider spinlock here */
++      strcpy(extra, priv->nick);
++      /* FIXME : consider spinlock here */
++
++      dwrq->length = strlen(extra) + 1;
++
++      return OK;
++}
++
++
++/*----------------------------------------------------------------
++* acx_ioctl_set_nick
++*----------------------------------------------------------------*/
++static int
++acx_ioctl_set_nick(
++      struct net_device *dev,
++      struct iw_request_info *info,
++      struct iw_point *dwrq,
++      char *extra)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++      int result;
++
++      FN_ENTER;
++
++      acx_sem_lock(priv);
++
++      if (dwrq->length > IW_ESSID_MAX_SIZE + 1) {
++              result = -E2BIG;
++              goto end_unlock;
++      }
++
++      /* extra includes trailing \0, so it's ok */
++      strcpy(priv->nick, extra);
++      result = OK;
++
++end_unlock:
++      acx_sem_unlock(priv);
++
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/*------------------------------------------------------------------------------
++ * acx_ioctl_get_retry
++ *----------------------------------------------------------------------------*/
++static int
++acx_ioctl_get_retry(
++      struct net_device *dev,
++      struct iw_request_info *info,
++      struct iw_param *vwrq,
++      char *extra)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++      unsigned int type = vwrq->flags & IW_RETRY_TYPE;
++      unsigned int modifier = vwrq->flags & IW_RETRY_MODIFIER;
++      int result;
++
++      acx_sem_lock(priv);
++
++      /* return the short retry number by default */
++      if (type == IW_RETRY_LIFETIME) {
++              vwrq->flags = IW_RETRY_LIFETIME;
++              vwrq->value = priv->msdu_lifetime;
++      } else if (modifier == IW_RETRY_MAX) {
++              vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
++              vwrq->value = priv->long_retry;
++      } else {
++              vwrq->flags = IW_RETRY_LIMIT;
++              if (priv->long_retry != priv->short_retry)
++                      SET_BIT(vwrq->flags, IW_RETRY_MIN);
++              vwrq->value = priv->short_retry;
++      }
++
++      /* can't be disabled */
++      vwrq->disabled = (u8)0;
++      result = OK;
++
++      acx_sem_unlock(priv);
++
++      return result;
++}
++
++
++/*----------------------------------------------------------------
++* acx_ioctl_set_retry
++*----------------------------------------------------------------*/
++static int
++acx_ioctl_set_retry(
++      struct net_device *dev,
++      struct iw_request_info *info,
++      struct iw_param *vwrq,
++      char *extra)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++      int result;
++
++      FN_ENTER;
++
++      if (!vwrq) {
++              result = -EFAULT;
++              goto end;
++      }
++      if (vwrq->disabled) {
++              result = -EINVAL;
++              goto end;
++      }
++
++      acx_sem_lock(priv);
++
++      result = -EINVAL;
++      if (IW_RETRY_LIMIT == (vwrq->flags & IW_RETRY_TYPE)) {
++              printk("old retry limits: short %d long %d\n",
++                              priv->short_retry, priv->long_retry);
++              if (vwrq->flags & IW_RETRY_MAX) {
++                      priv->long_retry = vwrq->value;
++              } else if (vwrq->flags & IW_RETRY_MIN) {
++                      priv->short_retry = vwrq->value;
++              } else {
++                      /* no modifier: set both */
++                      priv->long_retry = vwrq->value;
++                      priv->short_retry = vwrq->value;
++              }
++              printk("new retry limits: short %d long %d\n",
++                              priv->short_retry, priv->long_retry);
++              SET_BIT(priv->set_mask, GETSET_RETRY);
++              result = -EINPROGRESS;
++      }
++      else if (vwrq->flags & IW_RETRY_LIFETIME) {
++              priv->msdu_lifetime = vwrq->value;
++              printk("new MSDU lifetime: %d\n", priv->msdu_lifetime);
++              SET_BIT(priv->set_mask, SET_MSDU_LIFETIME);
++              result = -EINPROGRESS;
++      }
++
++      acx_sem_unlock(priv);
++end:
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/******************************* private ioctls ******************************/
++
++
++/*----------------------------------------------------------------
++* acx_ioctl_set_debug
++*----------------------------------------------------------------*/
++#if ACX_DEBUG
++static int
++acx_ioctl_set_debug(
++      struct net_device *dev,
++      struct iw_request_info *info,
++      struct iw_param *vwrq,
++      char *extra)
++{
++      unsigned int debug_new = *((unsigned int *)extra);
++      int result = -EINVAL;
++
++      acxlog(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 const char * const
++reg_domain_strings[] = {
++      " 1-11 FCC (USA)",
++      " 1-11 DOC/IC (Canada)",
++      /* BTW: WLAN use in ETSI is regulated by
++       * ETSI standard EN 300 328-2 V1.1.2 */
++      " 1-13 ETSI (Europe)",
++      "10-11 Spain",
++      "10-13 France",
++      "   14 MKK (Japan)",
++      " 1-14 MKK1",
++      "  3-9 Israel (not all firmware versions)",
++      NULL /* needs to remain as last entry */
++};
++
++static int
++acx_ioctl_list_reg_domain(
++      struct net_device *dev,
++      struct iw_request_info *info,
++      struct iw_param *vwrq,
++      char *extra)
++{
++
++      int i = 1;
++      const char * const *entry = 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 *dev,
++      struct iw_request_info *info,
++      struct iw_param *vwrq,
++      char *extra)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++      int result;
++
++      FN_ENTER;
++
++      if ((*extra < 1) || ((size_t)*extra > reg_domain_ids_len)) {
++              result = -EINVAL;
++              goto end;
++      }
++
++      acx_sem_lock(priv);
++
++      priv->reg_dom_id = reg_domain_ids[*extra - 1];
++      SET_BIT(priv->set_mask, GETSET_REG_DOMAIN);
++
++      result = -EINPROGRESS;
++
++      acx_sem_unlock(priv);
++end:
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/*----------------------------------------------------------------
++* acx_ioctl_get_reg_domain
++*----------------------------------------------------------------*/
++static int
++acx_ioctl_get_reg_domain(
++      struct net_device *dev,
++      struct iw_request_info *info,
++      struct iw_param *vwrq,
++      char *extra)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++      int dom,i;
++
++      /* no locking */
++      dom = priv->reg_dom_id;
++
++      for (i=1; i <= 7; i++) {
++              if (reg_domain_ids[i-1] == dom) {
++                      acxlog(L_IOCTL, "regulatory domain is currently set "
++                              "to %d (0x%X): %s\n", i, dom,
++                              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 *dev,
++      struct iw_request_info *info,
++      struct iw_param *vwrq,
++      char *extra)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++      int i;
++      int result;
++
++      FN_ENTER;
++
++      if ((unsigned char)*extra > 2) {
++              result = -EINVAL;
++              goto end;
++      }
++
++      acx_sem_lock(priv);
++
++      priv->preamble_mode = (u8)*extra;
++      switch (priv->preamble_mode) {
++      case 0: /* long */
++              priv->preamble_cur = 0;
++              break;
++      case 1:
++              /* short, kick incapable peers */
++              priv->preamble_cur = 1;
++              for (i = 0; i < VEC_SIZE(priv->sta_list); i++) {
++                      client_t *clt = &priv->sta_list[i];
++                      if (!clt->used) continue;
++                      if (!(clt->cap_info & WF_MGMT_CAP_SHORT)) {
++                              clt->used = CLIENT_EMPTY_SLOT_0;
++                      }
++              }
++              switch (priv->mode) {
++              case ACX_MODE_2_STA:
++                      if (priv->ap_client && !priv->ap_client->used) {
++                              /* We kicked our AP :) */
++                              SET_BIT(priv->set_mask, GETSET_RESCAN);
++                      }
++              }
++              break;
++      case 2: /* auto. short only if all peers are short-capable */
++              priv->preamble_cur = 1;
++              for (i = 0; i < VEC_SIZE(priv->sta_list); i++) {
++                      client_t *clt = &priv->sta_list[i];
++                      if (!clt->used) continue;
++                      if (!(clt->cap_info & WF_MGMT_CAP_SHORT)) {
++                              priv->preamble_cur = 0;
++                              break;
++                      }
++              }
++              break;
++      }
++      printk("new short preamble setting: configured %s, active %s\n",
++                      preamble_modes[priv->preamble_mode],
++                      preamble_modes[priv->preamble_cur]);
++      result = OK;
++
++      acx_sem_unlock(priv);
++end:
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/*----------------------------------------------------------------
++* acx_ioctl_get_short_preamble
++*----------------------------------------------------------------*/
++static int
++acx_ioctl_get_short_preamble(
++      struct net_device *dev,
++      struct iw_request_info *info,
++      struct iw_param *vwrq,
++      char *extra)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++
++      acx_sem_lock(priv);
++
++      printk("current short preamble setting: configured %s, active %s\n",
++                      preamble_modes[priv->preamble_mode],
++                      preamble_modes[priv->preamble_cur]);
++
++      *extra = (char)priv->preamble_mode;
++
++      acx_sem_unlock(priv);
++
++      return OK;
++}
++
++
++/*----------------------------------------------------------------
++* acx_ioctl_set_antenna
++*
++* Comment: 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 *dev,
++      struct iw_request_info *info,
++      struct iw_param *vwrq,
++      char *extra)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++
++      acx_sem_lock(priv);
++
++      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",
++                   priv->antenna, (u8)*extra);
++
++      priv->antenna = (u8)*extra;
++      SET_BIT(priv->set_mask, GETSET_ANTENNA);
++
++      acx_sem_unlock(priv);
++
++      return -EINPROGRESS;
++}
++
++
++/*----------------------------------------------------------------
++* acx_ioctl_get_antenna
++*----------------------------------------------------------------*/
++static int
++acx_ioctl_get_antenna(
++      struct net_device *dev,
++      struct iw_request_info *info,
++      struct iw_param *vwrq,
++      char *extra)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++
++      /* 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", priv->antenna);
++
++      return 0;
++}
++
++
++/*----------------------------------------------------------------
++* acx_ioctl_set_rx_antenna
++*
++*
++* Arguments:
++*     0 = antenna1; 1 = antenna2; 2 = full diversity; 3 = partial diversity
++* Comment: Could anybody test which antenna is the external one
++*----------------------------------------------------------------*/
++static int
++acx_ioctl_set_rx_antenna(
++      struct net_device *dev,
++      struct iw_request_info *info,
++      struct iw_param *vwrq,
++      char *extra)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++      int result;
++
++      FN_ENTER;
++
++      if (*extra > 3) {
++              result = -EINVAL;
++              goto end;
++      }
++
++      printk("old antenna value: 0x%02X\n", priv->antenna);
++
++      acx_sem_lock(priv);
++
++      priv->antenna &= 0x3f;
++      SET_BIT(priv->antenna, (*extra << 6));
++      SET_BIT(priv->set_mask, GETSET_ANTENNA);
++      printk("new antenna value: 0x%02X\n", priv->antenna);
++      result = -EINPROGRESS;
++
++      acx_sem_unlock(priv);
++end:
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/*----------------------------------------------------------------
++* acx_ioctl_set_tx_antenna
++*
++*
++* Arguments: 0 == antenna2; 1 == antenna1;
++* Comment: Could anybody test which antenna is the external one
++*----------------------------------------------------------------*/
++static int
++acx_ioctl_set_tx_antenna(
++      struct net_device *dev,
++      struct iw_request_info *info,
++      struct iw_param *vwrq,
++      char *extra)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++      int result;
++
++      FN_ENTER;
++
++      if (*extra > 1) {
++              result = -EINVAL;
++              goto end;
++      }
++
++      printk("old antenna value: 0x%02X\n", priv->antenna);
++
++      acx_sem_lock(priv);
++
++      priv->antenna &= ~0x30;
++      SET_BIT(priv->antenna, ((*extra & 0x01) << 5));
++      SET_BIT(priv->set_mask, GETSET_ANTENNA);
++      printk("new antenna value: 0x%02X\n", priv->antenna);
++      result = -EINPROGRESS;
++
++      acx_sem_unlock(priv);
++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 *dev,
++      struct iw_request_info *info,
++      struct iw_param *vwrq,
++      char *extra)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++      unsigned int *params = (unsigned int*)extra;
++      unsigned int enable = (unsigned int)(params[0] > 0);
++      int result;
++
++      FN_ENTER;
++
++      acx_sem_lock(priv);
++
++      /* not using printk() here, since it distorts kismet display
++       * when printk messages activated */
++      acxlog(L_IOCTL, "setting monitor to: 0x%02X\n", params[0]);
++
++      switch (params[0]) {
++      case 0:
++              priv->netdev->type = ARPHRD_ETHER;
++              break;
++      case 1:
++              priv->netdev->type = ARPHRD_IEEE80211_PRISM;
++              break;
++      case 2:
++              priv->netdev->type = ARPHRD_IEEE80211;
++              break;
++      }
++
++      if (params[0]) {
++              priv->mode = ACX_MODE_MONITOR;
++              SET_BIT(priv->set_mask, GETSET_MODE);
++      }
++
++      if (enable) {
++              priv->channel = params[1];
++              SET_BIT(priv->set_mask, GETSET_RX);
++      }
++      result = -EINPROGRESS;
++
++      acx_sem_unlock(priv);
++
++      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 *dev,
++      struct iw_request_info *info,
++      struct iw_param *vwrq,
++      char *extra)
++{
++#ifdef BROKEN
++      wlandevice_t *priv = netdev_priv(dev);
++      unsigned long flags;
++      client_t client;
++      int result;
++
++      acx_sem_lock(priv);
++      acx_lock(priv, flags);
++
++      acx_l_transmit_disassoc(priv, &client);
++      result = OK;
++
++      acx_unlock(priv, flags);
++      acx_sem_unlock(priv);
++
++      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 *dev,
++      struct iw_request_info *info,
++      struct iw_param *vwrq,
++      char *extra)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++      const unsigned int *params = (unsigned int*)extra;
++      int result;
++
++      acx_sem_lock(priv);
++
++      acxlog(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],
++                      priv->get_mask, priv->set_mask);
++      SET_BIT(priv->get_mask, params[0]);
++      SET_BIT(priv->set_mask, params[1]);
++      acxlog(L_IOCTL, "after: get_mask %08X set_mask %08X\n",
++                      priv->get_mask, priv->set_mask);
++      result = -EINPROGRESS; /* immediately call commit handler */
++
++      acx_sem_unlock(priv);
++
++      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 *dev, struct iw_request_info *info,
++               struct iw_param *vwrq, char *extra)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++      unsigned long flags;
++      int result;
++      u32 brate = 0, orate = 0; /* basic, operational rate set */
++
++      FN_ENTER;
++
++      acxlog(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);
++      acxlog(L_IOCTL, "brate %08X orate %08X\n", brate, orate);
++
++      result = verify_rate(brate, priv->chip_type);
++      if (result) goto end;
++      result = verify_rate(orate, priv->chip_type);
++      if (result) goto end;
++
++      acx_sem_lock(priv);
++      acx_lock(priv, flags);
++
++      priv->rate_basic = brate;
++      priv->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 */
++      priv->rate_bcast = 1 << lowest_bit(brate);
++      if (IS_ACX100(priv))
++              priv->rate_bcast100 = acx_rate111to100(priv->rate_bcast);
++      priv->rate_auto = !has_only_one_bit(orate);
++      acx_l_update_client_rates(priv, orate);
++      /* TODO: get rid of ratevector, build it only when needed */
++      acx_l_update_ratevector(priv);
++
++      /* Do/don't do tx rate fallback; beacon contents and rate */
++      SET_BIT(priv->set_mask, SET_RATE_FALLBACK|SET_TEMPLATES);
++      result = -EINPROGRESS;
++
++      acx_unlock(priv, flags);
++      acx_sem_unlock(priv);
++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 *dev,
++      struct iw_request_info *info,
++      struct iw_param *vwrq,
++      char *extra)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++      struct { /* added ACX_PACKED, not tested --vda */
++              u16 type ACX_PACKED;
++              u16 len ACX_PACKED;
++              u32 busytime ACX_PACKED;
++              u32 totaltime ACX_PACKED;
++      } usage;
++
++      acx_sem_lock(priv);
++
++      if (OK != acx_s_interrogate(priv, &usage, ACX1xx_IE_MEDIUM_USAGE))
++              goto bad_unlock;
++
++      printk("%s: average busy percentage since last invocation: %d%% "
++              "(microseconds: %u of %u)\n",
++              dev->name,
++              100 * (le32_to_cpu(usage.busytime) / 100) / (le32_to_cpu(usage.totaltime) / 100),
++              le32_to_cpu(usage.busytime), le32_to_cpu(usage.totaltime));
++              /* prevent calculation overflow */
++
++      acx_sem_unlock(priv);
++
++      return OK;
++
++bad_unlock:
++      acx_sem_unlock(priv);
++
++      return NOT_OK;
++}
++
++
++/*----------------------------------------------------------------
++* acx_ioctl_set_ed_threshold
++*----------------------------------------------------------------*/
++static inline int
++acx_ioctl_set_ed_threshold(
++      struct net_device *dev,
++      struct iw_request_info *info,
++      struct iw_param *vwrq,
++      char *extra)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++
++      acx_sem_lock(priv);
++
++      printk("old ED threshold value: %d\n", priv->ed_threshold);
++      priv->ed_threshold = (unsigned char)*extra;
++      printk("new ED threshold value: %d\n", (unsigned char)*extra);
++      SET_BIT(priv->set_mask, GETSET_ED_THRESH);
++
++      acx_sem_unlock(priv);
++
++      return -EINPROGRESS;
++}
++
++
++/*----------------------------------------------------------------
++* acx_ioctl_set_cca
++*----------------------------------------------------------------*/
++static inline int
++acx_ioctl_set_cca(
++      struct net_device *dev,
++      struct iw_request_info *info,
++      struct iw_param *vwrq,
++      char *extra)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++      int result;
++
++      acx_sem_lock(priv);
++
++      printk("old CCA value: 0x%02X\n", priv->cca);
++      priv->cca = (unsigned char)*extra;
++      printk("new CCA value: 0x%02X\n", (unsigned char)*extra);
++      SET_BIT(priv->set_mask, GETSET_CCA);
++      result = -EINPROGRESS;
++
++      acx_sem_unlock(priv);
++
++      return result;
++}
++
++
++/***********************************************************************
++*/
++static const char * const
++scan_modes[] = { "active", "passive", "background" };
++
++static void
++acx_print_scan_params(wlandevice_t *priv, const char* head)
++{
++      printk("%s: %smode %d (%s), min chan time %dTU, "
++              "max chan time %dTU, max scan rate byte: %d\n",
++              priv->netdev->name, head,
++              priv->scan_mode, scan_modes[priv->scan_mode],
++              priv->scan_probe_delay, priv->scan_duration, priv->scan_rate);
++}
++
++static int
++acx_ioctl_set_scan_params(
++      struct net_device *dev,
++      struct iw_request_info *info,
++      struct iw_param *vwrq,
++      char *extra)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++      int result;
++      const int *params = (int *)extra;
++
++      acx_sem_lock(priv);
++
++      acx_print_scan_params(priv, "old scan parameters: ");
++      if ((params[0] != -1) && (params[0] >= 0) && (params[0] <= 2))
++              priv->scan_mode = params[0];
++      if (params[1] != -1)
++              priv->scan_probe_delay = params[1];
++      if (params[2] != -1)
++              priv->scan_duration = params[2];
++      if ((params[3] != -1) && (params[3] <= 255))
++              priv->scan_rate = params[3];
++      acx_print_scan_params(priv, "new scan parameters: ");
++      SET_BIT(priv->set_mask, GETSET_RESCAN);
++      result = -EINPROGRESS;
++
++      acx_sem_unlock(priv);
++
++      return result;
++}
++
++static int
++acx_ioctl_get_scan_params(
++      struct net_device *dev,
++      struct iw_request_info *info,
++      struct iw_param *vwrq,
++      char *extra)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++      int result;
++      int *params = (int *)extra;
++
++      acx_sem_lock(priv);
++
++      acx_print_scan_params(priv, "current scan parameters: ");
++      params[0] = priv->scan_mode;
++      params[1] = priv->scan_probe_delay;
++      params[2] = priv->scan_duration;
++      params[3] = priv->scan_rate;
++      result = OK;
++
++      acx_sem_unlock(priv);
++
++      return result;
++}
++
++
++/***********************************************************************
++*/
++static int
++acx100_ioctl_set_led_power(
++      struct net_device *dev,
++      struct iw_request_info *info,
++      struct iw_param *vwrq,
++      char *extra)
++{
++      static const char * const led_modes[] = { "off", "on", "LinkQuality" };
++
++      wlandevice_t *priv = netdev_priv(dev);
++      int result;
++
++      acx_sem_lock(priv);
++
++      printk("%s: power LED status: old %d (%s), ",
++                      dev->name,
++                      priv->led_power,
++                      led_modes[priv->led_power]);
++      priv->led_power = extra[0];
++      if (priv->led_power > 2) priv->led_power = 2;
++      printk("new %d (%s)\n",
++                      priv->led_power,
++                      led_modes[priv->led_power]);
++
++      if (priv->led_power == 2) {
++              printk("%s: max link quality setting: old %d, ",
++                      dev->name, priv->brange_max_quality);
++              if (extra[1])
++                      priv->brange_max_quality = extra[1];
++              printk("new %d\n", priv->brange_max_quality);
++      }
++
++      SET_BIT(priv->set_mask, GETSET_LED_POWER);
++
++      result = -EINPROGRESS;
++
++      acx_sem_unlock(priv);
++
++      return result;
++}
++
++
++/***********************************************************************
++*/
++static inline int
++acx100_ioctl_get_led_power(
++      struct net_device *dev,
++      struct iw_request_info *info,
++      struct iw_param *vwrq,
++      char *extra)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++
++      acx_sem_lock(priv);
++
++      extra[0] = priv->led_power;
++      if (priv->led_power == 2)
++              extra[1] = priv->brange_max_quality;
++      else
++              extra[1] = -1;
++
++      acx_sem_unlock(priv);
++
++      return OK;
++}
++
++
++/***********************************************************************
++*/
++static int
++acx111_ioctl_info(
++      struct net_device *dev,
++      struct iw_request_info *info,
++      struct iw_param *vwrq,
++      char *extra)
++{
++      if (!IS_PCI((wlandevice_t*)netdev_priv(dev)))
++              return OK;
++      return acx111pci_ioctl_info(dev, info, vwrq, extra);
++}
++
++
++/***********************************************************************
++*/
++static int
++acx100_ioctl_set_phy_amp_bias(
++      struct net_device *dev,
++      struct iw_request_info *info,
++      struct iw_param *vwrq,
++      char *extra)
++{
++      if (!IS_PCI((wlandevice_t*)netdev_priv(dev))) {
++              printk("acx: set_phy_amp_bias() is not supported on USB\n");
++              return OK;
++      }
++      return acx100pci_ioctl_set_phy_amp_bias(dev, info, vwrq, extra);
++}
++
++
++/***********************************************************************
++*/
++#if WIRELESS_EXT >= 13
++static const iw_handler acx_ioctl_handler[] =
++{
++      (iw_handler) acx_ioctl_commit,          /* SIOCSIWCOMMIT */
++      (iw_handler) acx_ioctl_get_name,        /* SIOCGIWNAME */
++      (iw_handler) NULL,                      /* SIOCSIWNWID */
++      (iw_handler) NULL,                      /* SIOCGIWNWID */
++      (iw_handler) acx_ioctl_set_freq,        /* SIOCSIWFREQ */
++      (iw_handler) acx_ioctl_get_freq,        /* SIOCGIWFREQ */
++      (iw_handler) acx_ioctl_set_mode,        /* SIOCSIWMODE */
++      (iw_handler) acx_ioctl_get_mode,        /* SIOCGIWMODE */
++      (iw_handler) acx_ioctl_set_sens,        /* SIOCSIWSENS */
++      (iw_handler) acx_ioctl_get_sens,        /* SIOCGIWSENS */
++      (iw_handler) NULL,                      /* SIOCSIWRANGE */
++      (iw_handler) acx_ioctl_get_range,       /* SIOCGIWRANGE */
++      (iw_handler) NULL,                      /* SIOCSIWPRIV */
++      (iw_handler) NULL,                      /* SIOCGIWPRIV */
++      (iw_handler) NULL,                      /* SIOCSIWSTATS */
++      (iw_handler) 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
++      (iw_handler) NULL /* acx_ioctl_set_spy FIXME */,        /* SIOCSIWSPY */
++      (iw_handler) NULL /* acx_ioctl_get_spy FIXME */,        /* SIOCGIWSPY */
++#else /* WSPY */
++      (iw_handler) NULL,                      /* SIOCSIWSPY */
++      (iw_handler) NULL,                      /* SIOCGIWSPY */
++#endif /* WSPY */
++      (iw_handler) NULL,                      /* [nothing] */
++      (iw_handler) NULL,                      /* [nothing] */
++#endif /* IW_HANDLER_VERSION > 4 */
++      (iw_handler) acx_ioctl_set_ap,          /* SIOCSIWAP */
++      (iw_handler) acx_ioctl_get_ap,          /* SIOCGIWAP */
++      (iw_handler) NULL,                      /* [nothing] */
++      (iw_handler) acx_ioctl_get_aplist,      /* SIOCGIWAPLIST */
++#if WIRELESS_EXT > 13
++      (iw_handler) acx_ioctl_set_scan,        /* SIOCSIWSCAN */
++      (iw_handler) acx_ioctl_get_scan,        /* SIOCGIWSCAN */
++#else /* WE > 13 */
++      (iw_handler) NULL,                      /* SIOCSIWSCAN */
++      (iw_handler) NULL,                      /* SIOCGIWSCAN */
++#endif /* WE > 13 */
++      (iw_handler) acx_ioctl_set_essid,       /* SIOCSIWESSID */
++      (iw_handler) acx_ioctl_get_essid,       /* SIOCGIWESSID */
++      (iw_handler) acx_ioctl_set_nick,        /* SIOCSIWNICKN */
++      (iw_handler) acx_ioctl_get_nick,        /* SIOCGIWNICKN */
++      (iw_handler) NULL,                      /* [nothing] */
++      (iw_handler) NULL,                      /* [nothing] */
++      (iw_handler) acx_ioctl_set_rate,        /* SIOCSIWRATE */
++      (iw_handler) acx_ioctl_get_rate,        /* SIOCGIWRATE */
++      (iw_handler) acx_ioctl_set_rts,         /* SIOCSIWRTS */
++      (iw_handler) acx_ioctl_get_rts,         /* SIOCGIWRTS */
++      (iw_handler) NULL /* acx_ioctl_set_frag FIXME */,       /* SIOCSIWFRAG */
++      (iw_handler) NULL /* acx_ioctl_get_frag FIXME */,       /* SIOCGIWFRAG */
++      (iw_handler) acx_ioctl_set_txpow,       /* SIOCSIWTXPOW */
++      (iw_handler) acx_ioctl_get_txpow,       /* SIOCGIWTXPOW */
++      (iw_handler) acx_ioctl_set_retry,       /* SIOCSIWRETRY */
++      (iw_handler) acx_ioctl_get_retry,       /* SIOCGIWRETRY */
++      (iw_handler) acx_ioctl_set_encode,      /* SIOCSIWENCODE */
++      (iw_handler) acx_ioctl_get_encode,      /* SIOCGIWENCODE */
++      (iw_handler) acx_ioctl_set_power,       /* SIOCSIWPOWER */
++      (iw_handler) acx_ioctl_get_power,       /* SIOCGIWPOWER */
++};
++
++static const iw_handler acx_ioctl_private_handler[] =
++{
++#if ACX_DEBUG
++[ACX100_IOCTL_DEBUG           - ACX100_IOCTL] = (iw_handler) acx_ioctl_set_debug,
++#else
++[ACX100_IOCTL_DEBUG           - ACX100_IOCTL] = (iw_handler) NULL,
++#endif
++[ACX100_IOCTL_SET_PLED                - ACX100_IOCTL] = (iw_handler) acx100_ioctl_set_led_power,
++[ACX100_IOCTL_GET_PLED                - ACX100_IOCTL] = (iw_handler) acx100_ioctl_get_led_power,
++[ACX100_IOCTL_SET_RATES               - ACX100_IOCTL] = (iw_handler) acx_ioctl_set_rates,
++[ACX100_IOCTL_LIST_DOM                - ACX100_IOCTL] = (iw_handler) acx_ioctl_list_reg_domain,
++[ACX100_IOCTL_SET_DOM         - ACX100_IOCTL] = (iw_handler) acx_ioctl_set_reg_domain,
++[ACX100_IOCTL_GET_DOM         - ACX100_IOCTL] = (iw_handler) acx_ioctl_get_reg_domain,
++[ACX100_IOCTL_SET_SCAN_PARAMS - ACX100_IOCTL] = (iw_handler) acx_ioctl_set_scan_params,
++[ACX100_IOCTL_GET_SCAN_PARAMS - ACX100_IOCTL] = (iw_handler) acx_ioctl_get_scan_params,
++[ACX100_IOCTL_SET_PREAMB      - ACX100_IOCTL] = (iw_handler) acx_ioctl_set_short_preamble,
++[ACX100_IOCTL_GET_PREAMB      - ACX100_IOCTL] = (iw_handler) acx_ioctl_get_short_preamble,
++[ACX100_IOCTL_SET_ANT         - ACX100_IOCTL] = (iw_handler) acx_ioctl_set_antenna,
++[ACX100_IOCTL_GET_ANT         - ACX100_IOCTL] = (iw_handler) acx_ioctl_get_antenna,
++[ACX100_IOCTL_RX_ANT          - ACX100_IOCTL] = (iw_handler) acx_ioctl_set_rx_antenna,
++[ACX100_IOCTL_TX_ANT          - ACX100_IOCTL] = (iw_handler) acx_ioctl_set_tx_antenna,
++[ACX100_IOCTL_SET_PHY_AMP_BIAS        - ACX100_IOCTL] = (iw_handler) acx100_ioctl_set_phy_amp_bias,
++[ACX100_IOCTL_GET_PHY_CHAN_BUSY       - ACX100_IOCTL] = (iw_handler) acx_ioctl_get_phy_chan_busy_percentage,
++[ACX100_IOCTL_SET_ED          - ACX100_IOCTL] = (iw_handler) acx_ioctl_set_ed_threshold,
++[ACX100_IOCTL_SET_CCA         - ACX100_IOCTL] = (iw_handler) acx_ioctl_set_cca,
++[ACX100_IOCTL_MONITOR         - ACX100_IOCTL] = (iw_handler) acx_ioctl_wlansniff,
++[ACX100_IOCTL_TEST            - ACX100_IOCTL] = (iw_handler) acx_ioctl_unknown11,
++[ACX100_IOCTL_DBG_SET_MASKS   - ACX100_IOCTL] = (iw_handler) acx_ioctl_dbg_set_masks,
++[ACX111_IOCTL_INFO            - ACX100_IOCTL] = (iw_handler) acx111_ioctl_info,
++};
++
++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,
++};
++
++#endif /* WE >= 13 */
++
++
++#if WIRELESS_EXT < 13
++/*================================================================*/
++/* Main function                                                */
++/*================================================================*/
++/*----------------------------------------------------------------
++* acx_e_ioctl_old
++*
++* Comment:
++* This is the *OLD* ioctl handler.
++* Make sure to not only place your additions here, but instead mainly
++* in the new one (acx_ioctl_handler[])!
++*----------------------------------------------------------------*/
++int
++acx_e_ioctl_old(netdevice_t *dev, struct ifreq *ifr, int cmd)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++      int result = 0;
++      struct iwreq *iwr = (struct iwreq *)ifr;
++
++      acxlog(L_IOCTL, "%s cmd = 0x%04X\n", __func__, cmd);
++
++      /* This is the way it is done in the orinoco driver.
++       * Check to see if device is present.
++       */
++      if (0 == netif_device_present(dev)) {
++              return -ENODEV;
++      }
++
++      switch (cmd) {
++/* WE 13 and higher will use acx_ioctl_handler_def */
++      case SIOCGIWNAME:
++              /* get name == wireless protocol */
++              result = acx_ioctl_get_name(dev, NULL,
++                                             (char *)&(iwr->u.name), NULL);
++              break;
++
++      case SIOCSIWNWID: /* pre-802.11, */
++      case SIOCGIWNWID: /* not supported. */
++              result = -EOPNOTSUPP;
++              break;
++
++      case SIOCSIWFREQ:
++              /* set channel/frequency (Hz)
++                 data can be frequency or channel :
++                 0-1000 = channel
++                 > 1000 = frequency in Hz */
++              result = acx_ioctl_set_freq(dev, NULL, &(iwr->u.freq), NULL);
++              break;
++
++      case SIOCGIWFREQ:
++              /* get channel/frequency (Hz) */
++              result = acx_ioctl_get_freq(dev, NULL, &(iwr->u.freq), NULL);
++              break;
++
++      case SIOCSIWMODE:
++              /* set operation mode */
++              result = acx_ioctl_set_mode(dev, NULL, &(iwr->u.mode), NULL);
++              break;
++
++      case SIOCGIWMODE:
++              /* get operation mode */
++              result = acx_ioctl_get_mode(dev, NULL, &(iwr->u.mode), NULL);
++              break;
++
++      case SIOCSIWSENS:
++              /* Set sensitivity */
++              result = acx_ioctl_set_sens(dev, NULL, &(iwr->u.sens), NULL);
++              break;
++
++      case SIOCGIWSENS:
++              /* Get sensitivity */
++              result = acx_ioctl_get_sens(dev, NULL, &(iwr->u.sens), NULL);
++              break;
++
++#if WIRELESS_EXT > 10
++      case SIOCGIWRANGE:
++              /* Get range of parameters */
++              {
++                      struct iw_range range;
++                      result = acx_ioctl_get_range(dev, NULL,
++                                      &(iwr->u.data), (char *)&range);
++                      if (copy_to_user(iwr->u.data.pointer, &range,
++                                       sizeof(struct iw_range)))
++                              result = -EFAULT;
++              }
++              break;
++#endif
++
++      case SIOCGIWPRIV:
++              result = acx_ioctl_get_iw_priv(iwr);
++              break;
++
++      /* FIXME: */
++      /* case SIOCSIWSPY: */
++      /* case SIOCGIWSPY: */
++      /* case SIOCSIWTHRSPY: */
++      /* case SIOCGIWTHRSPY: */
++
++      case SIOCSIWAP:
++              /* set access point by MAC address */
++              result = acx_ioctl_set_ap(dev, NULL, &(iwr->u.ap_addr),
++                                           NULL);
++              break;
++
++      case SIOCGIWAP:
++              /* get access point MAC address */
++              result = acx_ioctl_get_ap(dev, NULL, &(iwr->u.ap_addr),
++                                           NULL);
++              break;
++
++      case SIOCGIWAPLIST:
++              /* get list of access points in range */
++              result = acx_ioctl_get_aplist(dev, NULL, &(iwr->u.data),
++                                               NULL);
++              break;
++
++#if NOT_FINISHED_YET
++      /* FIXME: do proper interfacing to activate that! */
++      case SIOCSIWSCAN:
++              /* start a station scan */
++              result = acx_ioctl_set_scan(iwr, priv);
++              break;
++
++      case SIOCGIWSCAN:
++              /* get list of stations found during scan */
++              result = acx_ioctl_get_scan(iwr, priv);
++              break;
++#endif
++
++      case SIOCSIWESSID:
++              /* set ESSID (network name) */
++              {
++                      char essid[IW_ESSID_MAX_SIZE+1];
++
++                      if (iwr->u.essid.length > IW_ESSID_MAX_SIZE)
++                      {
++                              result = -E2BIG;
++                              break;
++                      }
++                      if (copy_from_user(essid, iwr->u.essid.pointer,
++                                              iwr->u.essid.length))
++                      {
++                              result = -EFAULT;
++                              break;
++                      }
++                      result = acx_ioctl_set_essid(dev, NULL,
++                                      &(iwr->u.essid), essid);
++              }
++              break;
++
++      case SIOCGIWESSID:
++              /* get ESSID */
++              {
++                      char essid[IW_ESSID_MAX_SIZE+1];
++                      if (iwr->u.essid.pointer)
++                              result = acx_ioctl_get_essid(dev, NULL,
++                                      &(iwr->u.essid), essid);
++                      if (copy_to_user(iwr->u.essid.pointer, essid,
++                                              iwr->u.essid.length))
++                              result = -EFAULT;
++              }
++              break;
++
++      case SIOCSIWNICKN:
++              /* set nick */
++              {
++                      char nick[IW_ESSID_MAX_SIZE+1];
++
++                      if (iwr->u.data.length > IW_ESSID_MAX_SIZE)
++                      {
++                              result = -E2BIG;
++                              break;
++                      }
++                      if (copy_from_user(nick, iwr->u.data.pointer,
++                                              iwr->u.data.length))
++                      {
++                              result = -EFAULT;
++                              break;
++                      }
++                      result = acx_ioctl_set_nick(dev, NULL,
++                                      &(iwr->u.data), nick);
++              }
++              break;
++
++      case SIOCGIWNICKN:
++              /* get nick */
++              {
++                      char nick[IW_ESSID_MAX_SIZE+1];
++                      if (iwr->u.data.pointer)
++                              result = acx_ioctl_get_nick(dev, NULL,
++                                              &(iwr->u.data), nick);
++                      if (copy_to_user(iwr->u.data.pointer, nick,
++                                              iwr->u.data.length))
++                              result = -EFAULT;
++              }
++              break;
++
++      case SIOCSIWRATE:
++              /* set default bit rate (bps) */
++              result = acx_ioctl_set_rate(dev, NULL, &(iwr->u.bitrate),
++                                             NULL);
++              break;
++
++      case SIOCGIWRATE:
++              /* get default bit rate (bps) */
++              result = acx_ioctl_get_rate(dev, NULL, &(iwr->u.bitrate),
++                                             NULL);
++              break;
++
++      case  SIOCSIWRTS:
++              /* set RTS threshold value */
++              result = acx_ioctl_set_rts(dev, NULL, &(iwr->u.rts), NULL);
++              break;
++      case  SIOCGIWRTS:
++              /* get RTS threshold value */
++              result = acx_ioctl_get_rts(dev, NULL,  &(iwr->u.rts), NULL);
++              break;
++
++      /* FIXME: */
++      /* case  SIOCSIWFRAG: */
++      /* case  SIOCGIWFRAG: */
++
++#if WIRELESS_EXT > 9
++      case SIOCGIWTXPOW:
++              /* get tx power */
++              result = acx_ioctl_get_txpow(dev, NULL, &(iwr->u.txpower),
++                                              NULL);
++              break;
++
++      case SIOCSIWTXPOW:
++              /* set tx power */
++              result = acx_ioctl_set_txpow(dev, NULL, &(iwr->u.txpower),
++                                              NULL);
++              break;
++#endif
++
++      case SIOCSIWRETRY:
++              result = acx_ioctl_set_retry(dev, NULL, &(iwr->u.retry), NULL);
++              break;
++
++      case SIOCGIWRETRY:
++              result = acx_ioctl_get_retry(dev, NULL, &(iwr->u.retry), NULL);
++              break;
++
++      case SIOCSIWENCODE:
++              {
++                      /* set encoding token & mode */
++                      u8 key[29];
++                      if (iwr->u.encoding.pointer) {
++                              if (iwr->u.encoding.length > 29) {
++                                      result = -E2BIG;
++                                      break;
++                              }
++                              if (copy_from_user(key, iwr->u.encoding.pointer,
++                                              iwr->u.encoding.length)) {
++                                      result = -EFAULT;
++                                      break;
++                              }
++                      }
++                      else
++                      if (iwr->u.encoding.length) {
++                              result = -EINVAL;
++                              break;
++                      }
++                      result = acx_ioctl_set_encode(dev, NULL,
++                                      &(iwr->u.encoding), key);
++              }
++              break;
++
++      case SIOCGIWENCODE:
++              {
++                      /* get encoding token & mode */
++                      u8 key[29];
++
++                      result = acx_ioctl_get_encode(dev, NULL,
++                                      &(iwr->u.encoding), key);
++                      if (iwr->u.encoding.pointer) {
++                              if (copy_to_user(iwr->u.encoding.pointer,
++                                              key, iwr->u.encoding.length))
++                                      result = -EFAULT;
++                      }
++              }
++              break;
++
++      /******************** iwpriv ioctls below ********************/
++#if ACX_DEBUG
++      case ACX100_IOCTL_DEBUG:
++              acx_ioctl_set_debug(dev, NULL, NULL, iwr->u.name);
++              break;
++#endif
++
++      case ACX100_IOCTL_SET_PLED:
++              acx100_ioctl_set_led_power(dev, NULL, NULL, iwr->u.name);
++              break;
++
++      case ACX100_IOCTL_GET_PLED:
++              acx100_ioctl_get_led_power(dev, NULL, NULL, iwr->u.name);
++              break;
++
++      case ACX100_IOCTL_LIST_DOM:
++              acx_ioctl_list_reg_domain(dev, NULL, NULL, NULL);
++              break;
++
++      case ACX100_IOCTL_SET_DOM:
++              acx_ioctl_set_reg_domain(dev, NULL, NULL, iwr->u.name);
++              break;
++
++      case ACX100_IOCTL_GET_DOM:
++              acx_ioctl_get_reg_domain(dev, NULL, NULL, iwr->u.name);
++              break;
++
++      case ACX100_IOCTL_SET_SCAN_PARAMS:
++              acx_ioctl_set_scan_params(dev, NULL, NULL, iwr->u.name);
++              break;
++
++      case ACX100_IOCTL_GET_SCAN_PARAMS:
++              acx_ioctl_get_scan_params(dev, NULL, NULL, iwr->u.name);
++              break;
++
++      case ACX100_IOCTL_SET_PREAMB:
++              acx_ioctl_set_short_preamble(dev, NULL, NULL, iwr->u.name);
++              break;
++
++      case ACX100_IOCTL_GET_PREAMB:
++              acx_ioctl_get_short_preamble(dev, NULL, NULL, iwr->u.name);
++              break;
++
++      case ACX100_IOCTL_SET_ANT:
++              acx_ioctl_set_antenna(dev, NULL, NULL, iwr->u.name);
++              break;
++
++      case ACX100_IOCTL_GET_ANT:
++              acx_ioctl_get_antenna(dev, NULL, NULL, NULL);
++              break;
++
++      case ACX100_IOCTL_RX_ANT:
++              acx_ioctl_set_rx_antenna(dev, NULL, NULL, iwr->u.name);
++              break;
++
++      case ACX100_IOCTL_TX_ANT:
++              acx_ioctl_set_tx_antenna(dev, NULL, NULL, iwr->u.name);
++              break;
++
++      case ACX100_IOCTL_SET_ED:
++              acx_ioctl_set_ed_threshold(dev, NULL, NULL, iwr->u.name);
++              break;
++
++      case ACX100_IOCTL_SET_CCA:
++              acx_ioctl_set_cca(dev, NULL, NULL, iwr->u.name);
++              break;
++
++      case ACX100_IOCTL_MONITOR:      /* set sniff (monitor) mode */
++              acxlog(L_IOCTL, "%s: IWPRIV monitor\n", dev->name);
++
++              /* can only be done by admin */
++              if (!capable(CAP_NET_ADMIN)) {
++                      result = -EPERM;
++                      break;
++              }
++              result = acx_ioctl_wlansniff(dev, NULL, NULL, iwr->u.name);
++              break;
++
++      case ACX100_IOCTL_TEST:
++              acx_ioctl_unknown11(dev, NULL, NULL, NULL);
++              break;
++
++      case ACX111_IOCTL_INFO:
++              acx111_ioctl_info(dev, NULL, NULL, NULL);
++              break;
++
++      default:
++              acxlog(L_IOCTL, "wireless ioctl 0x%04X queried "
++                              "but not implemented yet\n", cmd);
++              result = -EOPNOTSUPP;
++              break;
++      }
++
++      if ((priv->dev_state_mask & ACX_STATE_IFACE_UP) && priv->set_mask) {
++              acx_sem_lock(priv);
++              acx_s_update_card_settings(priv, 0, 0);
++              acx_sem_unlock(priv);
++      }
++
++      /* older WEs don't have a commit handler,
++       * so we need to fix return code in this case */
++      if (-EINPROGRESS == result)
++              result = 0;
++
++      return result;
++}
++#endif /* WE < 13 */
+diff -Naur linux-2.6.14-omap2/drivers/net/wireless/tiacx/Kconfig linux-h6300-omap2-2.6.14.3/drivers/net/wireless/tiacx/Kconfig
+--- linux-2.6.14-omap2/drivers/net/wireless/tiacx/Kconfig      1970-01-01 02:00:00.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/drivers/net/wireless/tiacx/Kconfig      2005-09-28 23:54:23.000000000 +0300
+@@ -0,0 +1,59 @@
++config ACX
++      tristate "TI acx100/acx111 802.11b/g wireless chipsets"
++      depends on NET_RADIO && EXPERIMENTAL && 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 quite new and experimental.
++
++      These 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.
++
++      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 PCI && ACX
++      ---help---
++      Include PCI and CardBus support in acx.
++
++config ACX_USB
++      bool "TI acx100/acx111 802.11b/g USB"
++      depends on USB && ACX && BROKEN
++      ---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.
++
++config ACX_CFI
++      bool "TI acx100 802.11b/g Compact Flash"
++      depends on  ACX
++      ---help---
++      Include Compact Flash support.
+diff -Naur linux-2.6.14-omap2/drivers/net/wireless/tiacx/macros.h linux-h6300-omap2-2.6.14.3/drivers/net/wireless/tiacx/macros.h
+--- linux-2.6.14-omap2/drivers/net/wireless/tiacx/macros.h     1970-01-01 02:00:00.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/drivers/net/wireless/tiacx/macros.h     2005-09-28 23:54:23.000000000 +0300
+@@ -0,0 +1,33 @@
++#ifndef _MACROS_H
++#define _MACROS_H
++
++
++
++#define HW_SLAVE_REG_ADDR_REG 0x00000004
++#define HW_SLAVE_REG_DATA_REG 0x00000008
++#define HW_SLAVE_REG_CTRL_REG 0x0000000c
++#define HW_SLAVE_MEM_ADDR_REG 0x00000014
++#define HW_SLAVE_MEM_DATA_REG 0x00000018
++
++#define REG_LO(b,r)   ((u8 *) b + r)
++#define REG_HI(b,r)   ((u8 *) b + r + 2)
++
++static inline u32 acx_readl(unsigned char *iobase, unsigned int reg)
++{
++      u16 hi,lo;
++
++      writew( 0, REG_LO(iobase, HW_SLAVE_REG_CTRL_REG));
++      writew( 1, REG_HI(iobase,HW_SLAVE_REG_CTRL_REG));
++
++      writew( reg, REG_LO(iobase, HW_SLAVE_REG_ADDR_REG));
++      writew( 0, REG_HI(iobase,HW_SLAVE_REG_ADDR_REG));
++
++      lo = readw(REG_LO(iobase,HW_SLAVE_REG_DATA_REG));
++      hi = readw(REG_HI(iobase,HW_SLAVE_REG_DATA_REG));
++
++      printk("hi=%04x,lo=%04x\n",hi,lo);
++
++      return ((u32)hi<<16) | lo;
++}
++
++#endif
+diff -Naur linux-2.6.14-omap2/drivers/net/wireless/tiacx/Makefile linux-h6300-omap2-2.6.14.3/drivers/net/wireless/tiacx/Makefile
+--- linux-2.6.14-omap2/drivers/net/wireless/tiacx/Makefile     1970-01-01 02:00:00.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/drivers/net/wireless/tiacx/Makefile     2005-09-28 23:54:23.000000000 +0300
+@@ -0,0 +1,9 @@
++#Use this if you have proper Kconfig integration:
++
++obj-$(CONFIG_ACX) += acx.o
++
++acx-obj-$(CONFIG_ACX_PCI) += pci.o
++acx-obj-$(CONFIG_ACX_USB) += usb.o
++acx-obj-$(CONFIG_ACX_CFI) += cfi.o
++
++acx-objs := wlan.o conv.o ioctl.o common.o $(acx-obj-y)
+diff -Naur linux-2.6.14-omap2/drivers/net/wireless/tiacx/pci.c linux-h6300-omap2-2.6.14.3/drivers/net/wireless/tiacx/pci.c
+--- linux-2.6.14-omap2/drivers/net/wireless/tiacx/pci.c        1970-01-01 02:00:00.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/drivers/net/wireless/tiacx/pci.c        2005-09-28 23:54:23.000000000 +0300
+@@ -0,0 +1,4840 @@
++/***********************************************************************
++** 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/config.h>
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
++#include <linux/moduleparam.h>
++#endif
++#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>
++#if WIRELESS_EXT >= 13
++#include <net/iw_handler.h>
++#endif
++#include <linux/netdevice.h>
++#include <linux/ioport.h>
++#include <linux/pci.h>
++#include <linux/pm.h>
++
++#include "acx.h"
++
++
++/*================================================================*/
++/* Local Constants */
++#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      0x280
++
++#define CARD_EEPROM_ID_SIZE 6
++#define MAX_IRQLOOPS_PER_JIFFY  (20000/HZ) /* a la orinoco.c */
++
++
++/***********************************************************************
++*/
++static void acx_l_disable_irq(wlandevice_t *priv);
++static void acx_l_enable_irq(wlandevice_t *priv);
++static int acx_e_probe_pci(struct pci_dev *pdev,
++                          const struct pci_device_id *id);
++static void acx_e_remove_pci(struct pci_dev *pdev);
++
++#ifdef CONFIG_PM
++static int acx_e_suspend(struct pci_dev *pdev, pm_message_t state);
++static int acx_e_resume(struct pci_dev *pdev);
++#endif
++
++static void acx_i_tx_timeout(netdevice_t *dev);
++static struct net_device_stats *acx_e_get_stats(netdevice_t *dev);
++static struct iw_statistics *acx_e_get_wireless_stats(netdevice_t *dev);
++
++static irqreturn_t acx_i_interrupt(int irq, void *dev_id, struct pt_regs *regs);
++static void acx_i_set_multicast_list(netdevice_t *dev);
++
++static int acx_e_open(netdevice_t *dev);
++static int acx_e_close(netdevice_t *dev);
++static void acx_s_up(netdevice_t *dev);
++static void acx_s_down(netdevice_t *dev);
++
++
++/***********************************************************************
++** Register access
++*/
++
++/* Pick one */
++/* #define INLINE_IO static */
++#define INLINE_IO static inline
++
++INLINE_IO u32
++acx_read_reg32(wlandevice_t *priv, unsigned int offset)
++{
++#if ACX_IO_WIDTH == 32
++      return readl((u8 *)priv->iobase + priv->io[offset]);
++#else
++      return readw((u8 *)priv->iobase + priv->io[offset])
++          + (readw((u8 *)priv->iobase + priv->io[offset] + 2) << 16);
++#endif
++}
++
++INLINE_IO u16
++acx_read_reg16(wlandevice_t *priv, unsigned int offset)
++{
++      return readw((u8 *)priv->iobase + priv->io[offset]);
++}
++
++INLINE_IO u8
++acx_read_reg8(wlandevice_t *priv, unsigned int offset)
++{
++      return readb((u8 *)priv->iobase + priv->io[offset]);
++}
++
++INLINE_IO void
++acx_write_reg32(wlandevice_t *priv, unsigned int offset, u32 val)
++{
++#if ACX_IO_WIDTH == 32
++      writel(val, (u8 *)priv->iobase + priv->io[offset]);
++#else
++      writew(val & 0xffff, (u8 *)priv->iobase + priv->io[offset]);
++      writew(val >> 16, (u8 *)priv->iobase + priv->io[offset] + 2);
++#endif
++}
++
++INLINE_IO void
++acx_write_reg16(wlandevice_t *priv, unsigned int offset, u16 val)
++{
++      writew(val, (u8 *)priv->iobase + priv->io[offset]);
++}
++
++INLINE_IO void
++acx_write_reg8(wlandevice_t *priv, unsigned int offset, u8 val)
++{
++      writeb(val, (u8 *)priv->iobase + priv->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
++acx_write_flush(wlandevice_t *priv)
++{
++      /* readb(priv->iobase + priv->io[IO_ACX_INFO_MAILBOX_OFFS]); */
++      /* faster version (accesses the first register, IO_ACX_SOFT_RESET,
++       * which should also be safe): */
++      readb(priv->iobase);
++}
++
++
++/***********************************************************************
++*/
++static const char name_acx100[] = "ACX100";
++static const char name_tnetw1100a[] = "TNETW1100A";
++static const char name_tnetw1100b[] = "TNETW1100B";
++
++static const char name_acx111[] = "ACX111";
++static const char name_tnetw1130[] = "TNETW1130";
++
++static const struct pci_device_id
++acx_pci_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, acx_pci_id_tbl);
++
++/* FIXME: checks should be removed once driver is included in the kernel */
++#ifndef __devexit_p
++#warning *** your kernel is EXTREMELY old since it does not even know about
++#warning __devexit_p - this driver could easily FAIL to work, so better
++#warning upgrade your kernel! ***
++#define __devexit_p(x) x
++#endif
++
++#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 acx_pci_drv_id = {
++      .name        = "acx_pci",
++      .id_table    = acx_pci_id_tbl,
++      .probe       = acx_e_probe_pci,
++      .remove      = __devexit_p(acx_e_remove_pci),
++#ifdef CONFIG_PM
++      .suspend     = acx_e_suspend,
++      .resume      = acx_e_resume
++#endif /* CONFIG_PM */
++};
++
++typedef struct acx_device {
++      netdevice_t *newest;
++} acx_device_t;
++
++/* if this driver was only about PCI devices, then we probably wouldn't
++ * need this linked list.
++ * But if we want to register ALL kinds of devices in one global list,
++ * then we need it and need to maintain it properly. */
++static struct acx_device root_acx_dev = {
++      .newest         = NULL,
++};
++DECLARE_MUTEX(root_acx_dev_sem);
++
++
++/***********************************************************************
++*/
++static inline txdesc_t*
++get_txdesc(wlandevice_t* priv, int index)
++{
++      return (txdesc_t*) (((u8*)priv->txdesc_start) + index * priv->txdesc_size);
++}
++
++static inline txdesc_t*
++move_txdesc(wlandevice_t* priv, txdesc_t* txdesc, int inc)
++{
++      return (txdesc_t*) (((u8*)txdesc) + inc * priv->txdesc_size);
++}
++
++static txhostdesc_t*
++acx_get_txhostdesc(wlandevice_t* priv, txdesc_t* txdesc)
++{
++      int index = (u8*)txdesc - (u8*)priv->txdesc_start;
++      if (ACX_DEBUG && (index % priv->txdesc_size)) {
++              printk("bad txdesc ptr %p\n", txdesc);
++              return NULL;
++      }
++      index /= priv->txdesc_size;
++      if (ACX_DEBUG && (index >= TX_CNT)) {
++              printk("bad txdesc ptr %p\n", txdesc);
++              return NULL;
++      }
++      return &priv->txhostdesc_start[index*2];
++}
++
++static client_t*
++acx_get_txc(wlandevice_t* priv, txdesc_t* txdesc)
++{
++      int index = (u8*)txdesc - (u8*)priv->txdesc_start;
++      if (ACX_DEBUG && (index % priv->txdesc_size)) {
++              printk("bad txdesc ptr %p\n", txdesc);
++              return NULL;
++      }
++      index /= priv->txdesc_size;
++      if (ACX_DEBUG && (index >= TX_CNT)) {
++              printk("bad txdesc ptr %p\n", txdesc);
++              return NULL;
++      }
++      return priv->txc[index];
++}
++
++static void
++acx_put_txc(wlandevice_t* priv, txdesc_t* txdesc, client_t* c)
++{
++      int index = (u8*)txdesc - (u8*)priv->txdesc_start;
++      if (ACX_DEBUG && (index % priv->txdesc_size)) {
++              printk("bad txdesc ptr %p\n", txdesc);
++              return;
++      }
++      index /= priv->txdesc_size;
++      if (ACX_DEBUG && (index >= TX_CNT)) {
++              printk("bad txdesc ptr %p\n", txdesc);
++              return;
++      }
++      priv->txc[index] = c;
++}
++
++/***********************************************************************
++** EEPROM and PHY read/write helpers
++*/
++/***********************************************************************
++** acx_read_eeprom_offset
++**
++** Function called to read an octet in the EEPROM.
++**
++** This function is used by acx_probe_pci to check if the
++** connected card is a legal one or not.
++**
++** Arguments:
++**    priv            ptr to wlandevice structure
++**    addr            address to read in the EEPROM
++**    charbuf         ptr to a char. This is where the read octet
++**                    will be stored
++**
++** Returns:
++**    zero (0)        - failed
++**    one (1)         - success
++**
++** NOT ADAPTED FOR ACX111!!
++*/
++int
++acx_read_eeprom_offset(wlandevice_t *priv, u32 addr, u8 *charbuf)
++{
++      int result = NOT_OK;
++      int count;
++
++      acx_write_reg32(priv, IO_ACX_EEPROM_CFG, 0);
++      acx_write_reg32(priv, IO_ACX_EEPROM_ADDR, addr);
++      acx_write_flush(priv);
++      acx_write_reg32(priv, IO_ACX_EEPROM_CTL, 2);
++
++      count = 0xffff;
++      while (acx_read_reg16(priv, 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",
++                                                      priv->netdev->name);
++                      goto fail;
++              }
++      }
++
++      *charbuf = acx_read_reg8(priv, IO_ACX_EEPROM_DATA);
++      acxlog(L_DEBUG, "EEPROM at 0x%04X = 0x%02X\n", addr, *charbuf);
++      result = OK;
++
++fail:
++      return result;
++}
++
++
++/***********************************************************************
++** Dummy EEPROM read? why?!
++*/
++static int
++acx_read_eeprom_area(wlandevice_t *priv)
++{
++      int offs;
++      u8 tmp[0x3b];
++
++      for (offs = 0x8c; offs < 0xb9; offs++) {
++              acx_read_eeprom_offset(priv, offs, &tmp[offs - 0x8c]);
++      }
++      return OK;
++}
++
++
++/***********************************************************************
++** 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
++acx_s_write_eeprom_offset(wlandevice_t *priv, 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 = acx_read_reg16(priv, IO_ACX_GPIO_OE);
++      acx_write_reg16(priv, IO_ACX_GPIO_OE, gpio_orig & ~1);
++      acx_write_flush(priv);
++
++      /* ok, now start writing the data out */
++      for (i = 0; i < len; i++) {
++              acx_write_reg32(priv, IO_ACX_EEPROM_CFG, 0);
++              acx_write_reg32(priv, IO_ACX_EEPROM_ADDR, addr + i);
++              acx_write_reg32(priv, IO_ACX_EEPROM_DATA, *(charbuf + i));
++              acx_write_flush(priv);
++              acx_write_reg32(priv, IO_ACX_EEPROM_CTL, 1);
++
++              while (acx_read_reg16(priv, IO_ACX_EEPROM_CTL)) {
++                      if (unlikely(++count > 0xffff)) {
++                              printk("WARNING, DANGER!!! "
++                                      "Timeout waiting for EEPROM write\n");
++                              goto end;
++                      }
++              }
++      }
++
++      /* disable EEPROM writing */
++      acx_write_reg16(priv, IO_ACX_GPIO_OE, gpio_orig);
++      acx_write_flush(priv);
++
++      /* now start a verification run */
++      count = 0xffff;
++      for (i = 0; i < len; i++) {
++              acx_write_reg32(priv, IO_ACX_EEPROM_CFG, 0);
++              acx_write_reg32(priv, IO_ACX_EEPROM_ADDR, addr + i);
++              acx_write_flush(priv);
++              acx_write_reg32(priv, IO_ACX_EEPROM_CTL, 2);
++
++              while (acx_read_reg16(priv, IO_ACX_EEPROM_CTL)) {
++                      if (unlikely(!--count)) {
++                              printk("timeout waiting for EEPROM read\n");
++                              goto end;
++                      }
++              }
++
++              data_verify[i] = acx_read_reg16(priv, 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
++** (acx_write_reg32(priv, IO_ACX_ENABLE, 0b000000xx)) kills traffic
++*/
++int
++acxpci_s_read_phy_reg(wlandevice_t *priv, u32 reg, u8 *charbuf)
++{
++      int result = NOT_OK;
++      int count;
++
++      FN_ENTER;
++
++      acx_write_reg32(priv, IO_ACX_PHY_ADDR, reg);
++      acx_write_flush(priv);
++      acx_write_reg32(priv, IO_ACX_PHY_CTL, 2);
++
++      count = 0xffff;
++      while (acx_read_reg32(priv, 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",
++                                                      priv->netdev->name);
++                      *charbuf = 0;
++                      goto fail;
++              }
++      }
++
++      acxlog(L_DEBUG, "count was %u\n", count);
++      *charbuf = acx_read_reg8(priv, IO_ACX_PHY_DATA);
++
++      acxlog(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(wlandevice_t *priv, u32 reg, u8 value)
++{
++      FN_ENTER;
++
++      /* FIXME: we didn't use 32bit access here since mprusko said that
++       * it results in distorted sensitivity on his card (huh!?!?
++       * doesn't happen with my setup...)
++       * But with the access reordering and flushing it
++       * shouldn't happen any more...
++       * FIXME: which radio is in the problematic card? My working one
++       * is 0x11 */
++      acx_write_reg32(priv, IO_ACX_PHY_DATA, value);
++      acx_write_reg32(priv, IO_ACX_PHY_ADDR, reg);
++      acx_write_flush(priv);
++      acx_write_reg32(priv, IO_ACX_PHY_CTL, 1);
++      acx_write_flush(priv);
++      acxlog(L_DEBUG, "radio PHY write 0x%02X at 0x%04X\n", value, reg);
++
++      FN_EXIT1(OK);
++      return OK;
++}
++
++
++#define NO_AUTO_INCREMENT     1
++
++/***********************************************************************
++** acx_s_write_fw
++**
++** Write the firmware image into the card.
++**
++** Arguments:
++**    priv            wlan device structure
++**    apfw_image      firmware image.
++**
++** Returns:
++**    1       firmware image corrupted
++**    0       success
++*/
++static int
++acx_s_write_fw(wlandevice_t *priv, const firmware_image_t *apfw_image, u32 offset)
++{
++      int len, size;
++      u32 sum, v32;
++      /* we skip the first four bytes which contain the control sum */
++      const u8 *image = (u8*)apfw_image + 4;
++
++      /* start the image checksum by adding the image size value */
++      sum = image[0]+image[1]+image[2]+image[3];
++      image += 4;
++
++      acx_write_reg32(priv, IO_ACX_SLV_END_CTL, 0);
++
++#if NO_AUTO_INCREMENT
++      acxlog(L_INIT, "not using auto increment for firmware loading\n");
++      acx_write_reg32(priv, IO_ACX_SLV_MEM_CTL, 0); /* use basic mode */
++#else
++      acx_write_reg32(priv, IO_ACX_SLV_MEM_CTL, 1); /* use autoincrement mode */
++      acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR, offset); /* configure start address */
++      acx_write_flush(priv);
++#endif
++
++      len = 0;
++      size = le32_to_cpu(apfw_image->size) & (~3);
++
++      while (likely(len < size)) {
++              v32 = be32_to_cpu(*(u32*)image);
++              sum += image[0]+image[1]+image[2]+image[3];
++              image += 4;
++              len += 4;
++
++#if NO_AUTO_INCREMENT
++              acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR, offset + len - 4);
++              acx_write_flush(priv);
++#endif
++              acx_write_reg32(priv, IO_ACX_SLV_MEM_DATA, v32);
++      }
++
++      acxlog(L_DEBUG, "%s: firmware written\n", __func__);
++
++      /* compare our checksum with the stored image checksum */
++      return (sum != le32_to_cpu(apfw_image->chksum));
++}
++
++
++/***********************************************************************
++** acx_s_validate_fw
++**
++** Compare the firmware image given with
++** the firmware image written into the card.
++**
++** Arguments:
++**    priv            wlan device structure
++**   apfw_image  firmware image.
++**
++** Returns:
++**    NOT_OK  firmware image corrupted or not correctly written
++**    OK      success
++*/
++static int
++acx_s_validate_fw(wlandevice_t *priv, const firmware_image_t *apfw_image,
++                              u32 offset)
++{
++      u32 v32, w32, sum;
++      int len, size;
++      int result = OK;
++      /* we skip the first four bytes which contain the control sum */
++      const u8 *image = (u8*)apfw_image + 4;
++
++      /* start the image checksum by adding the image size value */
++      sum = image[0]+image[1]+image[2]+image[3];
++      image += 4;
++
++      acx_write_reg32(priv, IO_ACX_SLV_END_CTL, 0);
++
++#if NO_AUTO_INCREMENT
++      acx_write_reg32(priv, IO_ACX_SLV_MEM_CTL, 0); /* use basic mode */
++#else
++      acx_write_reg32(priv, IO_ACX_SLV_MEM_CTL, 1); /* use autoincrement mode */
++      acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR, offset); /* configure start address */
++#endif
++
++      len = 0;
++      size = le32_to_cpu(apfw_image->size) & (~3);
++
++      while (likely(len < size)) {
++              v32 = be32_to_cpu(*(u32*)image);
++              image += 4;
++              len += 4;
++
++#if NO_AUTO_INCREMENT
++              acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR, offset + len - 4);
++#endif
++              w32 = acx_read_reg32(priv, 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(apfw_image->chksum)) {
++                      printk("acx: FATAL: firmware upload: "
++                              "checksums don't match!\n");
++                      result = NOT_OK;
++              }
++      }
++
++      return result;
++}
++
++
++/***********************************************************************
++** acx_s_upload_fw
++**
++** Arguments:
++**    wlandevice: private device that contains card device
++** Returns:
++**    NOT_OK: failed
++**    OK: success
++** Call context:
++**    acx_reset_dev
++*/
++static int
++acx_s_upload_fw(wlandevice_t *priv)
++{
++      firmware_image_t *apfw_image = NULL;
++      int res = NOT_OK;
++      int try;
++      u32 size;
++      char filename[sizeof("tiacx1NNcNN")];
++
++      FN_ENTER;
++
++      /* Try combined, then main image */
++      priv->need_radio_fw = 0;
++      sprintf(filename, "tiacx1%02dc%02X",
++              IS_ACX111(priv)*11, priv->radio_type);
++
++      apfw_image = acx_s_read_fw(&priv->pdev->dev, filename, &size);
++      if (!apfw_image) {
++              priv->need_radio_fw = 1;
++              filename[sizeof("tiacx1NN")-1] = '\0';
++              apfw_image = acx_s_read_fw(&priv->pdev->dev, filename, &size);
++              if (!apfw_image) {
++                      FN_EXIT1(NOT_OK);
++                      return NOT_OK;
++              }
++      }
++
++      for (try = 1; try <= 5; try++) {
++              res = acx_s_write_fw(priv, apfw_image, 0);
++              acxlog(L_DEBUG|L_INIT, "acx_write_fw (main/combined):%d\n", res);
++              if (OK == res) {
++                      res = acx_s_validate_fw(priv, apfw_image, 0);
++                      acxlog(L_DEBUG|L_INIT, "acx_validate_fw "
++                                      "(main/combined):%d\n", res);
++              }
++
++              if (OK == res) {
++                      SET_BIT(priv->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(apfw_image);
++
++      FN_EXIT1(res);
++      return res;
++}
++
++
++/***********************************************************************
++** acx_s_upload_radio
++**
++** Uploads the appropriate radio module firmware
++** into the card.
++*/
++int
++acx_s_upload_radio(wlandevice_t *priv)
++{
++      acx_ie_memmap_t mm;
++      firmware_image_t *radio_image = NULL;
++      acx_cmd_radioinit_t radioinit;
++      int res = NOT_OK;
++      int try;
++      u32 offset;
++      u32 size;
++      char filename[sizeof("tiacx1NNrNN")];
++
++      if (!priv->need_radio_fw) return OK;
++
++      FN_ENTER;
++
++      acx_s_interrogate(priv, &mm, ACX1xx_IE_MEMORY_MAP);
++      offset = le32_to_cpu(mm.CodeEnd);
++
++      sprintf(filename, "tiacx1%02dr%02X",
++              IS_ACX111(priv)*11,
++              priv->radio_type);
++      radio_image = acx_s_read_fw(&priv->pdev->dev, filename, &size);
++      if (!radio_image) {
++              printk("acx: can't load radio module '%s'\n", filename);
++              goto fail;
++      }
++
++      acx_s_issue_cmd(priv, ACX1xx_CMD_SLEEP, NULL, 0);
++
++      for (try = 1; try <= 5; try++) {
++              res = acx_s_write_fw(priv, radio_image, offset);
++              acxlog(L_DEBUG|L_INIT, "acx_write_fw (radio): %d\n", res);
++              if (OK == res) {
++                      res = acx_s_validate_fw(priv, radio_image, offset);
++                      acxlog(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(priv, 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(priv, ACX1xx_CMD_RADIOINIT,
++              &radioinit, sizeof(radioinit), CMD_TIMEOUT_MS(1000));
++
++      res = acx_s_interrogate(priv, &mm, ACX1xx_IE_MEMORY_MAP);
++fail:
++      FN_EXIT1(res);
++      return res;
++}
++
++
++/***********************************************************************
++** acx_l_reset_mac
++**
++** Arguments:
++**    wlandevice: private device that contains card device
++** Side effects:
++**    MAC will be reset
++** Call context:
++**    acx_reset_dev
++** Comment:
++**    resets onboard acx100 MAC
++**
++** Requires lock to be taken
++*/
++static void
++acx_l_reset_mac(wlandevice_t *priv)
++{
++      u16 temp;
++
++      FN_ENTER;
++
++      /* halt eCPU */
++      temp = acx_read_reg16(priv, IO_ACX_ECPU_CTRL) | 0x1;
++      acx_write_reg16(priv, IO_ACX_ECPU_CTRL, temp);
++
++      /* now do soft reset of eCPU */
++      temp = acx_read_reg16(priv, IO_ACX_SOFT_RESET) | 0x1;
++      acxlog(L_DEBUG, "%s: enable soft reset...\n", __func__);
++      acx_write_reg16(priv, IO_ACX_SOFT_RESET, temp);
++      acx_write_flush(priv);
++
++      /* now reset bit again */
++      acxlog(L_DEBUG, "%s: disable soft reset and go to init mode...\n", __func__);
++      /* deassert eCPU reset */
++      acx_write_reg16(priv, IO_ACX_SOFT_RESET, temp & ~0x1);
++
++      /* now start a burst read from initial flash EEPROM */
++      temp = acx_read_reg16(priv, IO_ACX_EE_START) | 0x1;
++      acx_write_reg16(priv, IO_ACX_EE_START, temp);
++      acx_write_flush(priv);
++
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++** acx_s_verify_init
++*/
++static int
++acx_s_verify_init(wlandevice_t *priv)
++{
++      int result = NOT_OK;
++      int timer;
++
++      FN_ENTER;
++
++      for (timer = 40; timer > 0; timer--) {
++              u16 irqstat = acx_read_reg16(priv, IO_ACX_IRQ_STATUS_NON_DES);
++              if (irqstat & HOST_INT_FCS_THRESHOLD) {
++                      result = OK;
++                      acx_write_reg16(priv, IO_ACX_IRQ_ACK, HOST_INT_FCS_THRESHOLD);
++                      break;
++              }
++              /* HZ / 50 resulted in 24 schedules for ACX100 on my machine,
++               * so better schedule away longer for greater efficiency,
++               * decrease loop count */
++              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
++*/
++
++/***********************************************************************
++** acx_read_info_status
++*/
++/* Info mailbox format:
++2 bytes: type
++2 bytes: status
++more bytes may follow
++    docs 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 is no message 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
++acx_read_info_status(wlandevice_t *priv)
++{
++      u32 value;
++
++      acx_write_reg32(priv, IO_ACX_SLV_END_CTL, 0x0);
++      acx_write_reg32(priv, IO_ACX_SLV_MEM_CTL, 0x1);
++
++      acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR,
++              acx_read_reg32(priv, IO_ACX_INFO_MAILBOX_OFFS));
++
++      /* make sure we only read the data once all cfg registers are written: */
++      acx_write_flush(priv);
++      value = acx_read_reg32(priv, IO_ACX_SLV_MEM_DATA);
++
++      priv->info_type = (u16)value;
++      priv->info_status = (value >> 16);
++
++      /* inform hw that we have read this info message */
++      acx_write_reg32(priv, IO_ACX_SLV_MEM_DATA, priv->info_type | 0x00010000);
++      acx_write_flush(priv);
++      /* now bother hw to notice it: */
++      acx_write_reg16(priv, IO_ACX_INT_TRIG, INT_TRIG_INFOACK);
++      acx_write_flush(priv);
++
++      acxlog(L_CTL, "info_type 0x%04X, info_status 0x%04X\n",
++                      priv->info_type, priv->info_status);
++}
++
++
++/***********************************************************************
++** acx_write_cmd_type_or_status
++*/
++static void
++acx_write_cmd_type_or_status(wlandevice_t *priv, u32 val)
++{
++      acx_write_reg32(priv, IO_ACX_SLV_END_CTL, 0x0);
++      acx_write_reg32(priv, IO_ACX_SLV_MEM_CTL, 0x1); /* FIXME: why auto increment?? */
++
++      acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR,
++              acx_read_reg32(priv, IO_ACX_CMD_MAILBOX_OFFS));
++
++      /* make sure we only write the data once all config registers are written */
++      acx_write_flush(priv);
++      acx_write_reg32(priv, IO_ACX_SLV_MEM_DATA, val);
++      acx_write_flush(priv);
++}
++static inline void
++acx_write_cmd_type(wlandevice_t *priv, u32 val)
++{
++      acx_write_cmd_type_or_status(priv, val);
++}
++static inline void
++acx_write_cmd_status(wlandevice_t *priv, u32 val)
++{
++      acx_write_cmd_type_or_status(priv, val<<16);
++}
++
++
++/***********************************************************************
++** acx_read_cmd_status
++*/
++static void
++acx_read_cmd_status(wlandevice_t *priv)
++{
++      u32 value;
++
++      acx_write_reg32(priv, IO_ACX_SLV_END_CTL, 0x0);
++      acx_write_reg32(priv, IO_ACX_SLV_MEM_CTL, 0x1); /* FIXME: why auto increment?? */
++
++      acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR,
++              acx_read_reg32(priv, IO_ACX_CMD_MAILBOX_OFFS));
++
++      /* make sure we only read the data once all config registers are written */
++      acx_write_flush(priv);
++      value = acx_read_reg32(priv, IO_ACX_SLV_MEM_DATA);
++
++      priv->cmd_type = (u16)value;
++      priv->cmd_status = (value >> 16);
++
++      acxlog(L_CTL, "cmd_type 0x%04X, cmd_status 0x%04X [%s]\n",
++              priv->cmd_type, priv->cmd_status,
++              acx_cmd_status_str(priv->cmd_status));
++}
++
++
++/***********************************************************************
++** acx_s_reset_dev
++**
++** Arguments:
++**    netdevice that contains the wlandevice priv variable
++** Returns:
++**    NOT_OK on fail
++**    OK on success
++** Side effects:
++**    device is hard reset
++** Call context:
++**    acx_probe_pci
++** Comment:
++**    This resets the acx100 device using low level hardware calls
++**    as well as uploads and verifies the firmware to the card
++*/
++static int
++acx_s_reset_dev(netdevice_t *dev)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++      const char* msg = "";
++      unsigned long flags;
++      int result = NOT_OK;
++      u16 hardware_info;
++      u16 ecpu_ctrl;
++
++      FN_ENTER;
++
++      /* we're doing a reset, so hardware is unavailable */
++
++      /* reset the device to make sure the eCPU is stopped
++       * to upload the firmware correctly */
++
++      acx_lock(priv, flags);
++
++      acx_l_reset_mac(priv);
++
++      ecpu_ctrl = acx_read_reg16(priv, IO_ACX_ECPU_CTRL) & 1;
++      if (!ecpu_ctrl) {
++              msg = "eCPU is already running. ";
++              goto fail_unlock;
++      }
++
++#ifdef WE_DONT_NEED_THAT_DO_WE
++      if (acx_read_reg16(priv, IO_ACX_SOR_CFG) & 2) {
++              /* eCPU most likely means "embedded CPU" */
++              msg = "eCPU did not start after boot from flash. ";
++              goto fail_unlock;
++      }
++
++      /* check sense on reset flags */
++      if (acx_read_reg16(priv, IO_ACX_SOR_CFG) & 0x10) {
++              printk("%s: eCPU did not start after boot (SOR), "
++                      "is this fatal?\n", dev->name);
++      }
++#endif
++      /* scan, if any, is stopped now, setting corresponding IRQ bit */
++      priv->irq_status |= HOST_INT_SCAN_COMPLETE;
++
++      acx_unlock(priv, flags);
++
++      /* without this delay acx100 may fail to report hardware_info
++      ** (see below). Most probably eCPU runs some init code */
++      acx_s_msleep(10);
++
++      /* Need to know radio type before fw load */
++      hardware_info = acx_read_reg16(priv, IO_ACX_EEPROM_INFORMATION);
++      priv->form_factor = hardware_info & 0xff;
++      priv->radio_type = hardware_info >> 8;
++
++      /* load the firmware */
++      if (OK != acx_s_upload_fw(priv))
++              goto fail;
++
++      acx_s_msleep(10);
++
++      /* now start eCPU by clearing bit */
++      acxlog(L_DEBUG, "booted eCPU up and waiting for completion...\n");
++      acx_write_reg16(priv, IO_ACX_ECPU_CTRL, ecpu_ctrl & ~0x1);
++
++      /* wait for eCPU bootup */
++      if (OK != acx_s_verify_init(priv)) {
++              msg = "timeout waiting for eCPU. ";
++              goto fail;
++      }
++
++      acxlog(L_DEBUG, "eCPU has woken up, card is ready to be configured\n");
++
++      if (IS_ACX111(priv)) {
++              acxlog(L_DEBUG, "cleaning up cmd mailbox access area\n");
++              acx_write_cmd_status(priv, 0);
++              acx_read_cmd_status(priv);
++              if (priv->cmd_status) {
++                      msg = "error cleaning cmd mailbox area. ";
++                      goto fail;
++              }
++      }
++
++      /* TODO what is this one doing ?? adapt for acx111 */
++      if ((OK != acx_read_eeprom_area(priv)) && IS_ACX100(priv)) {
++              /* does "CIS" mean "Card Information Structure"?
++               * If so, then this would be a PCMCIA message...
++               */
++              msg = "CIS error. ";
++              goto fail;
++      }
++
++      result = OK;
++      FN_EXIT1(result);
++      return result;
++
++/* Finish error message. Indicate which function failed */
++fail_unlock:
++      acx_unlock(priv, flags);
++fail:
++      printk("acx: %sreset_dev() FAILED\n", msg);
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/***********************************************************************
++** acx_init_mboxes
++*/
++void
++acx_init_mboxes(wlandevice_t *priv)
++{
++      u32 cmd_offs, info_offs;
++
++      FN_ENTER;
++
++      cmd_offs = acx_read_reg32(priv, IO_ACX_CMD_MAILBOX_OFFS);
++      info_offs = acx_read_reg32(priv, IO_ACX_INFO_MAILBOX_OFFS);
++      priv->cmd_area = (u8 *)priv->iobase2 + cmd_offs + 0x4;
++      priv->info_area = (u8 *)priv->iobase2 + info_offs + 0x4;
++      acxlog(L_DEBUG, "iobase2=%p\n"
++              "cmd_mbox_offset=%X cmd_area=%p\n"
++              "info_mbox_offset=%X info_area=%p\n",
++              priv->iobase2,
++              cmd_offs, priv->cmd_area,
++              info_offs, priv->info_area);
++
++      FN_EXIT0;
++}
++
++
++/*----------------------------------------------------------------
++* acx_s_issue_cmd_timeo
++* Excecutes a command in the command mailbox
++*
++* Arguments:
++*   *pcmdparam = an pointer to the data. The data mustn't include
++*                the 4 byte command header!
++*
++* 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(
++      wlandevice_t *priv,
++      unsigned int cmd,
++      void *buffer,
++      unsigned buflen,
++      unsigned timeout)
++{
++#else
++int
++acxpci_s_issue_cmd_timeo_debug(
++      wlandevice_t *priv,
++      unsigned cmd,
++      void *buffer,
++      unsigned buflen,
++      unsigned timeout,
++      const char* cmdstr)
++{
++      unsigned long start = jiffies;
++#endif
++      const char *devname;
++      unsigned counter;
++      u16 irqtype;
++      u16 cmd_status;
++
++      FN_ENTER;
++
++      devname = priv->netdev->name;
++      if (!devname || !devname[0])
++              devname = "acx";
++
++      acxlog(L_CTL, FUNC"(cmd:%s,buflen:%u,timeout:%ums,type:0x%04X)\n",
++              cmdstr, buflen, timeout,
++              buffer ? le16_to_cpu(((acx_ie_generic_t *)buffer)->type) : -1);
++
++      if (!(priv->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 pdr (len=%u):\n", buflen);
++              acx_dump_bytes(buffer, buflen);
++      }
++
++      /* wait for firmware to become idle for our command submission */
++      counter = 199; /* in ms */
++      do {
++              acx_read_cmd_status(priv);
++              /* Test for IDLE state */
++              if (!priv->cmd_status)
++                      break;
++              if (counter % 10 == 0) {
++                      /* we waited 10 iterations, no luck. Sleep 10 ms */
++                      acx_s_msleep(10);
++              }
++      } while (--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, priv->cmd_status);
++              goto bad;
++      } else if (counter < 190) { /* if waited >10ms... */
++              acxlog(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(priv->cmd_area, 0xAA, buflen);
++#endif
++              memcpy(priv->cmd_area, buffer,
++                      (cmd == ACX1xx_CMD_INTERROGATE) ? 4 : buflen);
++      }
++      /* now write the actual command type */
++      priv->cmd_type = cmd;
++      acx_write_cmd_type(priv, cmd);
++      /* execute command */
++      acx_write_reg16(priv, IO_ACX_INT_TRIG, INT_TRIG_CMD);
++      acx_write_flush(priv);
++
++      /* 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 */
++      timeout = (timeout-1) | 1;
++      if (unlikely(timeout > 1199))
++              timeout = 1199;
++      /* clear CMD_COMPLETE bit. can be set only by IRQ handler: */
++      priv->irq_status &= ~HOST_INT_CMD_COMPLETE;
++
++      /* we schedule away sometimes (timeout can be large) */
++      counter = timeout;
++      do {
++              if (!priv->irqs_active) { /* IRQ disabled: poll */
++                      irqtype = acx_read_reg16(priv, IO_ACX_IRQ_STATUS_NON_DES);
++                      if (irqtype & HOST_INT_CMD_COMPLETE) {
++                              acx_write_reg16(priv, IO_ACX_IRQ_ACK,
++                                              HOST_INT_CMD_COMPLETE);
++                              break;
++                      }
++              } else { /* Wait when IRQ will set the bit */
++                      irqtype = priv->irq_status;
++                      if (irqtype & HOST_INT_CMD_COMPLETE)
++                              break;
++              }
++
++              if (counter % 10 == 0) {
++                      /* we waited 10 iterations, no luck. Sleep 10 ms */
++                      acx_s_msleep(10);
++              }
++      } while (--counter);
++
++      /* save state for debugging */
++      acx_read_cmd_status(priv);
++      cmd_status = priv->cmd_status;
++
++      /* put the card in IDLE state */
++      priv->cmd_status = 0;
++      acx_write_cmd_status(priv, 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, (priv->irqs_active) ? "waiting" : "polling",
++                      irqtype, priv->irq_status, timeout,
++                      cmd_status, acx_cmd_status_str(cmd_status));
++              goto bad;
++      } else if (timeout - counter > 30) { /* if waited >30ms... */
++              acxlog(L_CTL|L_DEBUG, FUNC"(): %s for CMD_COMPLETE %dms. "
++                      "count:%d. Please report\n",
++                      (priv->irqs_active) ? "waited" : "polled",
++                      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),
++                      timeout - counter, timeout);
++              /* zero out result buffer */
++              if (buffer && buflen)
++                      memset(buffer, 0, buflen);
++              goto bad;
++      }
++
++      /* read in result parameters if needed */
++      if (buffer && buflen && (cmd == ACX1xx_CMD_INTERROGATE)) {
++              memcpy(buffer, priv->cmd_area, buflen);
++              if (acx_debug & L_DEBUG) {
++                      printk("output buffer (len=%u): ", buflen);
++                      acx_dump_bytes(buffer, buflen);
++              }
++      }
++/* ok: */
++      acxlog(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;
++}
++
++
++/*----------------------------------------------------------------
++* acx_s_get_firmware_version
++*----------------------------------------------------------------*/
++static void
++acx_s_get_firmware_version(wlandevice_t *priv)
++{
++      fw_ver_t fw;
++      u8 hexarr[4] = { 0, 0, 0, 0 };
++      int hexidx = 0, val = 0;
++      const char *num;
++      char c;
++
++      FN_ENTER;
++
++      acx_s_interrogate(priv, &fw, ACX1xx_IE_FWREV);
++      memcpy(priv->firmware_version, fw.fw_id, FW_ID_SIZE);
++      priv->firmware_version[FW_ID_SIZE] = '\0';
++      acxlog(L_DEBUG, "fw_ver: fw_id='%s' hw_id=%08X\n",
++                              priv->firmware_version, fw.hw_id);
++
++      if (strncmp(fw.fw_id, "Rev ", 4) != 0) {
++              printk("acx: strange firmware version string "
++                      "'%s', please report\n", priv->firmware_version);
++              priv->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;
++              }
++
++              priv->firmware_numver = (u32)(
++                              (hexarr[0] << 24) + (hexarr[1] << 16)
++                              + (hexarr[2] << 8) + hexarr[3]);
++              acxlog(L_DEBUG, "firmware_numver 0x%08X\n", priv->firmware_numver);
++      }
++      if (IS_ACX111(priv)) {
++              if (priv->firmware_numver == 0x00010011) {
++                      /* This one does not survive floodpinging */
++                      printk("acx: firmware '%s' is known to be buggy, "
++                              "please upgrade\n", priv->firmware_version);
++              }
++              if (priv->firmware_numver == 0x02030131) {
++                      /* With this one, all rx packets look mangled
++                      ** Most probably we simply do not know how to use it
++                      ** properly */
++                      printk("acx: firmware '%s' does not work well "
++                              "with this driver\n", priv->firmware_version);
++              }
++      }
++
++      priv->firmware_id = le32_to_cpu(fw.hw_id);
++
++      /* we're able to find out more detailed chip names now */
++      switch (priv->firmware_id & 0xffff0000) {
++              case 0x01010000:
++              case 0x01020000:
++                      priv->chip_name = name_tnetw1100a;
++                      break;
++              case 0x01030000:
++                      priv->chip_name = name_tnetw1100b;
++                      break;
++              case 0x03000000:
++              case 0x03010000:
++                      priv->chip_name = name_tnetw1130;
++                      break;
++              default:
++                      printk("acx: unknown chip ID 0x%08X, "
++                              "please report\n", priv->firmware_id);
++                      break;
++      }
++
++      FN_EXIT0;
++}
++
++
++/*----------------------------------------------------------------
++* acx_display_hardware_details
++*
++* Arguments:
++*     priv: ptr to wlandevice that contains all the details
++*       displayed by this function
++* Call context:
++*     acx_probe_pci
++* Comment:
++*     This function will display strings to the system log according
++* to device form_factor and radio type. It will needed to be
++*----------------------------------------------------------------*/
++static void
++acx_display_hardware_details(wlandevice_t *priv)
++{
++      const char *radio_str, *form_str;
++
++      FN_ENTER;
++
++      switch (priv->radio_type) {
++      case RADIO_MAXIM_0D:
++              /* hmm, the DWL-650+ seems to have two variants,
++               * according to a windows driver changelog comment:
++               * RFMD and Maxim. */
++              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;
++      default:
++              radio_str = "UNKNOWN, please report the radio type name!";
++              break;
++      }
++
++      switch (priv->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: form factor 0x%02X (%s), "
++              "radio type 0x%02X (%s), EEPROM version 0x%02X, "
++              "uploaded firmware '%s' (0x%08X)\n",
++              priv->form_factor, form_str, priv->radio_type, radio_str,
++              priv->eeprom_version, priv->firmware_version,
++              priv->firmware_id);
++
++      FN_EXIT0;
++}
++
++/***********************************************************************
++*/
++#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(wlandevice_t *priv)
++{
++      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 != acx_read_eeprom_offset(priv,
++                                       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 */
++
++
++/***********************************************************************
++*/
++static void
++acx_s_device_chain_add(struct net_device *dev)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++
++      down(&root_acx_dev_sem);
++      priv->prev_nd = root_acx_dev.newest;
++      root_acx_dev.newest = dev;
++      priv->netdev = dev;
++      up(&root_acx_dev_sem);
++}
++
++static void
++acx_s_device_chain_remove(struct net_device *dev)
++{
++      struct net_device *querydev;
++      struct net_device *olderdev;
++      struct net_device *newerdev;
++
++      down(&root_acx_dev_sem);
++      querydev = root_acx_dev.newest;
++      newerdev = NULL;
++      while (querydev) {
++              olderdev = ((wlandevice_t*)netdev_priv(querydev))->prev_nd;
++              if (0 == strcmp(querydev->name, dev->name)) {
++                      if (!newerdev) {
++                              /* if we were at the beginning of the
++                               * list, then it's the list head that
++                               * we need to update to point at the
++                               * next older device */
++                              root_acx_dev.newest = olderdev;
++                      } else {
++                              /* it's the device that is newer than us
++                               * that we need to update to point at
++                               * the device older than us */
++                              ((wlandevice_t*)netdev_priv(newerdev))->
++                                      prev_nd = olderdev;
++                      }
++                      break;
++              }
++              /* "newerdev" is actually the device of the old iteration,
++               * but since the list starts (root_acx_dev.newest)
++               * with the newest devices,
++               * it's newer than the ones following.
++               * Oh the joys of iterating from newest to oldest :-\ */
++              newerdev = querydev;
++
++              /* keep checking old devices for matches until we hit the end
++               * of the list */
++              querydev = olderdev;
++      }
++      up(&root_acx_dev_sem);
++}
++
++
++/***********************************************************************
++** acx_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
++acx_free_coherent(struct pci_dev *hwdev, size_t size,
++                      void *vaddr, dma_addr_t dma_handle)
++{
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 53)
++      dma_free_coherent(hwdev == NULL ? NULL : &hwdev->dev,
++                      size, vaddr, dma_handle);
++#else
++      pci_free_consistent(hwdev, size, vaddr, dma_handle);
++#endif
++}
++
++void
++acx_free_desc_queues(wlandevice_t *priv)
++{
++#define ACX_FREE_QUEUE(size, ptr, phyaddr) \
++      if (ptr) { \
++              acx_free_coherent(0, size, ptr, phyaddr); \
++              ptr = NULL; \
++              size = 0; \
++      }
++
++      FN_ENTER;
++
++      ACX_FREE_QUEUE(priv->txhostdesc_area_size, priv->txhostdesc_start, priv->txhostdesc_startphy);
++      ACX_FREE_QUEUE(priv->txbuf_area_size, priv->txbuf_start, priv->txbuf_startphy);
++
++      priv->txdesc_start = NULL;
++
++      ACX_FREE_QUEUE(priv->rxhostdesc_area_size, priv->rxhostdesc_start, priv->rxhostdesc_startphy);
++      ACX_FREE_QUEUE(priv->rxbuf_area_size, priv->rxbuf_start, priv->rxbuf_startphy);
++
++      priv->rxdesc_start = NULL;
++
++      FN_EXIT0;
++}
++
++
++/*----------------------------------------------------------------
++* acx_s_delete_dma_regions
++*----------------------------------------------------------------*/
++static void
++acx_s_delete_dma_regions(wlandevice_t *priv)
++{
++      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? */
++      acx_write_reg16(priv, IO_ACX_ENABLE, 0);
++
++      acx_s_msleep(100);
++
++      acx_lock(priv, flags);
++      acx_free_desc_queues(priv);
++      acx_unlock(priv, flags);
++
++      FN_EXIT0;
++}
++
++
++/*----------------------------------------------------------------
++* acx_e_probe_pci
++*
++* 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
++*
++* Arguments:
++*     pdev            ptr to pci device structure containing info about
++*                     pci configuration.
++*     id              ptr to the device id entry that matched this device.
++*
++* Returns:
++*     zero            - success
++*     negative        - failed
++*
++* Call context:
++*     process thread
++----------------------------------------------------------------*/
++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 need 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
++acx_netdev_init(struct net_device *dev) {}
++
++//FIXME: do the same for USB
++static int
++acx_change_mtu(struct net_device *dev, int mtu)
++{
++      enum {
++              MIN_MTU = 256,
++              MAX_MTU = WLAN_DATA_MAXLEN - (ETH_HLEN)
++      };
++
++      if (mtu < MIN_MTU || mtu > MAX_MTU)
++              return -EINVAL;
++
++      dev->mtu = mtu;
++      return 0;
++}
++
++static int __devinit
++acx_e_probe_pci(struct pci_dev *pdev, const struct pci_device_id *id)
++{
++      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;
++      wlandevice_t *priv = NULL;
++      struct net_device *dev = NULL;
++      const char *chip_name;
++      int result = -EIO;
++      int err;
++      u8 chip_type;
++
++#if SEPARATE_DRIVER_INSTANCES
++      struct pci_dev *tdev;
++      unsigned int inited;
++      static int turn = 0;
++#endif /* SEPARATE_DRIVER_INSTANCES */
++
++      FN_ENTER;
++
++#if SEPARATE_DRIVER_INSTANCES
++      if (card) {
++              turn++;
++              inited = 0;
++              pci_for_each_dev(tdev) {
++                      if (tdev->vendor != PCI_VENDOR_ID_TI)
++                              continue;
++
++                      if (tdev == pdev)
++                              break;
++                      if (pci_get_drvdata(tdev))
++                              inited++;
++              }
++              if (inited + turn != card) {
++                      result = -ENODEV;
++                      goto done;
++              }
++      }
++#endif /* SEPARATE_DRIVER_INSTANCES */
++
++      /* 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);
++
++      /* 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 = 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 = 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), "ACX1xx_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), "ACX1xx_2")) {
++              printk("acx: cannot reserve PCI memory region 2\n");
++              goto fail_request_mem_region2;
++      }
++
++      mem1 = ioremap(phymem1, mem_region1_size);
++      if (NULL == mem1) {
++              printk("acx: ioremap() FAILED\n");
++              goto fail_ioremap1;
++      }
++
++      mem2 = ioremap(phymem2, mem_region2_size);
++      if (NULL == mem2) {
++              printk("acx: ioremap() #2 FAILED\n");
++              goto fail_ioremap2;
++      }
++
++      /* Log the device */
++      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);
++      acxlog(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;
++      }
++
++      dev = alloc_netdev(sizeof(wlandevice_t), "wlan%d", acx_netdev_init);
++      /* (NB: memsets to 0 entire area) */
++      if (!dev) {
++              printk("acx: no memory for netdevice structure\n");
++              goto fail_alloc_netdev;
++      }
++
++      ether_setup(dev);
++      dev->open = &acx_e_open;
++      dev->stop = &acx_e_close;
++      dev->hard_start_xmit = &acx_i_start_xmit;
++      dev->get_stats = &acx_e_get_stats;
++      dev->get_wireless_stats = &acx_e_get_wireless_stats;
++#if WIRELESS_EXT >= 13
++      dev->wireless_handlers = (struct iw_handler_def *)&acx_ioctl_handler_def;
++#else
++      dev->do_ioctl = &acx_e_ioctl_old;
++#endif
++      dev->set_multicast_list = &acx_i_set_multicast_list;
++      dev->tx_timeout = &acx_i_tx_timeout;
++      dev->change_mtu = &acx_change_mtu;
++      dev->watchdog_timeo = 4 * HZ;
++      dev->irq = pdev->irq;
++      dev->base_addr = pci_resource_start(pdev, 0);
++
++      priv = netdev_priv(dev);
++      spin_lock_init(&priv->lock);    /* initial state: unlocked */
++      /* We do not start with downed sem: we want PARANOID_LOCKING to work */
++      sema_init(&priv->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(priv); */
++      priv->pdev = pdev;
++      priv->dev_type = DEVTYPE_PCI;
++      priv->chip_type = chip_type;
++      priv->chip_name = chip_name;
++      priv->io = (CHIPTYPE_ACX100 == chip_type) ? IO_ACX100 : IO_ACX111;
++      priv->membase = phymem1;
++      priv->iobase = mem1;
++      priv->membase2 = phymem2;
++      priv->iobase2 = mem2;
++      /* to find crashes due to weird driver access
++       * to unconfigured interface (ifup) */
++      priv->mgmt_timer.function = (void (*)(unsigned long))0x0000dead;
++
++#ifdef NONESSENTIAL_FEATURES
++      acx_show_card_eeprom_id(priv);
++#endif /* NONESSENTIAL_FEATURES */
++
++      /* 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(dev, "after setup");
++
++#ifdef SET_MODULE_OWNER
++      SET_MODULE_OWNER(dev);
++#endif
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 70)
++      /* this define and its netdev member exist since 2.5.70 */
++      SET_NETDEV_DEV(dev, &pdev->dev);
++#endif
++
++      /* register new dev in linked list */
++      acx_s_device_chain_add(dev);
++
++      acxlog(L_IRQ|L_INIT, "using IRQ %d\n", pdev->irq);
++
++      /* need to be able to restore PCI state after a suspend */
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
++      /* 2.6.9-rc3-mm2 (2.6.9-bk4, too) introduced this shorter version,
++         then it made its way into 2.6.10 */
++      pci_save_state(pdev);
++#else
++      pci_save_state(pdev, priv->pci_state);
++#endif
++
++      /* NB: acx_read_reg() reads may return bogus data before reset_dev().
++      ** acx100 seems to be more affected than acx111 */
++      if (OK != acx_s_reset_dev(dev)) {
++              goto fail_reset;
++      }
++
++      /* ok, basic setup is finished, now start initialising the card */
++
++      if (OK != acx_read_eeprom_offset(priv, 0x05, &priv->eeprom_version)) {
++              goto fail_read_eeprom_version;
++      }
++
++      if (OK != acx_s_init_mac(dev)) {
++              printk("acx: init_mac() FAILED\n");
++              goto fail_init_mac;
++      }
++      if (OK != acx_s_set_defaults(priv)) {
++              printk("acx: set_defaults() FAILED\n");
++              goto fail_set_defaults;
++      }
++
++      /* needs to be after acx_s_init_mac() due to necessary init stuff */
++      acx_s_get_firmware_version(priv);
++
++      acx_display_hardware_details(priv);
++
++      pci_set_drvdata(pdev, dev);
++
++      /* ...and 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(dev);
++      if (OK != err) {
++              printk("acx: register_netdev() FAILED: %d\n", err);
++              goto fail_register_netdev;
++      }
++
++      acx_carrier_off(dev, "on probe");
++
++#ifdef CONFIG_PROC_FS
++      if (OK != acx_proc_register_entries(dev)) {
++              goto fail_proc_register_entries;
++      }
++#endif
++
++      /* after register_netdev() userspace may start working with dev
++       * (in particular, on other CPUs), we only need to up the sem */
++      /* acx_sem_unlock(priv); */
++
++      printk("acx "WLAN_RELEASE": net device %s, driver compiled "
++              "against wireless extensions %d and Linux %s\n",
++              dev->name, WIRELESS_EXT, UTS_RELEASE);
++
++#if CMD_DISCOVERY
++      great_inquisitor(priv);
++#endif
++
++      result = OK;
++      goto done;
++
++      /* error paths: undo everything in reverse order... */
++
++#ifdef CONFIG_PROC_FS
++fail_proc_register_entries:
++
++      if (priv->dev_state_mask & ACX_STATE_IFACE_UP)
++              acx_s_down(dev);
++
++      unregister_netdev(dev);
++
++      /* after unregister_netdev() userspace is guaranteed to finish
++       * working with it. netdev does not exist anymore.
++       * For paranoid reasons I am taking sem anyway */
++      acx_sem_lock(priv);
++#endif
++
++fail_register_netdev:
++
++      acx_s_delete_dma_regions(priv);
++      pci_set_drvdata(pdev, NULL);
++
++fail_set_defaults:
++fail_init_mac:
++fail_read_eeprom_version:
++fail_reset:
++
++      acx_s_device_chain_remove(dev);
++      free_netdev(dev);
++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, 3);
++
++done:
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/*----------------------------------------------------------------
++* acx_e_remove_pci
++*
++* Deallocate PCI resources for the ACX100 chip.
++*
++* This should NOT execute any other hardware operations on the card,
++* since the card might already be ejected. Instead, that should be done
++* in cleanup_module, since the card is most likely still available there.
++*
++* Arguments:
++*     pdev            ptr to PCI device structure containing info about
++*                     PCI configuration.
++*
++* Call context:
++*     process thread
++----------------------------------------------------------------*/
++static void __devexit
++acx_e_remove_pci(struct pci_dev *pdev)
++{
++      struct net_device *dev;
++      wlandevice_t *priv;
++      unsigned long mem_region1, mem_region2;
++
++      FN_ENTER;
++
++      dev = (struct net_device *) pci_get_drvdata(pdev);
++      if (!dev) {
++              acxlog(L_DEBUG, "%s: card is unused. Skipping any release code\n",
++                      __func__);
++              goto end;
++      }
++
++      priv = netdev_priv(dev);
++
++      /* unregister the device to not let the kernel
++       * (e.g. ioctls) access a half-deconfigured device
++       * NB: this will cause acx_e_close() to be called,
++       * thus we shouldn't call it under sem! */
++      acxlog(L_INIT, "removing device %s\n", dev->name);
++      unregister_netdev(dev);
++
++      /* unregister_netdev ensures that no references to us left.
++       * For paranoid reasons we continue to follow the rules */
++      acx_sem_lock(priv);
++
++      if (IS_ACX100(priv)) {
++              mem_region1 = PCI_ACX100_REGION1;
++              mem_region2 = PCI_ACX100_REGION2;
++      } else {
++              mem_region1 = PCI_ACX111_REGION1;
++              mem_region2 = PCI_ACX111_REGION2;
++      }
++
++#ifdef CONFIG_PROC_FS
++      acx_proc_unregister_entries(dev);
++#endif
++
++      /* find our PCI device in the global acx list and remove it */
++      acx_s_device_chain_remove(dev);
++
++      if (priv->dev_state_mask & ACX_STATE_IFACE_UP)
++              acx_s_down(dev);
++
++      CLEAR_BIT(priv->dev_state_mask, ACX_STATE_IFACE_UP);
++
++      acx_s_delete_dma_regions(priv);
++
++      /* finally, clean up PCI bus state */
++      if (priv->iobase) iounmap(priv->iobase);
++      if (priv->iobase2) iounmap(priv->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);
++
++      /* Free netdev (quite late,
++       * since otherwise we might get caught off-guard
++       * by a netdev timeout handler execution
++       * expecting to see a working dev...)
++       * But don't use free_netdev() here,
++       * it's supported by newer kernels only */
++      free_netdev(dev);
++
++      /* put device into ACPI D3 mode (shutdown) */
++      pci_set_power_state(pdev, 3);
++
++end:
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++*/
++#ifdef CONFIG_PM
++static int if_was_up = 0; /* FIXME: HACK, do it correctly sometime instead */
++static int
++acx_e_suspend(struct pci_dev *pdev, pm_message_t state)
++{
++      struct net_device *dev = pci_get_drvdata(pdev);
++      wlandevice_t *priv = netdev_priv(dev);
++
++      FN_ENTER;
++
++      acx_sem_lock(priv);
++
++      printk("acx: experimental suspend handler called for %p\n", priv);
++      if (netif_device_present(dev)) {
++              if_was_up = 1;
++              acx_s_down(dev);
++      }
++      else
++              if_was_up = 0;
++
++      netif_device_detach(dev);       /* This one cannot sleep */
++      acx_s_delete_dma_regions(priv);
++
++      acx_sem_unlock(priv);
++
++      FN_EXIT0;
++      return OK;
++}
++
++static int
++acx_e_resume(struct pci_dev *pdev)
++{
++      struct net_device *dev;
++      wlandevice_t *priv;
++
++      printk(KERN_WARNING "rsm: resume\n");
++      dev = pci_get_drvdata(pdev);
++      printk(KERN_WARNING "rsm: got dev\n");
++
++      if (!netif_running(dev))
++              return 0;
++
++      priv = netdev_priv(dev);
++
++      acx_sem_lock(priv);
++
++      printk(KERN_WARNING "rsm: got priv\n");
++      FN_ENTER;
++      printk("acx: experimental resume handler called for %p!\n", priv);
++      pci_set_power_state(pdev, 0);
++      acxlog(L_DEBUG, "rsm: power state set\n");
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
++      /* 2.6.9-rc3-mm2 (2.6.9-bk4, too) introduced this shorter version,
++         then it made its way into 2.6.10 */
++      pci_restore_state(pdev);
++#else
++      pci_restore_state(pdev, priv->pci_state);
++#endif
++      acxlog(L_DEBUG, "rsm: PCI state restored\n");
++      acx_s_reset_dev(dev);
++      acxlog(L_DEBUG, "rsm: device reset done\n");
++
++      if (OK != acx_s_init_mac(dev)) {
++              printk("rsm: init_mac FAILED\n");
++              goto fail;
++      }
++      acxlog(L_DEBUG, "rsm: init MAC done\n");
++
++      if (1 == if_was_up)
++              acx_s_up(dev);
++      acxlog(L_DEBUG, "rsm: acx up\n");
++
++      /* now even reload all card parameters as they were before suspend,
++       * and possibly be back in the network again already :-)
++       * FIXME: should this be done in that scheduled task instead?? */
++      if (ACX_STATE_IFACE_UP & priv->dev_state_mask)
++              acx_s_update_card_settings(priv, 0, 1);
++      acxlog(L_DEBUG, "rsm: settings updated\n");
++      netif_device_attach(dev);
++      acxlog(L_DEBUG, "rsm: device attached\n");
++fail: /* we need to return OK here anyway, right? */
++      acx_sem_unlock(priv);
++      FN_EXIT0;
++      return OK;
++}
++#endif /* CONFIG_PM */
++
++
++/*----------------------------------------------------------------
++* acx_s_up
++*
++* Side effects:
++*     - Enables on-card interrupt requests
++*     - calls acx_start
++* Call context:
++*     - process thread
++* Comment:
++*     This function is called by acx_open (when ifconfig sets the
++*     device as up).
++*----------------------------------------------------------------*/
++static void
++acx_s_up(netdevice_t *dev)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++      unsigned long flags;
++
++      FN_ENTER;
++
++      acx_lock(priv, flags);
++      acx_l_enable_irq(priv);
++      acx_unlock(priv, 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(&priv->mgmt_timer);
++      priv->mgmt_timer.function = acx_i_timer;
++      priv->mgmt_timer.data = (unsigned long)priv;
++
++      /* Need to set ACX_STATE_IFACE_UP first, or else
++      ** timer won't be started by acx_set_status() */
++      SET_BIT(priv->dev_state_mask, ACX_STATE_IFACE_UP);
++      switch (priv->mode) {
++      case ACX_MODE_0_ADHOC:
++      case ACX_MODE_2_STA:
++              /* actual scan cmd will happen in start() */
++              acx_set_status(priv, ACX_STATUS_1_SCANNING); break;
++      case ACX_MODE_3_AP:
++      case ACX_MODE_MONITOR:
++              acx_set_status(priv, ACX_STATUS_4_ASSOCIATED); break;
++      }
++
++      acx_s_start(priv);
++
++      FN_EXIT0;
++}
++
++
++/*----------------------------------------------------------------
++* acx_s_down
++*
++* Side effects:
++*     - disables on-card interrupt request
++* Call context:
++*     process thread
++* Comment:
++*     this disables the netdevice
++*----------------------------------------------------------------*/
++static void
++acx_s_down(netdevice_t *dev)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++      unsigned long flags;
++
++      FN_ENTER;
++
++      /* Disable IRQs first, so that IRQs cannot race with us */
++      acx_lock(priv, flags);
++      acx_l_disable_irq(priv);
++      acx_unlock(priv, 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(priv);
++      FLUSH_SCHEDULED_WORK();
++      acx_sem_lock(priv);
++
++      /* 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(priv, flags);
++      acx_stop_queue(dev, "during close");
++      acx_set_status(priv, ACX_STATUS_0_STOPPED);
++      acx_unlock(priv, 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(&priv->mgmt_timer);
++
++      FN_EXIT0;
++}
++
++
++/*----------------------------------------------------------------
++* acx_e_open
++*
++* WLAN device open method.  Called from p80211netdev when kernel
++* device open (start) method is called in response to the
++* SIOCSIFFLAGS ioctl changing the flags bit IFF_UP
++* from clear to set.
++*
++* Returns:
++*     0       success
++*     >0      f/w reported error
++*     <0      driver reported error
++*
++* Call context:
++*     process thread
++----------------------------------------------------------------*/
++static int
++acx_e_open(netdevice_t *dev)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++      int result = OK;
++
++      FN_ENTER;
++
++      acxlog(L_INIT, "module count++\n");
++      WLAN_MOD_INC_USE_COUNT;
++
++      acx_sem_lock(priv);
++
++      acx_init_task_scheduler(priv);
++
++      /* request shared IRQ handler */
++      if (request_irq(dev->irq, acx_i_interrupt, SA_SHIRQ, dev->name, dev)) {
++              printk("%s: request_irq FAILED\n", dev->name);
++              result = -EAGAIN;
++              goto done;
++      }
++      acxlog(L_DEBUG|L_IRQ, "request_irq %d successful\n", dev->irq);
++
++      /* ifup device */
++      acx_s_up(dev);
++
++      /* 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(priv);
++
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/*----------------------------------------------------------------
++* acx_e_close
++*
++* WLAN device close method.  Called from network core when kernel
++* device close method is called in response to the
++* SIOCSIIFFLAGS ioctl changing the flags bit IFF_UP
++* from set to clear.
++* (i.e. called for "ifconfig DEV down")
++*
++* Returns:
++*     0       success
++*     >0      f/w reported error
++*     <0      driver reported error
++*
++* Call context:
++*     process thread
++----------------------------------------------------------------*/
++static int
++acx_e_close(netdevice_t *dev)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++
++      FN_ENTER;
++
++      acx_sem_lock(priv);
++
++      /* ifdown device */
++      CLEAR_BIT(priv->dev_state_mask, ACX_STATE_IFACE_UP);
++      if (netif_device_present(dev)) {
++              acx_s_down(dev);
++      }
++
++      /* disable all IRQs, release shared IRQ handler */
++      acx_write_reg16(priv, IO_ACX_IRQ_MASK, 0xffff);
++      acx_write_reg16(priv, IO_ACX_FEMR, 0x0);
++      free_irq(dev->irq, dev);
++
++      /* 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.
++       */
++      acxlog(L_INIT, "module count--\n");
++      WLAN_MOD_DEC_USE_COUNT;
++
++      acx_sem_unlock(priv);
++
++      acxlog(L_INIT, "closed device\n");
++      FN_EXIT0;
++      return OK;
++}
++
++
++/*----------------------------------------------------------------
++* acx_i_tx_timeout
++*
++* Called from network core. Must not sleep!
++*----------------------------------------------------------------*/
++static void
++acx_i_tx_timeout(netdevice_t *dev)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++      unsigned long flags;
++      unsigned int tx_num_cleaned;
++
++      FN_ENTER;
++
++      acx_lock(priv, flags);
++
++      /* clean processed tx descs, they may have been completely full */
++      tx_num_cleaned = acx_l_clean_tx_desc(priv);
++
++      /* 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 ((priv->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", dev->name);
++              acx_l_clean_tx_desc_emergency(priv);
++      }
++
++      if (acx_queue_stopped(dev) && (ACX_STATUS_4_ASSOCIATED == priv->status))
++              acx_wake_queue(dev, "after tx timeout");
++
++      /* stall may have happened due to radio drift, so recalib radio */
++      acx_schedule_after_interrupt_task(priv, ACX_AFTER_IRQ_CMD_RADIO_RECALIB);
++
++      /* do unimportant work last */
++      printk("%s: tx timeout!\n", dev->name);
++      priv->stats.tx_errors++;
++
++      acx_unlock(priv, flags);
++
++      FN_EXIT0;
++}
++
++
++/*----------------------------------------------------------------
++* acx_e_get_stats
++*----------------------------------------------------------------*/
++static struct net_device_stats*
++acx_e_get_stats(netdevice_t *dev)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++      return &priv->stats;
++}
++
++
++/*----------------------------------------------------------------
++* acx_e_get_wireless_stats
++*----------------------------------------------------------------*/
++static struct iw_statistics*
++acx_e_get_wireless_stats(netdevice_t *dev)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++      return &priv->wstats;
++}
++
++
++/*----------------------------------------------------------------
++* acx_i_set_multicast_list
++* FIXME: most likely needs refinement
++*----------------------------------------------------------------*/
++static void
++acx_i_set_multicast_list(netdevice_t *dev)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++      unsigned long flags;
++
++      FN_ENTER;
++
++      acx_lock(priv, flags);
++
++      /* firmwares don't have allmulti capability,
++       * so just use promiscuous mode instead in this case. */
++      if (dev->flags & (IFF_PROMISC|IFF_ALLMULTI)) {
++              SET_BIT(priv->rx_config_1, RX_CFG1_RCV_PROMISCUOUS);
++              CLEAR_BIT(priv->rx_config_1, RX_CFG1_FILTER_ALL_MULTI);
++              SET_BIT(priv->set_mask, SET_RXCONFIG);
++              /* let kernel know in case *we* needed to set promiscuous */
++              dev->flags |= (IFF_PROMISC|IFF_ALLMULTI);
++      } else {
++              CLEAR_BIT(priv->rx_config_1, RX_CFG1_RCV_PROMISCUOUS);
++              SET_BIT(priv->rx_config_1, RX_CFG1_FILTER_ALL_MULTI);
++              SET_BIT(priv->set_mask, SET_RXCONFIG);
++              dev->flags &= ~(IFF_PROMISC|IFF_ALLMULTI);
++      }
++
++      /* cannot update card settings directly here, atomic context */
++      acx_schedule_after_interrupt_task(priv, ACX_AFTER_IRQ_UPDATE_CARD_CFG);
++
++      acx_unlock(priv, flags);
++
++      FN_EXIT0;
++}
++
++static void
++acx_l_update_link_quality_led(wlandevice_t *priv)
++{
++      int qual;
++
++      qual = acx_signal_determine_quality(priv->wstats.qual.level, priv->wstats.qual.noise);
++      if (qual > priv->brange_max_quality)
++              qual = priv->brange_max_quality;
++
++      if (time_after(jiffies, priv->brange_time_last_state_change +
++                              (HZ/2 - HZ/2 * (unsigned long) qual/priv->brange_max_quality ) )) {
++              acx_l_power_led(priv, (priv->brange_last_state == 0));
++              priv->brange_last_state ^= 1; /* toggle */
++              priv->brange_time_last_state_change = jiffies;
++      }
++}
++
++
++/*----------------------------------------------------------------
++* acx_l_enable_irq
++*----------------------------------------------------------------*/
++static void
++acx_l_enable_irq(wlandevice_t *priv)
++{
++      FN_ENTER;
++      acx_write_reg16(priv, IO_ACX_IRQ_MASK, priv->irq_mask);
++      acx_write_reg16(priv, IO_ACX_FEMR, 0x8000);
++      priv->irqs_active = 1;
++      FN_EXIT0;
++}
++
++
++/*----------------------------------------------------------------
++* acx_l_disable_irq
++*----------------------------------------------------------------*/
++static void
++acx_l_disable_irq(wlandevice_t *priv)
++{
++      FN_ENTER;
++      acx_write_reg16(priv, IO_ACX_IRQ_MASK, priv->irq_mask_off);
++      acx_write_reg16(priv, IO_ACX_FEMR, 0x0);
++      priv->irqs_active = 0;
++      FN_EXIT0;
++}
++
++/* 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
++
++static void
++acx_l_handle_info_irq(wlandevice_t *priv)
++{
++#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
++      acx_read_info_status(priv);
++      acxlog(L_IRQ, "got Info IRQ: status 0x%04X type 0x%04X: %s\n",
++              priv->info_status, priv->info_type,
++              info_type_msg[(priv->info_type >= VEC_SIZE(info_type_msg)) ?
++                              0 : priv->info_type]
++      );
++}
++
++
++/*----------------------------------------------------------------
++* acx_i_interrupt
++*
++* IRQ handler (atomic context, must not sleep, blah, blah)
++*----------------------------------------------------------------*/
++static void
++acx_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) {
++              acxlog(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");
++      }
++              /* 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 irqreturn_t
++acx_i_interrupt(int irq, void *dev_id, struct pt_regs *regs)
++{
++      wlandevice_t *priv;
++      unsigned long flags;
++      unsigned int irqcount = MAX_IRQLOOPS_PER_JIFFY;
++      u16 irqtype, unmasked;
++
++      priv = (wlandevice_t *) (((netdevice_t *) dev_id)->priv);
++
++      /* LOCKING: can just spin_lock() since IRQs are disabled anyway.
++       * I am paranoid */
++      acx_lock(priv, flags);
++
++      unmasked = acx_read_reg16(priv, IO_ACX_IRQ_STATUS_CLEAR);
++      if (unlikely(0xffff == unmasked)) {
++              /* 0xffff value hints at missing hardware,
++               * so don't do anything.
++               * FIXME: that's not very clean - maybe we are able to
++               * establish a flag which definitely tells us that some
++               * hardware is absent and which we could check here?
++               * Hmm, but other drivers do the very same thing... */
++              acxlog(L_IRQ, "IRQ type:FFFF - device removed? IRQ_NONE\n");
++              goto none;
++      }
++
++      /* We will check only "interesting" IRQ types */
++      irqtype = unmasked & ~priv->irq_mask;
++      if (!irqtype) {
++              /* We are on a shared IRQ line and it wasn't our IRQ */
++              acxlog(L_IRQ, "IRQ type:%04X, mask:%04X - all are masked, IRQ_NONE\n",
++                      unmasked, priv->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 != priv->irq_last_jiffies) {
++      priv->irq_loops_this_jiffy = 0;
++      priv->irq_last_jiffies = jiffies;
++}
++
++/* safety condition; we'll normally abort loop below
++ * in case no IRQ type occurred */
++while (--irqcount) {
++#endif
++      /* ACK all IRQs asap */
++      acx_write_reg16(priv, IO_ACX_IRQ_ACK, 0xffff);
++
++      acxlog(L_IRQ, "IRQ type:%04X, mask:%04X, type & ~mask:%04X\n",
++                              unmasked, priv->irq_mask, irqtype);
++
++      /* Handle most important IRQ types first */
++      if (irqtype & HOST_INT_RX_COMPLETE) {
++              acxlog(L_IRQ, "got Rx_Complete IRQ\n");
++              acx_l_process_rx_desc(priv);
++      }
++      if (irqtype & HOST_INT_TX_COMPLETE) {
++              acxlog(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
++               * acx_l_clean_tx_desc() at a time when we won't wakeup
++               * the net queue in there for some reason...) */
++              if (priv->tx_free <= TX_START_CLEAN) {
++#if TX_CLEANUP_IN_SOFTIRQ
++                      acx_schedule_after_interrupt_task(priv, ACX_AFTER_IRQ_TX_CLEANUP);
++#else
++                      acx_l_clean_tx_desc(priv);
++#endif
++              }
++      }
++
++      /* Less frequent ones */
++      if (irqtype & (0
++              | HOST_INT_CMD_COMPLETE
++              | HOST_INT_INFO
++              | HOST_INT_SCAN_COMPLETE
++      )) {
++              if (irqtype & HOST_INT_CMD_COMPLETE) {
++                      acxlog(L_IRQ, "got Command_Complete IRQ\n");
++                      /* save the state for the running issue_cmd() */
++                      SET_BIT(priv->irq_status, HOST_INT_CMD_COMPLETE);
++              }
++              if (irqtype & HOST_INT_INFO) {
++                      acx_l_handle_info_irq(priv);
++              }
++              if (irqtype & HOST_INT_SCAN_COMPLETE) {
++                      acxlog(L_IRQ, "got Scan_Complete IRQ\n");
++                      /* need to do that in process context */
++                      acx_schedule_after_interrupt_task(priv, ACX_AFTER_IRQ_COMPLETE_SCAN);
++                      /* remember that fw is not scanning anymore */
++                      SET_BIT(priv->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
++      )) {
++              acx_log_unusual_irq(irqtype);
++      }
++
++#if IRQ_ITERATE
++      unmasked = acx_read_reg16(priv, IO_ACX_IRQ_STATUS_CLEAR);
++      irqtype = unmasked & ~priv->irq_mask;
++      /* Bail out if no new IRQ bits or if all are masked out */
++      if (!irqtype)
++              break;
++
++      if (unlikely(++priv->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 */
++              acx_write_reg16(priv, IO_ACX_IRQ_MASK, 0xffff);
++              /* This will short-circuit all future attempts to handle IRQ.
++               * We cant do much more... */
++              priv->irq_mask = 0;
++              break;
++      }
++}
++#endif
++      /* Routine to perform blink with range */
++      if (unlikely(priv->led_power == 2))
++              acx_l_update_link_quality_led(priv);
++
++/* handled: */
++      /* acx_write_flush(priv); - not needed, last op was read anyway */
++      acx_unlock(priv, flags);
++      FN_EXIT0;
++      return IRQ_HANDLED;
++
++none:
++      acx_unlock(priv, flags);
++      return IRQ_NONE;
++}
++
++
++/*----------------------------------------------------------------
++* acx_l_power_led
++*----------------------------------------------------------------*/
++void
++acx_l_power_led(wlandevice_t *priv, int enable)
++{
++      u16 gpio_pled = IS_ACX111(priv) ? 0x0040 : 0x0800;
++
++      /* A hack. Not moving message rate limiting to priv->xxx
++       * (it's only a debug message after all) */
++      static int rate_limit = 0;
++
++      if (rate_limit++ < 3)
++              acxlog(L_IOCTL, "Please report in case toggling the power "
++                              "LED doesn't work for your card!\n");
++      if (enable)
++              acx_write_reg16(priv, IO_ACX_GPIO_OUT,
++                      acx_read_reg16(priv, IO_ACX_GPIO_OUT) & ~gpio_pled);
++      else
++              acx_write_reg16(priv, IO_ACX_GPIO_OUT,
++                      acx_read_reg16(priv, IO_ACX_GPIO_OUT) | gpio_pled);
++}
++
++
++/***********************************************************************
++** Ioctls
++*/
++
++/***********************************************************************
++*/
++int
++acx111pci_ioctl_info(
++      struct net_device *dev,
++      struct iw_request_info *info,
++      struct iw_param *vwrq,
++      char *extra)
++{
++#if ACX_DEBUG
++      wlandevice_t *priv = netdev_priv(dev);
++      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(priv);
++
++      if (!IS_ACX111(priv)) {
++              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(priv, &memconf, ACX1xx_IE_QUEUE_CONFIG);
++
++      /* get Acx111 Queue Configuration */
++      memset(&queueconf, 0, sizeof(queueconf));
++      acx_s_interrogate(priv, &queueconf, ACX1xx_IE_MEMORY_CONFIG_OPTIONS);
++
++      /* get Acx111 Memory Map */
++      memset(memmap, 0, sizeof(memmap));
++      acx_s_interrogate(priv, &memmap, ACX1xx_IE_MEMORY_MAP);
++
++      /* get Acx111 Rx Config */
++      memset(rxconfig, 0, sizeof(rxconfig));
++      acx_s_interrogate(priv, &rxconfig, ACX1xx_IE_RXCONFIG);
++
++      /* get Acx111 fcs error count */
++      memset(fcserror, 0, sizeof(fcserror));
++      acx_s_interrogate(priv, &fcserror, ACX1xx_IE_FCS_ERROR_COUNT);
++
++      /* get Acx111 rate fallback */
++      memset(ratefallback, 0, sizeof(ratefallback));
++      acx_s_interrogate(priv, &ratefallback, ACX1xx_IE_RATE_FALLBACK);
++
++      /* force occurrence of a beacon interrupt */
++      /* TODO: comment why is this necessary */
++      acx_write_reg16(priv, 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]),
++              priv->iobase,
++              priv->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(priv, flags);
++
++      /* dump acx111 internal rx descriptor ring buffer */
++      rxdesc = priv->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 = priv->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 = priv->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 = move_txdesc(priv, txdesc, 1);
++      }
++
++      /* dump host tx descriptor ring buffer */
++
++      txhostdesc = priv->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++;
++      }
++
++      /* acx_write_reg16(priv, 0xb4, 0x4); */
++
++      acx_unlock(priv, flags);
++end_ok:
++
++      acx_sem_unlock(priv);
++#endif /* ACX_DEBUG */
++      return OK;
++}
++
++
++/***********************************************************************
++*/
++int
++acx100pci_ioctl_set_phy_amp_bias(
++      struct net_device *dev,
++      struct iw_request_info *info,
++      struct iw_param *vwrq,
++      char *extra)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++      unsigned long flags;
++      u16 gpio_old;
++
++      if (!IS_ACX100(priv)) {
++              /* 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(priv);
++
++      /* Need to lock accesses to [IO_ACX_GPIO_OUT]:
++       * IRQ handler uses it to update LED */
++      acx_lock(priv, flags);
++      gpio_old = acx_read_reg16(priv, IO_ACX_GPIO_OUT);
++      acx_write_reg16(priv, IO_ACX_GPIO_OUT, (gpio_old & 0xf8ff) | ((u16)*extra << 8));
++      acx_unlock(priv, flags);
++
++      acxlog(L_DEBUG, "gpio_old: 0x%04X\n", gpio_old);
++      printk("%s: PHY power amplifier bias: old:%d, new:%d\n",
++              dev->name,
++              (gpio_old & 0x0700) >> 8, (unsigned char)*extra);
++
++      acx_sem_unlock(priv);
++
++      return OK;
++}
++
++
++/***************************************************************
++** acxpci_l_alloc_tx
++** Actually returns a txdesc_t* ptr
++*/
++tx_t*
++acxpci_l_alloc_tx(wlandevice_t* priv)
++{
++      struct txdesc *txdesc;
++      u8 ctl8;
++
++      FN_ENTER;
++
++      txdesc = get_txdesc(priv, priv->tx_head);
++      ctl8 = txdesc->Ctl_8;
++      if (unlikely(DESC_CTL_HOSTOWN != (ctl8 & DESC_CTL_DONE))) {
++              /* whoops, descr at current index is not free, so probably
++               * ring buffer already full */
++              /* FIXME: this causes a deadlock situation (endless
++               * loop) in case the current descriptor remains busy,
++               * so handle it a bit better in the future!! */
++              printk("acx: BUG: tx_head->Ctl8=0x%02X, (0x%02X & "
++                      "0x"DESC_CTL_DONE_STR") != 0x"DESC_CTL_HOSTOWN_STR
++                      ": failed to find free tx descr\n",
++                      ctl8, ctl8);
++              txdesc = NULL;
++              goto end;
++      }
++
++      priv->tx_free--;
++      acxlog(L_BUFT, "tx: got desc %u, %u remain\n",
++                      priv->tx_head, priv->tx_free);
++
++/*
++ * This comment is probably not entirely correct, needs further discussion
++ * (restored commented-out code below to fix Tx ring buffer overflow,
++ * since it's much better to have a slightly less efficiently used ring
++ * buffer rather than one which easily overflows):
++ *
++ * This doesn't do anything other than limit our maximum number of
++ * buffers used at a single time (we might as well just declare
++ * TX_STOP_QUEUE less descriptors when we open up.) We should just let it
++ * slide here, and back off TX_STOP_QUEUE in acx_l_clean_tx_desc, when given the
++ * opportunity to let the queue start back up.
++ */
++      if (priv->tx_free < TX_STOP_QUEUE) {
++              acxlog(L_BUF, "stop queue (%u tx desc left)\n",
++                              priv->tx_free);
++              acx_stop_queue(priv->netdev, NULL);
++      }
++
++      /* returning current descriptor, so advance to next free one */
++      priv->tx_head = (priv->tx_head + 1) % TX_CNT;
++end:
++      FN_EXIT0;
++
++      return (tx_t*)txdesc;
++}
++
++
++/***********************************************************************
++*/
++void*
++acxpci_l_get_txbuf(wlandevice_t *priv, tx_t* tx_opaque)
++{
++      return acx_get_txhostdesc(priv, (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).
++*/
++void
++acxpci_l_tx_data(wlandevice_t *priv, tx_t* tx_opaque, int len)
++{
++      txdesc_t *txdesc = (txdesc_t*)tx_opaque;
++      txhostdesc_t *hostdesc1, *hostdesc2;
++      client_t *clt;
++      u8 Ctl_8, Ctl2_8;
++
++      FN_ENTER;
++
++      /* fw doesn't tx such packets anyhow */
++      if (len < WLAN_HDR_A3_LEN)
++              goto end;
++
++      hostdesc1 = acx_get_txhostdesc(priv, txdesc);
++      hostdesc2 = hostdesc1 + 1;
++
++      /* 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 = txdesc->Ctl2_8;
++
++      /* 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...
++       * FIXME: what about Ctl2? Equally problematic? */
++
++      /* let chip do RTS/CTS handshaking before sending
++       * in case packet size exceeds threshold */
++      if (len > priv->rts_threshold)
++              SET_BIT(Ctl2_8, DESC_CTL2_RTS);
++      else
++              CLEAR_BIT(Ctl2_8, DESC_CTL2_RTS);
++
++#ifdef DEBUG_WEP
++      if (priv->wep_enabled)
++              SET_BIT(Ctl2_8, DESC_CTL2_WEP);
++      else
++              CLEAR_BIT(Ctl2_8, DESC_CTL2_WEP);
++#endif
++
++      switch (priv->mode) {
++      case ACX_MODE_0_ADHOC:
++      case ACX_MODE_3_AP:
++              clt = acx_l_sta_list_get(priv, ((wlan_hdr_t*)hostdesc1->data)->a1);
++              break;
++      case ACX_MODE_2_STA:
++              clt = priv->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;
++      }
++
++      if (unlikely(clt && !clt->rate_cur)) {
++              printk("acx: driver bug! bad ratemask\n");
++              goto end;
++      }
++
++      /* used in tx cleanup routine for auto rate and accounting: */
++      acx_put_txc(priv, txdesc, clt);
++
++      txdesc->total_length = cpu_to_le16(len);
++      hostdesc2->length = cpu_to_le16(len - WLAN_HDR_A3_LEN);
++      if (IS_ACX111(priv)) {
++              u16 rate_cur = clt ? clt->rate_cur : priv->rate_bcast;
++              /* 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 : priv->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);
++              hostdesc1->length = cpu_to_le16(WLAN_HDR_A3_LEN);
++      }
++      /* don't need to clean ack/rts statistics here, already
++       * done on descr cleanup */
++
++      /* clears Ctl DESC_CTL_HOSTOWN bit, thus telling that the descriptors
++       * are now owned by the acx100; do this as LAST operation */
++      CLEAR_BIT(Ctl_8, DESC_CTL_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); */
++//TODO: should it be a mmiowb() instead? we are protecting against race with write[bwl]()
++      /* flush writes before we tell the adapter that it's its turn now */
++      wmb(); 
++      acx_write_reg16(priv, IO_ACX_INT_TRIG, INT_TRIG_TXPRC);
++      acx_write_flush(priv);
++
++      /* 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(priv))
++                      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)" : "",
++                              priv->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)" : "",
++                              priv->status);
++
++              if (acx_debug & L_DATA) {
++                      printk("tx: 802.11 [%d]: ", len);
++                      acx_dump_bytes(hostdesc1->data, len);
++              }
++      }
++end:
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++*/
++static void
++acx_l_handle_tx_error(wlandevice_t *priv, 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";
++              priv->wstats.discard.fragment++;
++              break;
++      case 0x02:
++              err = "Tx aborted";
++              priv->stats.tx_aborted_errors++;
++              break;
++      case 0x04:
++              err = "Tx desc wrong parameters";
++              priv->wstats.discard.misc++;
++              break;
++      case 0x08:
++              err = "WEP key not found";
++              priv->wstats.discard.misc++;
++              break;
++      case 0x10:
++              err = "MSDU lifetime timeout? - try changing "
++                              "'iwconfig retry lifetime XXX'";
++              priv->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'";
++              priv->wstats.discard.retries++;
++              /* FIXME: set (GETSET_TX|GETSET_RX) here
++               * (this seems to recalib radio on ACX100)
++               * after some more jiffies passed??
++               * But OTOH Tx error 0x20 also seems to occur on
++               * overheating, so I'm not sure whether we
++               * actually want that, 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.
++               * ENABLE_TX|ENABLE_RX helps, so even do
++               * DISABLE_TX and DISABLE_RX in order to perhaps
++               * have more impact. */
++              if (++priv->retry_errors_msg_ratelimit % 4 == 0) {
++                      if (priv->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",
++                                      priv->netdev->name);
++                      if (priv->retry_errors_msg_ratelimit == 20)
++                              printk("disabling above "
++                                      "notification message\n");
++
++                      acx_schedule_after_interrupt_task(priv, ACX_AFTER_IRQ_CMD_RADIO_RECALIB);
++              }
++              break;
++      case 0x40:
++              err = "Tx buffer overflow";
++              priv->stats.tx_fifo_errors++;
++              break;
++      case 0x80:
++              err = "DMA error";
++              priv->wstats.discard.misc++;
++              break;
++      }
++      priv->stats.tx_errors++;
++      if (priv->stats.tx_errors <= 20)
++              printk("%s: tx error 0x%02X, buf %02u! (%s)\n",
++                              priv->netdev->name, error, finger, err);
++      else
++              printk("%s: tx error 0x%02X, buf %02u!\n",
++                              priv->netdev->name, error, finger);
++}
++
++
++/***********************************************************************
++*/
++/* 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_2;
++      }
++}
++
++
++static void
++acx_l_handle_txrate_auto(wlandevice_t *priv, struct client *txc,
++                      unsigned int idx, u8 rate100, u16 rate111, u8 error)
++{
++      u16 sent_rate;
++      u16 cur = txc->rate_cur;
++      int slower_rate_was_used;
++
++      /* FIXME: need to implement some kind of rate success memory
++       * which stores the success percentage per rate, to be taken
++       * into account when considering allowing a new rate, since it
++       * doesn't really help to stupidly count fallback/stepup,
++       * since one invalid rate will spoil the party anyway
++       * (such as 22M in case of 11M-only peers) */
++
++      /* 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 */
++
++      /* do some preparations, i.e. calculate the one rate that was
++       * used to send this packet */
++      if (IS_ACX111(priv)) {
++              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 */
++      acxlog(L_DEBUG, "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, priv->fallback_threshold,
++              txc->stepup_count, priv->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 here only, in order to have the 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 & 0x30)) {
++              txc->stepup_count = 0;
++              if (++txc->fallback_count <= priv->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! */
++                      acxlog(L_XFER, "tx: falling back to ratemask %04X\n", cur);
++                      txc->rate_cur = cur;
++                      txc->ignore_count = TX_CNT - priv->tx_free;
++              }
++      } else if (!slower_rate_was_used) {
++              txc->fallback_count = 0;
++              if (++txc->stepup_count <= priv->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);
++              acxlog(L_XFER, "tx: stepping up to ratemask %04X\n", cur);
++              txc->rate_cur = cur;
++              /* FIXME: totally bogus - we could be sending to many peers at once... */
++              txc->ignore_count = TX_CNT - priv->tx_free;
++      }
++
++      /* calculate acx100 style rate byte if needed */
++      if (IS_ACX100(priv)) {
++              txc->rate_100 = bitpos2rate100[highest_bit(cur)];
++      }
++}
++
++
++/*----------------------------------------------------------------
++* acx_l_log_txbuffer
++*----------------------------------------------------------------*/
++#if !ACX_DEBUG
++static inline void acx_l_log_txbuffer(const wlandevice_t *priv) {}
++#else
++static void
++acx_l_log_txbuffer(wlandevice_t *priv)
++{
++      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 = priv->txdesc_start;
++      if (!txdesc) return;
++      for (i = 0; i < TX_CNT; i++) {
++              if ((txdesc->Ctl_8 & DESC_CTL_DONE) == DESC_CTL_DONE)
++                      printk("tx: buf %d done\n", i);
++              txdesc = move_txdesc(priv, txdesc, 1);
++      }
++}
++#endif
++
++
++/*----------------------------------------------------------------
++* acx_l_clean_tx_desc
++*
++* 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.
++* Oops, now we have our own index, so everytime we get called we know
++* where the next packet to be cleaned is.
++* Hmm, still need to loop through the whole ring buffer now,
++* since we lost sync for some reason when ping flooding or so...
++* (somehow we don't get the IRQ for acx_l_clean_tx_desc any more when
++* too many packets are being sent!)
++* FIXME: currently we only process one packet, but this gets out of
++* sync for some reason when ping flooding, so we need to loop,
++* but the previous smart loop implementation causes the ping latency
++* to rise dramatically (~3000 ms), at least on CardBus PheeNet WL-0022.
++* Dunno what to do :-\
++*----------------------------------------------------------------*/
++unsigned int
++acx_l_clean_tx_desc(wlandevice_t *priv)
++{
++      txdesc_t *txdesc;
++      struct client *txc;
++      int finger;
++      int num_cleaned;
++      int to_process;
++      u16 r111;
++      u8 error, ack_failures, rts_failures, rts_ok, r100;
++
++      FN_ENTER;
++
++      if (unlikely(acx_debug & L_DEBUG))
++              acx_l_log_txbuffer(priv);
++
++      acxlog(L_BUFT, "tx: cleaning up bufs from %u\n", priv->tx_tail);
++
++      finger = priv->tx_tail;
++      num_cleaned = 0;
++      to_process = TX_CNT;
++      do {
++              txdesc = get_txdesc(priv, finger);
++
++              /* abort if txdesc is not marked as "Tx finished" and "owned" */
++              if ((txdesc->Ctl_8 & DESC_CTL_DONE) != DESC_CTL_DONE) {
++                      /* we do need to have at least one cleaned,
++                       * otherwise we wouldn't get called in the first place
++                       */
++                      if (num_cleaned)
++                              break;
++              }
++
++              /* remember descr 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 = txdesc->u.r2.rate111;
++
++#if WIRELESS_EXT > 13 /* wireless_send_event() and IWEVTXDROP are WE13 */
++              /* 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 = acx_get_txhostdesc(priv, txdesc);
++                      hdr = (wlan_hdr_t *)hostdesc->data;
++                      MAC_COPY(wrqu.addr.sa_data, hdr->a1);
++                      wireless_send_event(priv->netdev, IWEVTXDROP, &wrqu, NULL);
++              }
++#endif
++              /* ...and free the descr */
++              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:
++               * if _OWN is set at the beginning instead, our own get_tx
++               * might choose a Tx desc that isn't fully cleared
++               * (in case of bad locking). */
++              txdesc->Ctl_8 = DESC_CTL_HOSTOWN;
++              priv->tx_free++;
++              num_cleaned++;
++
++              if ((priv->tx_free >= TX_START_QUEUE)
++              && (priv->status == ACX_STATUS_4_ASSOCIATED)
++              && (acx_queue_stopped(priv->netdev))
++              ) {
++                      acxlog(L_BUF, "tx: wake queue (avail. Tx desc %u)\n",
++                                      priv->tx_free);
++                      acx_wake_queue(priv->netdev, NULL);
++              }
++
++              /* do error checking, rate handling and logging
++               * AFTER having done the work, it's faster */
++
++              /* do rate handling */
++              txc = acx_get_txc(priv, txdesc);
++              if (txc && priv->rate_auto) {
++                      acx_l_handle_txrate_auto(priv, txc, finger, r100, r111, error);
++              }
++
++              if (unlikely(error))
++                      acx_l_handle_tx_error(priv, error, finger);
++
++              if (IS_ACX111(priv))
++                      acxlog(L_BUFT, "tx: cleaned %u: !ACK=%u !RTS=%u RTS=%u r111=%04X\n",
++                              finger, ack_failures, rts_failures, rts_ok, r111);
++              else
++                      acxlog(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;
++      } while (--to_process);
++
++      /* remember last position */
++      priv->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
++acx_l_clean_tx_desc_emergency(wlandevice_t *priv)
++{
++      txdesc_t *txdesc;
++      unsigned int i;
++
++      FN_ENTER;
++
++      for (i = 0; i < TX_CNT; i++) {
++              txdesc = get_txdesc(priv, i);
++
++              /* free it */
++              txdesc->ack_failures = 0;
++              txdesc->rts_failures = 0;
++              txdesc->rts_ok = 0;
++              txdesc->error = 0;
++              txdesc->Ctl_8 = DESC_CTL_HOSTOWN;
++      }
++
++      priv->tx_free = TX_CNT;
++
++      FN_EXIT0;
++}
++
++
++/*----------------------------------------------------------------
++* acx_l_log_rxbuffer
++*
++* Called from IRQ context only
++*----------------------------------------------------------------*/
++#if !ACX_DEBUG
++static inline void acx_l_log_rxbuffer(const wlandevice_t *priv) {}
++#else
++static void
++acx_l_log_rxbuffer(const wlandevice_t *priv)
++{
++      const struct rxhostdesc *rxhostdesc;
++      int i;
++
++      /* no FN_ENTER here, we don't want that */
++
++      rxhostdesc = priv->rxhostdesc_start;
++      if (!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
++
++
++/***************************************************************
++** acx_l_process_rx_desc
++**
++** Called directly and only from the IRQ handler
++*/
++void
++acx_l_process_rx_desc(wlandevice_t *priv)
++{
++      rxhostdesc_t *hostdesc;
++      /* unsigned int curr_idx; */
++      unsigned int count = 0;
++
++      FN_ENTER;
++
++      if (unlikely(acx_debug & L_BUFR)) {
++              acx_l_log_rxbuffer(priv);
++      }
++
++      /* 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. */
++      while (1) {
++              /* curr_idx = priv->rx_tail; */
++              hostdesc = &priv->rxhostdesc_start[priv->rx_tail];
++              priv->rx_tail = (priv->rx_tail + 1) % RX_CNT;
++              if ((hostdesc->Ctl_16 & cpu_to_le16(DESC_CTL_HOSTOWN))
++               && (hostdesc->Status & cpu_to_le32(DESC_STATUS_FULL))) {
++                      /* found it! */
++                      break;
++              }
++              count++;
++              if (unlikely(count > RX_CNT)) {
++                      /* hmm, no luck: all descriptors empty, bail out */
++                      goto end;
++              }
++      }
++
++      /* now process descriptors, starting with the first we figured out */
++      while (1) {
++              acxlog(L_BUFR, "rx: tail=%u Ctl_16=%04X Status=%08X\n",
++                      priv->rx_tail, hostdesc->Ctl_16, hostdesc->Status);
++
++              acx_l_process_rxbuf(priv, 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 */
++              /* curr_idx = priv->rx_tail; */
++              hostdesc = &priv->rxhostdesc_start[priv->rx_tail];
++
++              /* if next descriptor is empty, then bail out */
++              /* FIXME: is this check really entirely correct?? */
++              /*
++//FIXME: inconsistent with check in prev while() loop
++              if (!(hostdesc->Ctl & cpu_to_le16(DESC_CTL_HOSTOWN))
++               && !(hostdesc->Status & cpu_to_le32(DESC_STATUS_FULL))) */
++              if (!(hostdesc->Status & cpu_to_le32(DESC_STATUS_FULL)))
++                      break;
++
++              priv->rx_tail = (priv->rx_tail + 1) % RX_CNT;
++      }
++end:
++      FN_EXIT0;
++}
++
++
++/*----------------------------------------------------------------
++* acx_s_create_tx_host_desc_queue
++*----------------------------------------------------------------*/
++static inline void*
++acx_alloc_coherent(struct pci_dev *hwdev, size_t size,
++                      dma_addr_t *dma_handle, int flag)
++{
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 53)
++      return dma_alloc_coherent(hwdev == NULL ? NULL : &hwdev->dev,
++                      size, dma_handle, flag);
++#else
++#warning Using old PCI-specific DMA allocation, may fail with out-of-mem!
++#warning Upgrade kernel if it does...
++      return pci_alloc_consistent(hwdev, size, dma_handle);
++#endif
++}
++
++static void*
++allocate(wlandevice_t *priv, size_t size, dma_addr_t *phy, const char *msg)
++{
++      void *ptr = acx_alloc_coherent(priv->pdev, size, phy, GFP_KERNEL);
++      if (ptr) {
++              acxlog(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
++acx_s_create_tx_host_desc_queue(wlandevice_t *priv)
++{
++      txhostdesc_t *hostdesc;
++      u8 *txbuf;
++      dma_addr_t hostdesc_phy;
++      dma_addr_t txbuf_phy;
++      int i;
++
++      FN_ENTER;
++
++      /* allocate TX buffer */
++      priv->txbuf_area_size = TX_CNT * WLAN_A4FR_MAXLEN_WEP_FCS;
++      priv->txbuf_start = allocate(priv, priv->txbuf_area_size,
++                      &priv->txbuf_startphy, "txbuf_start");
++      if (!priv->txbuf_start)
++              goto fail;
++
++      /* allocate the TX host descriptor queue pool */
++      priv->txhostdesc_area_size = TX_CNT * 2*sizeof(txhostdesc_t);
++      priv->txhostdesc_start = allocate(priv, priv->txhostdesc_area_size,
++                      &priv->txhostdesc_startphy, "txhostdesc_start");
++      if (!priv->txhostdesc_start)
++              goto fail;
++      /* check for proper alignment of TX host descriptor pool */
++      if ((long) priv->txhostdesc_start & 3) {
++              printk("acx: driver bug: dma alloc returns unaligned address\n");
++              goto fail;
++      }
++
++/* Each tx frame buffer is accessed by hardware via
++** txdesc -> txhostdesc(s) -> framebuffer(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 hostdesc.length = 3 (or larger)
++** Storing NULL into hostdesc.desc_phy_next
++** doesn't seem to help.
++*/
++/* It is not known whether we need to have 'extra' second
++** txhostdescs for acx100. Maybe it is acx111-only bug.
++*/
++      hostdesc = priv->txhostdesc_start;
++      hostdesc_phy = priv->txhostdesc_startphy;
++      txbuf = priv->txbuf_start;
++      txbuf_phy = priv->txbuf_startphy;
++
++#if 0
++/* Works for xterasys xn2522g, does not for WG311v2 !!? */
++      for (i = 0; i < TX_CNT*2; i++) {
++              hostdesc_phy += sizeof(txhostdesc_t);
++              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 = 3; /* bug workaround */
++                      /* hostdesc->desc_phy_next = ... */
++                      /* hostdesc->pNext = ... */
++                      /* hostdesc->Status = ... */
++                      /* below: non-hardware fields */
++                      /* hostdesc->data = ... */
++              }
++              hostdesc++;
++      }
++#endif
++      for (i = 0; i < TX_CNT*2; i++) {
++              hostdesc_phy += sizeof(txhostdesc_t);
++              if (!(i & 1)) {
++                      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 = ... */
++                      /* below: non-hardware fields */
++                      hostdesc->data = txbuf;
++
++                      txbuf += WLAN_HDR_A3_LEN;
++                      txbuf_phy += WLAN_HDR_A3_LEN;
++              } else {
++                      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 = ... */
++                      /* below: non-hardware fields */
++                      hostdesc->data = txbuf;
++
++                      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(priv->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;
++}
++
++
++/***************************************************************
++** acx_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
++acx_s_create_rx_host_desc_queue(wlandevice_t *priv)
++{
++      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 */
++      priv->rxhostdesc_area_size = RX_CNT * sizeof(rxhostdesc_t);
++      priv->rxhostdesc_start = allocate(priv, priv->rxhostdesc_area_size,
++                      &priv->rxhostdesc_startphy, "rxhostdesc_start");
++      if (!priv->rxhostdesc_start)
++              goto fail;
++      /* check for proper alignment of RX host descriptor pool */
++      if ((long) priv->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 */
++      priv->rxbuf_area_size = RX_CNT * RX_BUFFER_SIZE;
++      priv->rxbuf_start = allocate(priv, priv->rxbuf_area_size,
++                      &priv->rxbuf_startphy, "rxbuf_start");
++      if (!priv->rxbuf_start)
++              goto fail;
++
++      rxbuf = priv->rxbuf_start;
++      rxbuf_phy = priv->rxbuf_startphy;
++      hostdesc = priv->rxhostdesc_start;
++      hostdesc_phy = priv->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(rxbuffer_t);
++              hostdesc_phy += sizeof(rxhostdesc_t);
++              hostdesc->desc_phy_next = cpu2acx(hostdesc_phy);
++              hostdesc++;
++      }
++      hostdesc--;
++      hostdesc->desc_phy_next = cpu2acx(priv->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;
++}
++
++
++/***************************************************************
++** acx_s_create_hostdesc_queues
++*/
++int
++acx_s_create_hostdesc_queues(wlandevice_t *priv)
++{
++      int result;
++      result = acx_s_create_tx_host_desc_queue(priv);
++      if (OK != result) return result;
++      result = acx_s_create_rx_host_desc_queue(priv);
++      return result;
++}
++
++
++/***************************************************************
++** acx_create_tx_desc_queue
++*/
++static void
++acx_create_tx_desc_queue(wlandevice_t *priv, u32 tx_queue_start)
++{
++      txdesc_t *txdesc;
++      txhostdesc_t *hostdesc;
++      dma_addr_t hostmemptr;
++      u32 mem_offs;
++      int i;
++
++      FN_ENTER;
++
++      priv->txdesc_size = sizeof(txdesc_t);
++
++      if (IS_ACX111(priv)) {
++              /* the acx111 txdesc is 4 bytes larger */
++              priv->txdesc_size = sizeof(txdesc_t) + 4;
++      }
++
++      priv->txdesc_start = (txdesc_t *) (priv->iobase2 + tx_queue_start);
++
++      acxlog(L_DEBUG, "priv->iobase2=%p\n"
++                      "tx_queue_start=%08X\n"
++                      "priv->txdesc_start=%p\n",
++                      priv->iobase2,
++                      tx_queue_start,
++                      priv->txdesc_start);
++
++      priv->tx_free = TX_CNT;
++      /* done by memset: priv->tx_head = 0; */
++      /* done by memset: priv->tx_tail = 0; */
++      txdesc = priv->txdesc_start;
++      mem_offs = tx_queue_start;
++      hostmemptr = priv->txhostdesc_startphy;
++      hostdesc = priv->txhostdesc_start;
++
++      if (IS_ACX111(priv)) {
++              /* 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(txhostdesc_t);
++                      txdesc = move_txdesc(priv, txdesc, 1);
++              }
++      } else {
++              /* ACX100 Tx buffer needs to be initialized by us */
++              /* clear whole send pool. sizeof is safe here (we are acx100) */
++              memset(priv->txdesc_start, 0, TX_CNT * sizeof(txdesc_t));
++
++              /* loop over whole send pool */
++              for (i = 0; i < TX_CNT; i++) {
++                      acxlog(L_DEBUG, "configure card tx descriptor: 0x%p, "
++                              "size: 0x%X\n", txdesc, priv->txdesc_size);
++
++                      /* pointer to hostdesc memory */
++                      /* FIXME: type-incorrect assignment, might cause trouble
++                       * in some cases */
++                      txdesc->HostMemPtr = ptr2acx(hostmemptr);
++                      /* initialise ctl */
++                      txdesc->Ctl_8 = DESC_CTL_INIT;
++                      txdesc->Ctl2_8 = 0;
++                      /* point to next txdesc */
++                      txdesc->pNextDesc = cpu2acx(mem_offs + priv->txdesc_size);
++                      /* reserve two (hdr desc and payload desc) */
++                      hostdesc += 2;
++                      hostmemptr += 2 * sizeof(txhostdesc_t);
++                      /* go to the next one */
++                      mem_offs += priv->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;
++}
++
++
++/***************************************************************
++** acx_create_rx_desc_queue
++*/
++static void
++acx_create_rx_desc_queue(wlandevice_t *priv, u32 rx_queue_start)
++{
++      rxdesc_t *rxdesc;
++      u32 mem_offs;
++      int i;
++
++      FN_ENTER;
++
++      /* done by memset: priv->rx_tail = 0; */
++
++      /* ACX111 doesn't need any further config: preconfigures itself.
++       * Simply print ring buffer for debugging */
++      if (IS_ACX111(priv)) {
++              /* rxdesc_start already set here */
++
++              priv->rxdesc_start = (rxdesc_t *) ((u8 *)priv->iobase2 + rx_queue_start);
++
++              rxdesc = priv->rxdesc_start;
++              for (i = 0; i < RX_CNT; i++) {
++                      acxlog(L_DEBUG, "rx descriptor %d @ 0x%p\n", i, rxdesc);
++                      rxdesc = priv->rxdesc_start = (rxdesc_t *)
++                              (priv->iobase2 + acx2cpu(rxdesc->pNextDesc));
++              }
++      } else {
++              /* we didn't pre-calculate rxdesc_start in case of ACX100 */
++              /* rxdesc_start should be right AFTER Tx pool */
++              priv->rxdesc_start = (rxdesc_t *)
++                      ((u8 *) priv->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(priv->rxdesc_start, 0, RX_CNT * sizeof(rxdesc_t));
++
++              /* loop over whole receive pool */
++              rxdesc = priv->rxdesc_start;
++              mem_offs = rx_queue_start;
++              for (i = 0; i < RX_CNT; i++) {
++                      acxlog(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_t));
++                      /* go to the next one */
++                      mem_offs += sizeof(rxdesc_t);
++                      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;
++}
++
++
++/***************************************************************
++** acx_create_desc_queues
++*/
++void
++acx_create_desc_queues(wlandevice_t *priv, u32 tx_queue_start, u32 rx_queue_start)
++{
++      acx_create_tx_desc_queue(priv, tx_queue_start);
++      acx_create_rx_desc_queue(priv, rx_queue_start);
++}
++
++
++/***************************************************************
++** acxpci_s_proc_diag_output
++*/
++char*
++acxpci_s_proc_diag_output(char *p, wlandevice_t *priv)
++{
++      const char *rtl, *thd, *ttl;
++      rxhostdesc_t *rxhostdesc;
++      txdesc_t *txdesc;
++      int i;
++
++      FN_ENTER;
++
++      p += sprintf(p, "** Rx buf **\n");
++      rxhostdesc = priv->rxhostdesc_start;
++      if (rxhostdesc) for (i = 0; i < RX_CNT; i++) {
++              rtl = (i == priv->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", priv->tx_free,
++                              acx_queue_stopped(priv->netdev) ? "STOPPED" : "running");
++      txdesc = priv->txdesc_start;
++      if (txdesc) for (i = 0; i < TX_CNT; i++) {
++              thd = (i == priv->tx_head) ? " [head]" : "";
++              ttl = (i == priv->tx_tail) ? " [tail]" : "";
++              if (txdesc->Ctl_8 & DESC_CTL_ACXDONE)
++                      p += sprintf(p, "%02u DONE   (%02X)%s%s\n", i, txdesc->Ctl_8, thd, ttl);
++              else
++              if (!(txdesc->Ctl_8 & DESC_CTL_HOSTOWN))
++                      p += sprintf(p, "%02u TxWait (%02X)%s%s\n", i, txdesc->Ctl_8, thd, ttl);
++              else
++                      p += sprintf(p, "%02u empty  (%02X)%s%s\n", i, txdesc->Ctl_8, thd, ttl);
++              txdesc = move_txdesc(priv, 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",
++              priv->txbuf_start, priv->txbuf_area_size, (u64)priv->txbuf_startphy,
++              priv->txdesc_size, priv->txdesc_start,
++              priv->txhostdesc_start, priv->txhostdesc_area_size, (u64)priv->txhostdesc_startphy,
++              priv->rxdesc_start,
++              priv->rxhostdesc_start, priv->rxhostdesc_area_size, (u64)priv->rxhostdesc_startphy,
++              priv->rxbuf_start, priv->rxbuf_area_size, (u64)priv->rxbuf_startphy);
++
++      FN_EXIT0;
++      return p;
++}
++
++
++/***********************************************************************
++*/
++int
++acx_proc_eeprom_output(char *buf, wlandevice_t *priv)
++{
++      char *p = buf;
++      int i;
++
++      FN_ENTER;
++
++      for (i = 0; i < 0x400; i++) {
++              acx_read_eeprom_offset(priv, i, p++);
++      }
++
++      FN_EXIT1(p - buf);
++      return p - buf;
++}
++
++
++/***********************************************************************
++*/
++void
++acx_set_interrupt_mask(wlandevice_t *priv)
++{
++      if (IS_ACX111(priv)) {
++              priv->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        */
++                              );
++              priv->irq_mask_off = (u16)~( HOST_INT_CMD_COMPLETE ); /* 0xfdff */
++      } else {
++              priv->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        */
++                              );
++              priv->irq_mask_off = (u16)~( HOST_INT_UNKNOWN ); /* 0x7fff */
++      }
++}
++
++
++/***********************************************************************
++*/
++int
++acx100_s_set_tx_level(wlandevice_t *priv, 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 (priv->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",
++                              priv->netdev->name);
++              return NOT_OK;
++      }
++      printk("%s: changing radio power level to %u dBm (%u)\n",
++                      priv->netdev->name, level_dbm, table[level_dbm]);
++      acxpci_s_write_phy_reg(priv, 0x11, table[level_dbm]);
++      return OK;
++}
++
++
++/*----------------------------------------------------------------
++* acx_e_init_module
++*
++* Module initialization routine, called once at module load time.
++*
++* Returns:
++*     0       - success
++*     ~0      - failure, module is unloaded.
++*
++* Call context:
++*     process thread (insmod or modprobe)
++----------------------------------------------------------------*/
++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
++      acxlog(L_INIT, "running on a little-endian CPU\n");
++#else
++      acxlog(L_INIT, "running on a BIG-ENDIAN CPU\n");
++#endif
++      acxlog(L_INIT, "PCI module " WLAN_RELEASE " initialized, "
++              "waiting for cards to probe...\n");
++
++      res = pci_module_init(&acx_pci_drv_id);
++      FN_EXIT1(res);
++      return res;
++}
++
++
++/*----------------------------------------------------------------
++* acx_e_cleanup_module
++*
++* Called at module unload time.  This is our last chance to
++* clean up after ourselves.
++*
++* Call context:
++*     process thread
++----------------------------------------------------------------*/
++void __exit
++acxpci_e_cleanup_module(void)
++{
++      struct net_device *dev;
++      unsigned long flags;
++
++      FN_ENTER;
++
++      /* Since the whole module is about to be unloaded,
++       * we recursively shutdown all cards we handled instead
++       * of doing it in remove_pci() (which will be activated by us
++       * via pci_unregister_driver at the end).
++       * remove_pci() might just get called after a card eject,
++       * that's why hardware operations have to be done here instead
++       * when the hardware is available. */
++
++      down(&root_acx_dev_sem);
++
++      dev = root_acx_dev.newest;
++      while (dev != NULL) {
++              /* doh, netdev_priv() doesn't have const! */
++              wlandevice_t *priv = netdev_priv(dev);
++
++              acx_sem_lock(priv);
++
++              /* disable both Tx and Rx to shut radio down properly */
++              acx_s_issue_cmd(priv, ACX1xx_CMD_DISABLE_TX, NULL, 0);
++              acx_s_issue_cmd(priv, 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(priv, ACX100_CMD_SLEEP, NULL, 0);
++#endif
++              acx_lock(priv, flags);
++
++              /* disable power LED to save power :-) */
++              acxlog(L_INIT, "switching off power LED to save power :-)\n");
++              acx_l_power_led(priv, 0);
++
++              /* stop our eCPU */
++              if (IS_ACX111(priv)) {
++                      /* FIXME: does this actually keep halting the eCPU?
++                       * I don't think so...
++                       */
++                      acx_l_reset_mac(priv);
++              } else {
++                      u16 temp;
++
++                      /* halt eCPU */
++                      temp = acx_read_reg16(priv, IO_ACX_ECPU_CTRL) | 0x1;
++                      acx_write_reg16(priv, IO_ACX_ECPU_CTRL, temp);
++                      acx_write_flush(priv);
++              }
++
++              acx_unlock(priv, flags);
++
++              acx_sem_unlock(priv);
++
++              dev = priv->prev_nd;
++      }
++
++      up(&root_acx_dev_sem);
++
++      /* now let the PCI layer recursively remove
++       * all PCI related things (acx_e_remove_pci()) */
++      pci_unregister_driver(&acx_pci_drv_id);
++
++      FN_EXIT0;
++}
+diff -Naur linux-2.6.14-omap2/drivers/net/wireless/tiacx/setrate.c linux-h6300-omap2-2.6.14.3/drivers/net/wireless/tiacx/setrate.c
+--- linux-2.6.14-omap2/drivers/net/wireless/tiacx/setrate.c    1970-01-01 02:00:00.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/drivers/net/wireless/tiacx/setrate.c    2005-09-28 23:54:23.000000000 +0300
+@@ -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;
++}
+diff -Naur linux-2.6.14-omap2/drivers/net/wireless/tiacx/usb.c linux-h6300-omap2-2.6.14.3/drivers/net/wireless/tiacx/usb.c
+--- linux-2.6.14-omap2/drivers/net/wireless/tiacx/usb.c        1970-01-01 02:00:00.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/drivers/net/wireless/tiacx/usb.c        2005-09-28 23:54:23.000000000 +0300
+@@ -0,0 +1,1700 @@
++/***********************************************************************
++** 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>
++**
++** Issues:
++**  - Note that this driver relies on a native little-endian byteformat
++**    at some points
++**
++** 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>
++#include <linux/config.h>
++#include <linux/types.h>
++#include <linux/module.h>
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
++#include <linux/moduleparam.h>
++#endif
++#include <linux/kernel.h>
++#include <linux/usb.h>
++#include <linux/netdevice.h>
++#include <linux/rtnetlink.h>
++#include <linux/etherdevice.h>
++#include <linux/wireless.h>
++#if WIRELESS_EXT >= 13
++#include <net/iw_handler.h>
++#endif
++
++#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 ??? */
++
++#define QUEUE_BULK    0
++#define ZERO_PACKET   URB_ZERO_PACKET
++
++static inline int
++submit_urb(struct urb *urb, int mem_flags)
++{
++      return usb_submit_urb(urb, mem_flags);
++}
++static inline struct urb*
++alloc_urb(int iso_pk, int mem_flags)
++{
++      return usb_alloc_urb(iso_pk, mem_flags);
++}
++
++
++/***********************************************************************
++*/
++#define ACX100_VENDOR_ID 0x2001
++#define ACX100_PRODUCT_ID_UNBOOTED 0x3B01
++#define ACX100_PRODUCT_ID_BOOTED 0x3B00
++
++/* RX-Timeout: NONE (request waits forever) */
++#define ACX100_USB_RX_TIMEOUT (0)
++
++#define ACX100_USB_TX_TIMEOUT (4*HZ)
++
++#define USB_CTRL_HARD_TIMEOUT 5500   /* steps in ms */
++
++
++/***********************************************************************
++** Prototypes
++*/
++static int acx100usb_e_probe(struct usb_interface *, const struct usb_device_id *);
++static void acx100usb_e_disconnect(struct usb_interface *);
++static void acx100usb_i_complete_tx(struct urb *, struct pt_regs *);
++static void acx100usb_i_complete_rx(struct urb *, struct pt_regs *);
++static int acx100usb_e_open(struct net_device *);
++static int acx100usb_e_close(struct net_device *);
++static void acx100usb_i_set_rx_mode(struct net_device *);
++static int acx100usb_e_init_network_device(struct net_device *);
++static int acx100usb_boot(struct usb_device *);
++
++static struct net_device_stats * acx_e_get_stats(struct net_device *);
++static struct iw_statistics *acx_e_get_wireless_stats(struct net_device *);
++
++static void acx100usb_l_poll_rx(wlandevice_t *, int number);
++
++static void acx100usb_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)
++//// Bogus! We CANNOT pretend that rxbuffer_t is larger than it is.
++/* make it a multiply of 64 */
++/* #define RXBUFSIZE ((sizeof(rxbuffer_t)+63) & ~63) */
++#define RXBUFSIZE sizeof(rxbuffer_t)
++
++static const struct usb_device_id
++acx100usb_ids[] = {
++      { USB_DEVICE(ACX100_VENDOR_ID, ACX100_PRODUCT_ID_BOOTED) },
++      { USB_DEVICE(ACX100_VENDOR_ID, ACX100_PRODUCT_ID_UNBOOTED) },
++      {}
++};
++
++
++/* USB driver data structure as required by the kernel's USB core */
++static struct usb_driver
++acx100usb_driver = {
++      .name = "acx_usb",
++      .owner = THIS_MODULE,
++      .probe = acx100usb_e_probe,
++      .disconnect = acx100usb_e_disconnect,
++      .id_table = acx100usb_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 osolete, usb_unlink_urb will always be
++** asynchronuos while usb_kill_urb is synchronuos and should be called
++** directly. -> drivers/usb/core/urb.c
++**
++** In light of this, timeout is just for paranoid reasons...
++*/
++static void
++acx_unlink_and_free_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) then what?? */
++      }
++
++      /* just a refcounted kfree, safe undef lock */
++      usb_free_urb(urb);
++}
++
++
++/***********************************************************************
++*/
++#if ACX_DEBUG
++static char*
++acx100usb_pstatus(int val)
++{
++      static char status[20];
++
++      if (val < 0)
++              sprintf(status, "errno %d", -val);
++      else
++              sprintf(status, "length %d", val);
++
++      return status;
++}
++#endif /* ACX_DEBUG */
++
++
++/***********************************************************************
++** EEPROM and PHY read/write helpers
++*/
++/***********************************************************************
++** acxusb_s_read_phy_reg
++*/
++int
++acxusb_s_read_phy_reg(wlandevice_t *priv, u32 reg, u8 *charbuf)
++{
++      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);
++      acx_s_issue_cmd(priv, ACX1xx_CMD_MEM_READ, &mem, sizeof(mem) - 4);
++      *charbuf = mem.data;
++      acxlog(L_DEBUG, "radio PHY at 0x%04X = 0x%02X\n", *charbuf, reg);
++
++      FN_EXIT1(OK);
++      return OK;
++}
++
++
++/***********************************************************************
++*/
++int
++acxusb_s_write_phy_reg(wlandevice_t *priv, 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;
++//FIXME: maybe sizeof() - 4?
++      acx_s_issue_cmd(priv, ACX1xx_CMD_MEM_WRITE, &mem, sizeof(mem));
++      acxlog(L_DEBUG, "radio PHY write 0x%02X at 0x%04X\n", value, reg);
++
++      FN_EXIT1(OK);
++      return OK;
++}
++
++
++/***********************************************************************
++** acx_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(
++      wlandevice_t *priv,
++      unsigned cmd,
++      void *buffer,
++      unsigned buflen,
++      unsigned timeout)
++{
++#else
++int
++acxusb_s_issue_cmd_timeo_debug(
++      wlandevice_t *priv,
++      unsigned cmd,
++      void *buffer,
++      unsigned buflen,
++      unsigned timeout,
++      const char* cmdstr)
++{
++#endif
++      /* USB ignores timeout param */
++
++      struct usb_device *usbdev;
++      struct {
++              u16     cmd ACX_PACKED;
++              u16     status ACX_PACKED;
++              u8      data[1] ACX_PACKED;
++      } *loc;
++      const char *devname;
++      int acklen, blocklen, inpipe, outpipe;
++      int cmd_status;
++      int result;
++
++      FN_ENTER;
++
++      devname = priv->netdev->name;
++      if (!devname || !devname[0])
++              devname = "acx";
++
++      acxlog(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 wlandevice */
++      usbdev = priv->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);
++      acxlog(L_CTL, "ctrl inpipe=0x%X outpipe=0x%X\n", inpipe, outpipe);
++      acxlog(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 */
++              USB_CTRL_HARD_TIMEOUT /* timeout in ms */
++      );
++      acxlog(L_CTL, "wrote %d bytes\n", result);
++      if (result < 0) {
++              goto bad;
++      }
++
++      /* check for device acknowledge */
++      acxlog(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 */
++              USB_CTRL_HARD_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);
++              acxlog(L_CTL, "response frame: cmd=0x%04X status=%d\n",
++                      le16_to_cpu(loc->cmd),
++                      cmd_status);
++      }
++      kfree(loc);
++      FN_EXIT1(OK);
++      return OK;
++bad:
++      kfree(loc);
++      /* 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;
++}
++
++
++/***********************************************************************
++** acx100usb_e_probe()
++**
++** Inputs:
++**    dev -> Pointer to usb_device structure that may or may not be claimed
++**  ifNum -> Interface number
++**  devID -> Device ID (vendor and product specific stuff)
++************************************************************************
++** Returns:
++**  (void *) Pointer to (custom) driver context or NULL if we are not interested
++**           or unable to handle the offered device.
++**
++** Description:
++**  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
++acx_netdev_init(struct net_device *dev) {}
++
++static int
++acx100usb_e_probe(struct usb_interface *intf, const struct usb_device_id *devID)
++{
++      struct usb_device *usbdev = interface_to_usbdev(intf);
++      wlandevice_t *priv = NULL;
++      struct net_device *dev = 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;
++
++      FN_ENTER;
++
++      /* First check if this is the "unbooted" hardware */
++      if ((usbdev->descriptor.idVendor == ACX100_VENDOR_ID)
++       && (usbdev->descriptor.idProduct == ACX100_PRODUCT_ID_UNBOOTED)) {
++              /* Boot the device (i.e. upload the firmware) */
++              acx100usb_boot(usbdev);
++
++              /* OK, we are done with booting. Normally, the
++              ** ID for the unbooted device should disappear
++              ** and it will not need a driver anyway...so
++              ** return a NULL
++              */
++              acxlog(L_INIT, "finished booting, returning from probe()\n");
++              result = OK; /* success */
++              goto end;
++      }
++
++      if ((usbdev->descriptor.idVendor != ACX100_VENDOR_ID)
++       || (usbdev->descriptor.idProduct != ACX100_PRODUCT_ID_BOOTED)) {
++              goto end_nodev;
++      }
++
++      /* Ok, so it's our device and it is already booted */
++
++      /* Allocate memory for a network device */
++      dev = alloc_netdev(sizeof(wlandevice_t), "wlan%d", acx_netdev_init);
++      /* (NB: memsets to 0 entire area) */
++      if (!dev) {
++              msg = "acx: no memory for netdev\n";
++              goto end_nomem;
++      }
++      dev->init = (void *)&acx100usb_e_init_network_device;
++
++      /* Setup private driver context */
++      priv = netdev_priv(dev);
++      priv->netdev = dev;
++      priv->dev_type = DEVTYPE_USB;
++      priv->chip_type = CHIPTYPE_ACX100;
++      /* FIXME: should be read from register (via firmware) using standard ACX code */
++      priv->radio_type = RADIO_MAXIM_0D;
++      priv->usbdev = usbdev;
++
++      spin_lock_init(&priv->lock);    /* initial state: unlocked */
++      sema_init(&priv->sem, 1);       /* initial state: 1 (upped) */
++
++      /* Initialize the device context and also check
++      ** if 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;
++      acxlog(L_DEBUG, "# of endpoints: %d\n", numep);
++
++      /* obtain information about the endpoint
++      ** addresses, begin with some default values
++      */
++      priv->bulkoutep = 1;
++      priv->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)
++                              priv->bulkinep = epdesc->bEndpointAddress & 0xF;
++                      else
++                              priv->bulkoutep = epdesc->bEndpointAddress & 0xF;
++              }
++      }
++      acxlog(L_DEBUG, "bulkout ep: 0x%X\n", priv->bulkoutep);
++      acxlog(L_DEBUG, "bulkin ep: 0x%X\n", priv->bulkinep);
++
++      /* Set the packet-size equivalent to the buffer size */
++      /* already done by memset: priv->rxtruncsize = 0; */
++      acxlog(L_DEBUG, "TXBUFSIZE=%d RXBUFSIZE=%d\n",
++                              (int) TXBUFSIZE, (int) RXBUFSIZE);
++
++      priv->tx_free = ACX100_USB_NUM_BULK_URBS;
++      /* already done by memset:
++      for (i = 0; i < ACX100_USB_NUM_BULK_URBS; i++) {
++              priv->usb_tx[i].busy = 0;
++      }
++      */
++
++      /* Setup URBs for bulk-in/out messages */
++      for (i = 0; i < ACX100_USB_NUM_BULK_URBS; i++) {
++              priv->bulkrx_urbs[i] = alloc_urb(0, GFP_KERNEL);
++              if (!priv->bulkrx_urbs[i]) {
++                      msg = "acx: no memory for input URB\n";
++                      goto end_nomem;
++              }
++              priv->bulkrx_urbs[i]->status = 0;
++
++              priv->usb_tx[i].urb = alloc_urb(0, GFP_KERNEL);
++              if (!priv->usb_tx[i].urb) {
++                      msg = "acx: no memory for output URB\n";
++                      goto end_nomem;
++              }
++              priv->usb_tx[i].urb->status = 0;
++
++              priv->usb_tx[i].priv = priv;
++      }
++
++      usb_set_intfdata(intf, priv);
++      SET_NETDEV_DEV(dev, &intf->dev);
++
++      /* Register the network device */
++      acxlog(L_INIT, "registering network device\n");
++      result = register_netdev(dev);
++      if (result != 0) {
++              msg = "acx: failed to register network device "
++                      "for USB WLAN (errcode=%d)\n";
++              goto end_nomem;
++      }
++#ifdef CONFIG_PROC_FS
++      if (OK != acx_proc_register_entries(dev)) {
++              printk("acx: /proc registration failed\n");
++      }
++#endif
++
++      printk("acx: USB module " WLAN_RELEASE " loaded successfully\n");
++
++#if CMD_DISCOVERY
++      great_inquisitor(priv);
++#endif
++
++      /* Everything went OK, we are happy now */
++      result = OK;
++      goto end;
++
++end_nomem:
++      printk(msg, result);
++
++      if (dev) {
++              for (i = 0; i < ACX100_USB_NUM_BULK_URBS; i++) {
++                      usb_free_urb(priv->bulkrx_urbs[i]);
++                      usb_free_urb(priv->usb_tx[i].urb);
++              }
++              free_netdev(dev);
++      }
++      result = -ENOMEM;
++      goto end;
++
++end_nodev:
++
++      /* no device we could handle, return error. */
++      result = -EIO;
++
++end:
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/***********************************************************************
++** acx100usb_e_disconnect():
++** Inputs:
++**         dev -> Pointer to usb_device structure handled by this module
++**  devContext -> Pointer to own device context (acx100usb_context)
++************************************************************************
++** Description:
++**  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
++acx100usb_e_disconnect(struct usb_interface *intf)
++{
++      wlandevice_t *priv = usb_get_intfdata(intf);
++      unsigned long flags;
++      int i;
++
++      FN_ENTER;
++
++      /* No WLAN device...no sense */
++      if (!priv)
++              goto end;
++
++      /*
++       * We get the sem *after* FLUSH to avoid a deadlock.
++       * See pci.c:acx_s_down() for deails.
++       */
++      FLUSH_SCHEDULED_WORK();
++      acx_sem_lock(priv);
++
++      acx_lock(priv, flags);
++
++      /* I wonder if above is enough to prevent tx/rx callbacks
++      ** to start queue again? Like this:
++      ** complete_rx -> acx_l_process_rxbuf -> associated -> acx_start_queue()
++      ** Oh well... */
++
++      /* This device exists no more. */
++      usb_set_intfdata(intf, NULL);
++
++      /* stop the transmit queue */
++      if (priv->netdev) {
++              acx_stop_queue(priv->netdev, "on USB disconnect");
++#ifdef CONFIG_PROC_FS
++              acx_proc_unregister_entries(priv->netdev);
++#endif
++      }
++
++      /* now abort pending URBs and free them */
++      for (i = 0; i < ACX100_USB_NUM_BULK_URBS; i++) {
++              acx_unlink_and_free_urb(priv->bulkrx_urbs[i]);
++              acx_unlink_and_free_urb(priv->usb_tx[i].urb);
++      }
++
++      acx_unlock(priv, flags);
++      acx_sem_unlock(priv);
++
++      /* Unregister the network devices */
++      if (priv->netdev) {
++              unregister_netdev(priv->netdev);
++              free_netdev(priv->netdev);
++      }
++end:
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++** acx100usb_boot():
++** Inputs:
++**    usbdev -> Pointer to kernel's usb_device structure
++**  endpoint -> Address of the endpoint for control transfers
++************************************************************************
++** Returns:
++**  (int) Errorcode or 0 on success
++**
++** Description:
++**  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 int
++acx100usb_boot(struct usb_device *usbdev)
++{
++      static const char filename[] = "tiacx100usb";
++
++      char *firmware = NULL;
++      char *usbbuf;
++      unsigned int offset;
++      unsigned int len, inpipe, outpipe;
++      u32 checksum;
++      u32 size;
++      int result;
++
++      FN_ENTER;
++
++      usbbuf = kmalloc(ACX100_USB_RWMEM_MAXLEN, GFP_KERNEL);
++      if (!usbbuf) {
++              printk(KERN_ERR "acx: no memory for USB transfer buffer ("
++                      STRING(ACX100_USB_RWMEM_MAXLEN)" bytes)\n");
++              result = -ENOMEM;
++              goto end;
++      }
++      firmware = (char *)acx_s_read_fw(&usbdev->dev, filename, &size);
++      if (!firmware) {
++              result = -EIO;
++              goto end;
++      }
++      acxlog(L_INIT, "firmware size: %d bytes\n", size);
++
++      /* Obtain the I/O pipes */
++      outpipe = usb_sndctrlpipe(usbdev, 0);
++      inpipe = usb_rcvctrlpipe(usbdev, 0);
++
++      /* now upload the firmware, slice the data into blocks */
++      offset = 8;
++      while (offset < size) {
++              len = size - offset;
++              if (len >= ACX100_USB_RWMEM_MAXLEN) {
++                      len = ACX100_USB_RWMEM_MAXLEN;
++              }
++              acxlog(L_INIT, "uploading firmware (%d bytes, offset=%d)\n",
++                                              len, offset);
++              result = 0;
++              memcpy(usbbuf, firmware + offset, len);
++              result = usb_control_msg(usbdev, outpipe,
++                      ACX_USB_REQ_UPLOAD_FW,
++                      USB_TYPE_VENDOR|USB_DIR_OUT,
++                      size - 8, /* value */
++                      0, /* index */
++                      usbbuf, /* dataptr */
++                      len, /* size */
++                      3000 /* timeout in ms */
++              );
++              offset += len;
++              if (result < 0) {
++#if ACX_DEBUG
++                      printk(KERN_ERR "acx: error %d (%s) during upload "
++                              "of firmware, aborting\n", result,
++                              acx100usb_pstatus(result));
++#else
++                      printk(KERN_ERR "acx: error %d during upload "
++                              "of firmware, aborting\n", result);
++#endif
++                      goto end;
++              }
++      }
++
++      /* finally, send the checksum and reboot the device */
++      checksum = le32_to_cpu(*(u32 *)firmware);
++      /* is this triggers the reboot? */
++      result = usb_control_msg(usbdev, outpipe,
++              ACX_USB_REQ_UPLOAD_FW,
++              USB_TYPE_VENDOR|USB_DIR_OUT,
++              checksum & 0xffff, /* value */
++              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,
++              checksum & 0xffff, /* value */
++              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) {
++              kfree(usbbuf);
++              printk(KERN_ERR "acx: invalid checksum?\n");
++              result = -EINVAL;
++              goto end;
++      }
++      result = 0;
++end:
++      vfree(firmware);
++      kfree(usbbuf);
++
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/***********************************************************************
++** acx100usb_e_init_network_device():
++** Inputs:
++**    dev -> Pointer to network device
++************************************************************************
++** Description:
++**  Basic setup of a network device for use with the WLAN device.
++*/
++static int
++acx100usb_e_init_network_device(struct net_device *dev)
++{
++      wlandevice_t *priv;
++      int result = 0;
++
++      FN_ENTER;
++
++      /* Setup the device and stop the queue */
++      ether_setup(dev);
++      acx_stop_queue(dev, "on init");
++
++      priv = netdev_priv(dev);
++
++      acx_sem_lock(priv);
++
++      /* put the ACX100 out of sleep mode */
++      acx_s_issue_cmd(priv, ACX1xx_CMD_WAKE, NULL, 0);
++
++      /* Register the callbacks for the network device functions */
++      dev->open = &acx100usb_e_open;
++      dev->stop = &acx100usb_e_close;
++      dev->hard_start_xmit = (void *)&acx_i_start_xmit;
++      dev->get_stats = (void *)&acx_e_get_stats;
++      dev->get_wireless_stats = (void *)&acx_e_get_wireless_stats;
++#if WIRELESS_EXT >= 13
++      dev->wireless_handlers = (struct iw_handler_def *)&acx_ioctl_handler_def;
++#else
++      dev->do_ioctl = (void *)&acx_e_ioctl_old;
++#endif
++      dev->set_multicast_list = (void *)&acx100usb_i_set_rx_mode;
++#ifdef HAVE_TX_TIMEOUT
++      dev->tx_timeout = &acx100usb_i_tx_timeout;
++      dev->watchdog_timeo = 4 * HZ;
++#endif
++      result = acx_s_init_mac(dev);
++      if (OK != result)
++              goto end;
++      result = acx_s_set_defaults(priv);
++      if (OK != result) {
++              printk("%s: acx_set_defaults FAILED\n", dev->name);
++              goto end;
++      }
++
++      SET_MODULE_OWNER(dev);
++end:
++      acx_sem_unlock(priv);
++
++      FN_EXIT1(result);
++      return result;
++}
++
++
++/***********************************************************************
++** acx100usb_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
++acx100usb_e_open(struct net_device *dev)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++      unsigned long flags;
++      int i;
++
++      FN_ENTER;
++
++      acx_sem_lock(priv);
++
++      /* put the ACX100 out of sleep mode */
++      acx_s_issue_cmd(priv, ACX1xx_CMD_WAKE, NULL, 0);
++
++      acx_init_task_scheduler(priv);
++
++      init_timer(&priv->mgmt_timer);
++      priv->mgmt_timer.function = acx_i_timer;
++      priv->mgmt_timer.data = (unsigned long)priv;
++
++      /* set ifup to 1, since acx_start needs it */
++      SET_BIT(priv->dev_state_mask, ACX_STATE_IFACE_UP);
++      acx_s_start(priv);
++
++      acx_start_queue(dev, "on open");
++
++      acx_lock(priv, flags);
++      for (i = 0; i < ACX100_USB_NUM_BULK_URBS; i++) {
++              acx100usb_l_poll_rx(priv, i);
++      }
++      acx_unlock(priv, flags);
++
++      WLAN_MOD_INC_USE_COUNT;
++
++      acx_sem_unlock(priv);
++
++      FN_EXIT0;
++      return 0;
++}
++
++
++/***********************************************************************
++** acx100usb_l_poll_rx
++** This function initiates a bulk-in USB transfer (in case the interface
++** is up).
++*/
++static void
++acx100usb_l_poll_rx(wlandevice_t *priv, int number)
++{
++      struct usb_device *usbdev;
++      rxbuffer_t *inbuf;
++      acx_usb_bulk_context_t *rxcon;
++      struct urb *rxurb;
++      int errcode;
++      unsigned int inpipe;
++
++      FN_ENTER;
++
++      if (!(priv->dev_state_mask & ACX_STATE_IFACE_UP)) {
++              goto end;
++      }
++
++      rxcon = &priv->rxcons[number];
++      inbuf = &priv->bulkins[number];
++      rxurb = priv->bulkrx_urbs[number];
++      usbdev = priv->usbdev;
++
++      rxcon->device = priv;
++      rxcon->number = number;
++      inpipe = usb_rcvbulkpipe(usbdev, priv->bulkinep);
++      if (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);
++      }
++      rxurb->actual_length = 0;
++      usb_fill_bulk_urb(rxurb, usbdev, inpipe,
++              inbuf, /* dataptr */
++              RXBUFSIZE, /* size */
++              acx100usb_i_complete_rx, /* handler */
++              rxcon /* handler param */
++      );
++      rxurb->transfer_flags = QUEUE_BULK;
++
++      /* ATOMIC: we may be called from complete_rx() usb callback */
++      errcode = submit_urb(rxurb, GFP_ATOMIC);
++      /* FIXME: evaluate the error code! */
++      acxlog(L_USBRXTX, "SUBMIT RX (%d) inpipe=0x%X size=%d errcode=%d\n",
++                      number, inpipe, (int) RXBUFSIZE, errcode);
++
++end:
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++** acx100usb_i_complete_rx():
++** Inputs:
++**     urb -> Pointer to USB request block
++**    regs -> Pointer to register-buffer for syscalls (see asm/ptrace.h)
++************************************************************************
++** Description:
++**  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
++acx100usb_i_complete_rx(struct urb *urb, struct pt_regs *regs)
++{
++      wlandevice_t *priv;
++      rxbuffer_t *ptr;
++      rxbuffer_t *inbuf;
++      unsigned long flags;
++      int size, number, remsize, packetsize;
++
++      FN_ENTER;
++
++      if (!urb->context) {
++              printk(KERN_ERR "acx: error, urb context was NULL\n");
++              goto end; /* at least try to prevent the worst */
++      }
++
++      priv = ((acx_usb_bulk_context_t *)urb->context)->device;
++
++      acx_lock(priv, flags);
++
++      /* TODO: we maybe need to check whether urb was unlinked
++      ** (happens on disconnect and close, see there). How? */
++
++      number = ((acx_usb_bulk_context_t *)urb->context)->number;
++      size = urb->actual_length;
++      remsize = size;
++
++      acxlog(L_USBRXTX, "RETURN RX (%d) status=%d size=%d\n",
++                              number, urb->status, size);
++
++      inbuf = &priv->bulkins[number];
++      ptr = inbuf;
++
++      /* check if the transfer was aborted */
++      switch (urb->status) {
++      case 0: /* No error */
++              break;
++      case -EOVERFLOW:
++              printk(KERN_ERR "acx: error in rx, data overrun -> emergency stop\n");
++              /* LOCKING BUG! acx100usb_e_close(priv->netdev); */
++              goto end_unlock;
++      case -ECONNRESET:
++              goto do_poll_rx;
++      default:
++              priv->stats.rx_errors++;
++              printk("acx: rx error (urb status=%d)\n", urb->status);
++              goto do_poll_rx;
++      }
++
++      if (!size)
++              printk("acx: warning, encountered zerolength rx packet\n");
++
++      if (urb->transfer_buffer != inbuf)
++              goto do_poll_rx;
++
++      /* check if previous frame was truncated
++      ** FIXME: this code can only handle truncation
++      ** of consecutive packets!
++      */
++      if (priv->rxtruncsize) {
++              int tail_size;
++
++              ptr = &priv->rxtruncbuf;
++              packetsize = RXBUF_BYTES_RCVD(ptr) + RXBUF_HDRSIZE;
++              if (acx_debug & L_USBRXTX) {
++                      printk("handling truncated frame (truncsize=%d size=%d "
++                                      "packetsize(from trunc)=%d)\n",
++                                      priv->rxtruncsize, size, packetsize);
++                      acx_dump_bytes(ptr, RXBUF_HDRSIZE);
++                      acx_dump_bytes(inbuf, RXBUF_HDRSIZE);
++              }
++
++              /* bytes needed for rxtruncbuf completion: */
++              tail_size = packetsize - priv->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) + priv->rxtruncsize, inbuf, size);
++                      priv->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: priv->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) + priv->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(priv, ptr);
++                      priv->rxtruncsize = 0;
++                      ptr = (rxbuffer_t *) (((char *)inbuf) + tail_size);
++                      remsize -= tail_size;
++              }
++              acxlog(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);
++                      break;
++              }
++              packetsize = RXBUF_BYTES_RCVD(ptr) + RXBUF_HDRSIZE;
++              acxlog(L_USBRXTX, "packet with packetsize=%d\n", packetsize);
++              if (packetsize > sizeof(rxbuffer_t)) {
++                      printk("acx: packet exceeds max wlan "
++                              "frame size (%d > %d). size=%d\n",
++                              packetsize, (int) sizeof(rxbuffer_t), size);
++                      /* FIXME: put some real error-handling in here! */
++                      break;
++              }
++
++              /* skip null packets (does this really happen?!) */
++              if (packetsize == RXBUF_HDRSIZE) {
++                      remsize -= RXBUF_HDRSIZE;
++                      if (acx_debug & L_USBRXTX) {
++                              printk("acx: null packet, new remsize=%d. "
++                                      "header follows:\n", remsize);
++                              acx_dump_bytes(ptr, RXBUF_HDRSIZE);
++                      }
++                      ptr = (rxbuffer_t *)(((char *)ptr) + RXBUF_HDRSIZE);
++                      continue;
++              }
++
++              if (packetsize > remsize) {
++                      /* frame truncation handling */
++                      if (acx_debug & L_USBRXTX) {
++                              printk("need to truncate packet, "
++                                      "packetsize=%d remsize=%d "
++                                      "size=%d\n",
++                                      packetsize, remsize, size);
++                              acx_dump_bytes(ptr, RXBUF_HDRSIZE);
++                      }
++                      memcpy(&priv->rxtruncbuf, ptr, remsize);
++                      priv->rxtruncsize = remsize;
++                      break;
++              } else { /* packetsize <= remsize */
++                      /* now handle the received data */
++                      acx_l_process_rxbuf(priv, ptr);
++
++                      ptr = (rxbuffer_t *)(((char *)ptr) + packetsize);
++                      remsize -= packetsize;
++                      if ((acx_debug & L_USBRXTX) && remsize) {
++                              printk("more than one packet in buffer, "
++                                              "second packet hdr follows\n");
++                              acx_dump_bytes(ptr, RXBUF_HDRSIZE);
++                      }
++              }
++      }
++
++do_poll_rx:
++      /* look for the next rx */
++      if (priv->dev_state_mask & ACX_STATE_IFACE_UP) {
++              /* receive of frame completed, now look for the next one */
++              acx100usb_l_poll_rx(priv, number);
++      }
++
++end_unlock:
++      acx_unlock(priv, flags);
++end:
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++** acx100usb_i_complete_tx():
++** Inputs:
++**     urb -> Pointer to USB request block
++**    regs -> Pointer to register-buffer for syscalls (see asm/ptrace.h)
++************************************************************************
++** Description:
++**   This function is invoked upon termination of a USB transfer. As the
++**   USB device is only capable of sending a limited amount of bytes per
++**   transfer to the bulk-out endpoint, this routine checks if there are
++**   more bytes to send and triggers subsequent transfers. In case the
++**   transfer size exactly matches the maximum bulk-out size, it triggers
++**   a transfer of a null-frame, telling the card that this is it. Upon
++**   completion of a frame, it checks whether the Tx ringbuffer contains
++**   more data to send and invokes the Tx routines if this is the case.
++**   If there are no more occupied Tx descriptors, the Tx Mutex is unlocked
++**   and the network queue is switched back to life again.
++**
++** FIXME: unlike PCI code, we do not analyze tx rate used, retries, etc...
++** Thus we have no automatic rate control in USB!
++*/
++static void
++acx100usb_i_complete_tx(struct urb *urb, struct pt_regs *regs)
++{
++      wlandevice_t *priv;
++      usb_tx_t *tx;
++      unsigned long flags;
++
++      FN_ENTER;
++
++      if (!urb->context) {
++              printk(KERN_ERR "acx: error, NULL context in tx completion callback\n");
++              /* FIXME: real error-handling code must go here! */
++              goto end;
++      }
++
++      tx = (usb_tx_t *)urb->context;
++      priv = tx->priv;
++
++      acx_lock(priv, flags);
++
++      /* TODO: we maybe need to check whether urb was unlinked
++      ** (happens on disconnect and close, see there). How? */
++
++      acxlog(L_USBRXTX, "RETURN TX (%p): status=%d size=%d\n",
++                              tx, urb->status, urb->actual_length);
++
++      /* handle USB transfer errors */
++      switch (urb->status) {
++      case 0: /* No error */
++              break;
++      case -ECONNRESET:
++              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 */
++      priv->tx_free++;
++      tx->busy = 0;
++
++/* end_unlock: */
++      acx_unlock(priv, flags);
++end:
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++** acx100usb_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
++acx100usb_e_close(struct net_device *dev)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++      unsigned long flags;
++      int i;
++
++      FN_ENTER;
++
++#if WE_STILL_DONT_CARE_ABOUT_IT
++      /* Transmit a disassociate frame */
++      lock
++      acx_l_transmit_disassoc(priv, &client);
++      unlock
++#endif
++
++      /*
++       * We get the sem *after* FLUSH to avoid a deadlock.
++       * See pci.c:acx_s_down() for deails.
++       */
++      FLUSH_SCHEDULED_WORK();
++      acx_sem_lock(priv);
++
++      /* stop the transmit queue, mark the device as DOWN */
++      acx_lock(priv, flags);
++      acx_stop_queue(dev, "on iface stop");
++      CLEAR_BIT(priv->dev_state_mask, ACX_STATE_IFACE_UP);
++
++      /* I wonder if above is enough to prevent tx/rx callbacks
++      ** to start queue again? Like this:
++      ** complete_rx -> acx_l_process_rxbuf -> associated -> acx_start_queue()
++      ** Oh well... */
++
++      /* stop pending rx/tx urb transfers */
++      for (i = 0; i < ACX100_USB_NUM_BULK_URBS; i++) {
++              acx_unlink_and_free_urb(priv->bulkrx_urbs[i]);
++              acx_unlink_and_free_urb(priv->usb_tx[i].urb);
++      }
++      acx_unlock(priv, flags);
++
++      /* disable rx and tx */
++      acx_s_issue_cmd(priv, ACX1xx_CMD_DISABLE_TX, NULL, 0);
++      acx_s_issue_cmd(priv, ACX1xx_CMD_DISABLE_RX, NULL, 0);
++
++      /* power down the device */
++      acx_s_issue_cmd(priv, ACX1xx_CMD_SLEEP, NULL, 0);
++
++      acx_sem_unlock(priv);
++
++      /* decrease module-in-use count (if necessary) */
++
++      WLAN_MOD_DEC_USE_COUNT;
++
++      FN_EXIT0;
++      return 0;
++}
++
++
++/***************************************************************
++** acxusb_l_alloc_tx
++** Actually returns a usb_tx_t* ptr
++*/
++tx_t*
++acxusb_l_alloc_tx(wlandevice_t* priv)
++{
++      int i;
++      usb_tx_t *tx = NULL;
++
++      FN_ENTER;
++
++      for (i = 0; i < ACX100_USB_NUM_BULK_URBS; i++) {
++              if (!priv->usb_tx[i].busy) {
++                      tx = &priv->usb_tx[i];
++                      tx->busy = 1;
++                      break;
++              }
++      }
++      if (i >= ACX100_USB_NUM_BULK_URBS) {
++              printk("acx: tx buffers full\n");
++      }
++
++      FN_EXIT0;
++
++      return (tx_t*)tx;
++}
++
++
++/***************************************************************
++*/
++void*
++acxusb_l_get_txbuf(wlandevice_t *priv, 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(wlandevice_t *priv, 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;
++      u8 rate100;
++
++      FN_ENTER;
++
++      tx = ((usb_tx_t *)tx_opaque);
++      txurb = tx->urb;
++      txbuf = &tx->bulkout;
++      whdr = (wlan_hdr_t *)txbuf->data;
++
++      priv->tx_free--;
++      acxlog(L_DEBUG, "using buf#%d free=%d len=%d\n",
++                      (int)(tx - priv->usb_tx),
++                      priv->tx_free, wlanpkt_len);
++
++      switch (priv->mode) {
++      case ACX_MODE_0_ADHOC:
++      case ACX_MODE_3_AP:
++              clt = acx_l_sta_list_get(priv, whdr->a1);
++              break;
++      case ACX_MODE_2_STA:
++              clt = priv->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;
++      }
++
++      /* used in tx cleanup routine for auto rate and accounting: */
++//TODO: currently unused - fix that
++      tx->txc = clt;
++
++      rate100 = clt ? clt->rate_100 : priv->rate_bcast100;
++
++      /* fill the USB transfer header */
++      txbuf->desc = cpu_to_le16(USB_TXBUF_TXDESC);
++      txbuf->MPDUlen = cpu_to_le16(wlanpkt_len);
++      txbuf->ctrl1 = 0;
++      txbuf->ctrl2 = 0;
++      txbuf->hostData = cpu_to_le32(wlanpkt_len | (rate100 << 24));
++      if (1 == priv->preamble_cur)
++              SET_BIT(txbuf->ctrl1, DESC_CTL_SHORT_PREAMBLE);
++      SET_BIT(txbuf->ctrl1, DESC_CTL_FIRSTFRAG);
++      txbuf->txRate = rate100;
++      txbuf->index = 1;
++      txbuf->dataLength = cpu_to_le16(wlanpkt_len);
++
++      if ( (WF_FC_FTYPEi & whdr->fc) == WF_FTYPE_DATAi )
++              SET_BIT(txbuf->hostData, cpu_to_le32(USB_TXBUF_HD_ISDATA));
++      if (mac_is_directed(whdr->a1))
++              SET_BIT(txbuf->hostData, cpu_to_le32(USB_TXBUF_HD_DIRECTED));
++      else if (mac_is_bcast(whdr->a1))
++              SET_BIT(txbuf->hostData, cpu_to_le32(USB_TXBUF_HD_BROADCAST));
++
++      if (acx_debug & L_DATA) {
++              printk("dump of bulk out urb:\n");
++              acx_dump_bytes(txbuf, wlanpkt_len + USB_TXBUF_HDRSIZE);
++      }
++
++      if (txurb->status == -EINPROGRESS) {
++              printk("acx: trying to submit tx urb while already in progress\n");
++      }
++
++      /* now schedule the USB transfer */
++      usbdev = priv->usbdev;
++      outpipe = usb_sndbulkpipe(usbdev, priv->bulkoutep);
++//can be removed, please try & test:
++      tx->priv = priv;
++
++      usb_fill_bulk_urb(txurb, usbdev, outpipe,
++              txbuf, /* dataptr */
++              wlanpkt_len + USB_TXBUF_HDRSIZE, /* size */
++              acx100usb_i_complete_tx, /* handler */
++              tx /* handler param */
++      );
++
++      txurb->transfer_flags = QUEUE_BULK|ZERO_PACKET;
++      ucode = submit_urb(txurb, GFP_ATOMIC);
++      acxlog(L_USBRXTX, "SUBMIT TX (%p): outpipe=0x%X buf=%p txsize=%d "
++              "errcode=%d\n", tx, outpipe, txbuf,
++              wlanpkt_len + USB_TXBUF_HDRSIZE, ucode);
++
++      if (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
++              */
++              priv->stats.tx_errors++;
++              tx->busy = 0;
++              priv->tx_free++;
++      }
++end:
++      FN_EXIT0;
++}
++
++
++/***********************************************************************
++*/
++static struct net_device_stats*
++acx_e_get_stats(netdevice_t *dev)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++      return &priv->stats;
++}
++
++
++/***********************************************************************
++*/
++static struct iw_statistics*
++acx_e_get_wireless_stats(netdevice_t *dev)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++      FN_ENTER;
++      FN_EXIT0;
++      return &priv->wstats;
++}
++
++
++/***********************************************************************
++*/
++static void
++acx100usb_i_set_rx_mode(struct net_device *dev)
++{
++}
++
++
++/***********************************************************************
++*/
++#ifdef HAVE_TX_TIMEOUT
++static void
++acx100usb_i_tx_timeout(struct net_device *dev)
++{
++      wlandevice_t *priv = netdev_priv(dev);
++      unsigned long flags;
++      int i;
++
++      FN_ENTER;
++
++      acx_lock(priv, flags);
++      /* unlink the URBs */
++      for (i = 0; i < ACX100_USB_NUM_BULK_URBS; i++) {
++              if (priv->usb_tx[i].urb->status == -EINPROGRESS)
++                      usb_unlink_urb(priv->usb_tx[i].urb);
++      }
++      /* TODO: stats update */
++      acx_unlock(priv, 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)
++{
++      acxlog(L_INIT, "USB module " WLAN_RELEASE " initialized, "
++              "probing for devices...\n");
++      return usb_register(&acx100usb_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(&acx100usb_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, 8)
++      /* halted removed in 2.6.9-rc1 */
++      /* DOH, Canbreak... err... Mandrake decided to do their very own very
++       * special version "2.6.8.1" which already includes this change, so we
++       * need to blacklist that version already (i.e. 2.6.8) */
++      printk("  halted[0]: 0x%X  halted[1]: 0x%X\n", usbdev->halted[0], usbdev->halted[1]);
++#endif
++#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)
++              printk("%d ", usbdev->ep_in[i]->desc.wMaxPacketSize);
++      printk("\n");
++      printk("  ep_out wMaxPacketSize: ");
++      for (i = 0; i < 15; ++i)
++              printk("%d ", 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);
++#if 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 */
+diff -Naur linux-2.6.14-omap2/drivers/net/wireless/tiacx/wlan.c linux-h6300-omap2-2.6.14.3/drivers/net/wireless/tiacx/wlan.c
+--- linux-2.6.14-omap2/drivers/net/wireless/tiacx/wlan.c       1970-01-01 02:00:00.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/drivers/net/wireless/tiacx/wlan.c       2005-09-28 23:54:23.000000000 +0300
+@@ -0,0 +1,392 @@
++/***********************************************************************
++** 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/config.h>
++#include <linux/version.h>
++
++#include <linux/types.h>
++#include <linux/if_arp.h>
++#include <linux/wireless.h>
++#if WIRELESS_EXT >= 13
++#include <net/iw_handler.h>
++#endif
++
++#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_NONERP:
++              /* was seen from WRT54GS with OpenWrt: 2F 01 07 */
++              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);
++}
++
++
++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);
++      }
++}
++
++
++/* 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;
++              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 */
++}
+diff -Naur linux-2.6.14-omap2/drivers/net/wireless/tiacx/wlan_compat.h linux-h6300-omap2-2.6.14.3/drivers/net/wireless/tiacx/wlan_compat.h
+--- linux-2.6.14-omap2/drivers/net/wireless/tiacx/wlan_compat.h        1970-01-01 02:00:00.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/drivers/net/wireless/tiacx/wlan_compat.h        2005-09-28 23:54:23.000000000 +0300
+@@ -0,0 +1,297 @@
++/***********************************************************************
++** 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_ATTRIB_PACK__          __attribute__ ((packed))
++#define __WLAN_PRAGMA_PACK1__
++#define __WLAN_PRAGMA_PACKDFLT__
++
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,38))
++ typedef struct device netdevice_t;
++#elif (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,4))
++ typedef struct net_device netdevice_t;
++#else
++ #undef netdevice_t
++ typedef struct net_device netdevice_t;
++#endif
++
++#ifdef WIRELESS_EXT
++#if (WIRELESS_EXT < 13)
++struct iw_request_info {
++      __u16 cmd;              /* Wireless Extension command */
++      __u16 flags;            /* More to come ;-) */
++};
++#endif
++#endif
++
++/* Interrupt handler backwards compatibility stuff */
++#ifndef IRQ_NONE
++#define IRQ_NONE
++#define IRQ_HANDLED
++typedef void irqreturn_t;
++#endif
++
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,41)  /* more or less */
++#define WLAN_MOD_INC_USE_COUNT        MOD_INC_USE_COUNT
++#define WLAN_MOD_DEC_USE_COUNT        MOD_DEC_USE_COUNT
++#else
++#define WLAN_MOD_INC_USE_COUNT
++#define WLAN_MOD_DEC_USE_COUNT
++#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
++/* unused
++#define WLAN_ETHHDR_LEN       14
++#define WLAN_ETHCONV_ENCAP    1
++#define WLAN_ETHCONV_RFC1042  2
++#define WLAN_ETHCONV_8021h    3
++#define WLAN_MIN_ETHFRM_LEN   60
++#define WLAN_MAX_ETHFRM_LEN   1514
++*/
++
++/*============================================================================*
++ * Types                                                                      *
++ *============================================================================*/
++
++/* local ether header type */
++typedef struct wlan_ethhdr {
++      u8      daddr[ETH_ALEN] __WLAN_ATTRIB_PACK__;
++      u8      saddr[ETH_ALEN] __WLAN_ATTRIB_PACK__;
++      u16     type __WLAN_ATTRIB_PACK__;
++} wlan_ethhdr_t;
++
++/* local llc header type */
++typedef struct wlan_llc {
++      u8      dsap __WLAN_ATTRIB_PACK__;
++      u8      ssap __WLAN_ATTRIB_PACK__;
++      u8      ctl __WLAN_ATTRIB_PACK__;
++} wlan_llc_t;
++
++/* local snap header type */
++typedef struct wlan_snap {
++      u8      oui[WLAN_IEEE_OUI_LEN] __WLAN_ATTRIB_PACK__;
++      u16     type __WLAN_ATTRIB_PACK__;
++} wlan_snap_t;
+diff -Naur linux-2.6.14-omap2/drivers/net/wireless/tiacx/wlan_hdr.h linux-h6300-omap2-2.6.14.3/drivers/net/wireless/tiacx/wlan_hdr.h
+--- linux-2.6.14-omap2/drivers/net/wireless/tiacx/wlan_hdr.h   1970-01-01 02:00:00.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/drivers/net/wireless/tiacx/wlan_hdr.h   2005-09-28 23:54:23.000000000 +0300
+@@ -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     */
++/*    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 __WLAN_ATTRIB_PACK__;
++      u16     dur __WLAN_ATTRIB_PACK__;
++      u8      a1[ETH_ALEN] __WLAN_ATTRIB_PACK__;
++      u8      a2[ETH_ALEN] __WLAN_ATTRIB_PACK__;
++      u8      a3[ETH_ALEN] __WLAN_ATTRIB_PACK__;
++      u16     seq __WLAN_ATTRIB_PACK__;
++      u8      a4[ETH_ALEN] __WLAN_ATTRIB_PACK__;
++} wlan_hdr_t;
++
++/* Separate structs for use if frame type is known */
++typedef struct wlan_hdr_a3 {
++      u16     fc __WLAN_ATTRIB_PACK__;
++      u16     dur __WLAN_ATTRIB_PACK__;
++      u8      a1[ETH_ALEN] __WLAN_ATTRIB_PACK__;
++      u8      a2[ETH_ALEN] __WLAN_ATTRIB_PACK__;
++      u8      a3[ETH_ALEN] __WLAN_ATTRIB_PACK__;
++      u16     seq __WLAN_ATTRIB_PACK__;
++} wlan_hdr_a3_t;
++
++typedef struct wlan_hdr_mgmt {
++      u16     fc __WLAN_ATTRIB_PACK__;
++      u16     dur __WLAN_ATTRIB_PACK__;
++      u8      da[ETH_ALEN] __WLAN_ATTRIB_PACK__;
++      u8      sa[ETH_ALEN] __WLAN_ATTRIB_PACK__;
++      u8      bssid[ETH_ALEN] __WLAN_ATTRIB_PACK__;
++      u16     seq __WLAN_ATTRIB_PACK__;
++} wlan_hdr_mgmt_t;
++
++#ifdef NOT_NEEDED_YET
++typedef struct { /* ad-hoc peer->peer (to/from DS = 0/0) */
++      u16     fc __WLAN_ATTRIB_PACK__;
++      u16     dur __WLAN_ATTRIB_PACK__;
++      u8      da[ETH_ALEN] __WLAN_ATTRIB_PACK__;
++      u8      sa[ETH_ALEN] __WLAN_ATTRIB_PACK__;
++      u8      bssid[ETH_ALEN] __WLAN_ATTRIB_PACK__;
++      u16     seq __WLAN_ATTRIB_PACK__;
++} ibss;
++typedef struct { /* ap->sta (to/from DS = 0/1) */
++      u16     fc __WLAN_ATTRIB_PACK__;
++      u16     dur __WLAN_ATTRIB_PACK__;
++      u8      da[ETH_ALEN] __WLAN_ATTRIB_PACK__;
++      u8      bssid[ETH_ALEN] __WLAN_ATTRIB_PACK__;
++      u8      sa[ETH_ALEN] __WLAN_ATTRIB_PACK__;
++      u16     seq __WLAN_ATTRIB_PACK__;
++} fromap;
++typedef struct { /* sta->ap (to/from DS = 1/0) */
++      u16     fc __WLAN_ATTRIB_PACK__;
++      u16     dur __WLAN_ATTRIB_PACK__;
++      u8      bssid[ETH_ALEN] __WLAN_ATTRIB_PACK__;
++      u8      sa[ETH_ALEN] __WLAN_ATTRIB_PACK__;
++      u8      da[ETH_ALEN] __WLAN_ATTRIB_PACK__;
++      u16     seq __WLAN_ATTRIB_PACK__;
++} toap;
++typedef struct { /* wds->wds (to/from DS = 1/1), the only 4addr pkt */
++      u16     fc __WLAN_ATTRIB_PACK__;
++      u16     dur __WLAN_ATTRIB_PACK__;
++      u8      ra[ETH_ALEN] __WLAN_ATTRIB_PACK__;
++      u8      ta[ETH_ALEN] __WLAN_ATTRIB_PACK__;
++      u8      da[ETH_ALEN] __WLAN_ATTRIB_PACK__;
++      u16     seq __WLAN_ATTRIB_PACK__;
++      u8      sa[ETH_ALEN] __WLAN_ATTRIB_PACK__;
++} wds;
++typedef struct { /* all management packets */
++      u16     fc __WLAN_ATTRIB_PACK__;
++      u16     dur __WLAN_ATTRIB_PACK__;
++      u8      da[ETH_ALEN] __WLAN_ATTRIB_PACK__;
++      u8      sa[ETH_ALEN] __WLAN_ATTRIB_PACK__;
++      u8      bssid[ETH_ALEN] __WLAN_ATTRIB_PACK__;
++      u16     seq __WLAN_ATTRIB_PACK__;
++} mgmt;
++typedef struct { /* has no body, just a FCS */
++      u16     fc __WLAN_ATTRIB_PACK__;
++      u16     dur __WLAN_ATTRIB_PACK__;
++      u8      ra[ETH_ALEN] __WLAN_ATTRIB_PACK__;
++      u8      ta[ETH_ALEN] __WLAN_ATTRIB_PACK__;
++} rts;
++typedef struct { /* has no body, just a FCS */
++      u16     fc __WLAN_ATTRIB_PACK__;
++      u16     dur __WLAN_ATTRIB_PACK__;
++      u8      ra[ETH_ALEN] __WLAN_ATTRIB_PACK__;
++} cts;
++typedef struct { /* has no body, just a FCS */
++      u16     fc __WLAN_ATTRIB_PACK__;
++      u16     dur __WLAN_ATTRIB_PACK__;
++      u8      ra[ETH_ALEN] __WLAN_ATTRIB_PACK__;
++} ack;
++typedef struct { /* has no body, just a FCS */
++      u16     fc __WLAN_ATTRIB_PACK__;
++      /* NB: this one holds Assoc ID in dur field: */
++      u16     aid __WLAN_ATTRIB_PACK__;
++      u8      bssid[ETH_ALEN] __WLAN_ATTRIB_PACK__;
++      u8      ta[ETH_ALEN] __WLAN_ATTRIB_PACK__;
++} pspoll;
++typedef struct { /* has no body, just a FCS */
++      u16     fc __WLAN_ATTRIB_PACK__;
++      u16     dur __WLAN_ATTRIB_PACK__;
++      u8      ra[ETH_ALEN] __WLAN_ATTRIB_PACK__;
++      u8      bssid[ETH_ALEN] __WLAN_ATTRIB_PACK__;
++} cfend;
++typedef struct { /* has no body, just a FCS */
++      u16     fc __WLAN_ATTRIB_PACK__;
++      u16     dur __WLAN_ATTRIB_PACK__;
++      u8      ra[ETH_ALEN] __WLAN_ATTRIB_PACK__;
++      u8      bssid[ETH_ALEN] __WLAN_ATTRIB_PACK__;
++} cfendcfack;
++#endif
++
++/* Prism header emulation (monitor mode) */
++typedef struct wlanitem_u32 {
++      u32     did __WLAN_ATTRIB_PACK__;
++      u16     status __WLAN_ATTRIB_PACK__;
++      u16     len __WLAN_ATTRIB_PACK__;
++      u32     data __WLAN_ATTRIB_PACK__;
++} 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 __WLAN_ATTRIB_PACK__;
++      u32             msglen __WLAN_ATTRIB_PACK__;
++      u8              devname[WLAN_DEVNAMELEN_MAX] __WLAN_ATTRIB_PACK__;
++      wlanitem_u32_t  hosttime __WLAN_ATTRIB_PACK__;
++      wlanitem_u32_t  mactime __WLAN_ATTRIB_PACK__;
++      wlanitem_u32_t  channel __WLAN_ATTRIB_PACK__;
++      wlanitem_u32_t  rssi __WLAN_ATTRIB_PACK__;
++      wlanitem_u32_t  sq __WLAN_ATTRIB_PACK__;
++      wlanitem_u32_t  signal __WLAN_ATTRIB_PACK__;
++      wlanitem_u32_t  noise __WLAN_ATTRIB_PACK__;
++      wlanitem_u32_t  rate __WLAN_ATTRIB_PACK__;
++      wlanitem_u32_t  istx __WLAN_ATTRIB_PACK__;      /* tx? 0:no 1:yes */
++      wlanitem_u32_t  frmlen __WLAN_ATTRIB_PACK__;
++} 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
+diff -Naur linux-2.6.14-omap2/drivers/net/wireless/tiacx/wlan_mgmt.h linux-h6300-omap2-2.6.14.3/drivers/net/wireless/tiacx/wlan_mgmt.h
+--- linux-2.6.14-omap2/drivers/net/wireless/tiacx/wlan_mgmt.h  1970-01-01 02:00:00.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/drivers/net/wireless/tiacx/wlan_mgmt.h  2005-09-28 23:54:23.000000000 +0300
+@@ -0,0 +1,579 @@
++/***********************************************************************
++** 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_ERP_INFO     42
++#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_GENERIC      221
++
++#if 0
++#define WLAN_EID_PWR_CONSTRAINT               32      /* 11H PowerConstraint */
++#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 __WLAN_ATTRIB_PACK__;
++      u8 len __WLAN_ATTRIB_PACK__;
++} wlan_ie_t;
++
++/*-- Service Set Identity (SSID)  -----------------*/
++typedef struct wlan_ie_ssid {
++      u8 eid __WLAN_ATTRIB_PACK__;
++      u8 len __WLAN_ATTRIB_PACK__;
++      u8 ssid[1] __WLAN_ATTRIB_PACK__;        /* may be zero */
++} wlan_ie_ssid_t;
++
++/*-- Supported Rates  -----------------------------*/
++typedef struct wlan_ie_supp_rates {
++      u8 eid __WLAN_ATTRIB_PACK__;
++      u8 len __WLAN_ATTRIB_PACK__;
++      u8 rates[1] __WLAN_ATTRIB_PACK__;       /* had better be at LEAST one! */
++} wlan_ie_supp_rates_t;
++
++/*-- FH Parameter Set  ----------------------------*/
++typedef struct wlan_ie_fh_parms {
++      u8 eid __WLAN_ATTRIB_PACK__;
++      u8 len __WLAN_ATTRIB_PACK__;
++      u16 dwell __WLAN_ATTRIB_PACK__;
++      u8 hopset __WLAN_ATTRIB_PACK__;
++      u8 hoppattern __WLAN_ATTRIB_PACK__;
++      u8 hopindex __WLAN_ATTRIB_PACK__;
++} wlan_ie_fh_parms_t;
++
++/*-- DS Parameter Set  ----------------------------*/
++typedef struct wlan_ie_ds_parms {
++      u8 eid __WLAN_ATTRIB_PACK__;
++      u8 len __WLAN_ATTRIB_PACK__;
++      u8 curr_ch __WLAN_ATTRIB_PACK__;
++} wlan_ie_ds_parms_t;
++
++/*-- CF Parameter Set  ----------------------------*/
++typedef struct wlan_ie_cf_parms {
++      u8 eid __WLAN_ATTRIB_PACK__;
++      u8 len __WLAN_ATTRIB_PACK__;
++      u8 cfp_cnt __WLAN_ATTRIB_PACK__;
++      u8 cfp_period __WLAN_ATTRIB_PACK__;
++      u16 cfp_maxdur __WLAN_ATTRIB_PACK__;
++      u16 cfp_durremaining __WLAN_ATTRIB_PACK__;
++} wlan_ie_cf_parms_t;
++
++/*-- TIM ------------------------------------------*/
++typedef struct wlan_ie_tim {
++      u8 eid __WLAN_ATTRIB_PACK__;
++      u8 len __WLAN_ATTRIB_PACK__;
++      u8 dtim_cnt __WLAN_ATTRIB_PACK__;
++      u8 dtim_period __WLAN_ATTRIB_PACK__;
++      u8 bitmap_ctl __WLAN_ATTRIB_PACK__;
++      u8 virt_bm[1] __WLAN_ATTRIB_PACK__;
++} wlan_ie_tim_t;
++
++/*-- IBSS Parameter Set ---------------------------*/
++typedef struct wlan_ie_ibss_parms {
++      u8 eid __WLAN_ATTRIB_PACK__;
++      u8 len __WLAN_ATTRIB_PACK__;
++      u16 atim_win __WLAN_ATTRIB_PACK__;
++} wlan_ie_ibss_parms_t;
++
++/*-- Challenge Text  ------------------------------*/
++typedef struct wlan_ie_challenge {
++      u8 eid __WLAN_ATTRIB_PACK__;
++      u8 len __WLAN_ATTRIB_PACK__;
++      u8 challenge[1] __WLAN_ATTRIB_PACK__;
++} wlan_ie_challenge_t;
++
++/*-- ERP (42) -------------------------------------*/
++typedef struct wlan_ie_erp {
++      u8 eid __WLAN_ATTRIB_PACK__;
++      u8 len __WLAN_ATTRIB_PACK__;
++      /* bit 0:Non ERP present
++      **     1:Use Protection
++      **     2:Barker Preamble mode
++      **     3-7:reserved */
++      u8 erp __WLAN_ATTRIB_PACK__;
++} 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_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 __WLAN_ATTRIB_PACK__;
++      u16     auth_seq __WLAN_ATTRIB_PACK__;
++      u16     status __WLAN_ATTRIB_PACK__;
++      wlan_ie_challenge_t challenge __WLAN_ATTRIB_PACK__;
++} auth_frame_body_t;
++
++typedef struct assocresp_frame_body {
++      u16     cap_info __WLAN_ATTRIB_PACK__;
++      u16     status __WLAN_ATTRIB_PACK__;
++      u16     aid __WLAN_ATTRIB_PACK__;
++      wlan_ie_supp_rates_t rates __WLAN_ATTRIB_PACK__;
++} assocresp_frame_body_t;
++
++typedef struct reassocreq_frame_body {
++      u16     cap_info __WLAN_ATTRIB_PACK__;
++      u16     listen_int __WLAN_ATTRIB_PACK__;
++      u8      current_ap[ETH_ALEN] __WLAN_ATTRIB_PACK__;
++      wlan_ie_ssid_t ssid __WLAN_ATTRIB_PACK__;
++/* access to this one is disabled since ssid_t is variable length: */
++     /* wlan_ie_supp_rates_t rates __WLAN_ATTRIB_PACK__; */
++} reassocreq_frame_body_t;
++
++typedef struct reassocresp_frame_body {
++      u16     cap_info __WLAN_ATTRIB_PACK__;
++      u16     status __WLAN_ATTRIB_PACK__;
++      u16     aid __WLAN_ATTRIB_PACK__;
++      wlan_ie_supp_rates_t rates __WLAN_ATTRIB_PACK__;
++} reassocresp_frame_body_t;
++
++typedef struct deauthen_frame_body {
++      u16     reason __WLAN_ATTRIB_PACK__;
++} deauthen_frame_body_t;
++
++typedef struct disassoc_frame_body {
++      u16     reason __WLAN_ATTRIB_PACK__;
++} disassoc_frame_body_t;
++
++typedef struct probereq_frame_body {
++      wlan_ie_ssid_t ssid __WLAN_ATTRIB_PACK__;
++      wlan_ie_supp_rates_t rates __WLAN_ATTRIB_PACK__;
++} probereq_frame_body_t;
++
++typedef struct proberesp_frame_body {
++      u8      timestamp[8] __WLAN_ATTRIB_PACK__;
++      u16     beacon_int __WLAN_ATTRIB_PACK__;
++      u16     cap_info __WLAN_ATTRIB_PACK__;
++      wlan_ie_ssid_t ssid __WLAN_ATTRIB_PACK__;
++/* access to these is disabled since ssid_t is variable length: */
++     /* wlan_ie_supp_rates_t rates __WLAN_ATTRIB_PACK__; */
++     /* fhps_t        fhps __WLAN_ATTRIB_PACK__; */
++     /* dsps_t        dsps __WLAN_ATTRIB_PACK__; */
++     /* cfps_t        cfps __WLAN_ATTRIB_PACK__; */
++} 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;
++}
+diff -Naur linux-2.6.14-omap2/drivers/ssi/omap-tsc2101.c linux-h6300-omap2-2.6.14.3/drivers/ssi/omap-tsc2101.c
+--- linux-2.6.14-omap2/drivers/ssi/omap-tsc2101.c      2005-12-02 01:53:33.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/drivers/ssi/omap-tsc2101.c      2005-10-22 03:52:45.000000000 +0300
+@@ -36,10 +36,11 @@
+ #include <asm/arch/hardware.h>
+ #include <asm/hardware/tsc2101.h>
+ #include <asm/arch/gpioexpander.h>
++#include <asm/arch/gpio.h>
+ #include "omap-tsc2101.h"
+-#if CONFIG_ARCH_OMAP16XX
++#if CONFIG_ARCH_OMAP1
+ #include <../drivers/ssi/omap-uwire.h>
+ #else
+ #error "Unsupported configuration"
+@@ -66,27 +67,28 @@
+       if (count++ == 0) {
+               int ret = 0;
+               /* set the Mux to provide MCLK to TSC2101 */
+-              if (machine_is_omap_h3()) {
++              if (machine_is_omap_h3())
+                       ret = omap_cfg_reg(V5_1710_MCLK_ON);
+-              } else {
+-                      if (machine_is_omap_h2()) {
+-                              ret = omap_cfg_reg(R10_1610_MCLK_ON);
++              else if (machine_is_omap_h2())
++                      ret = omap_cfg_reg(R10_1610_MCLK_ON);
++              else if (machine_is_h6300 ())
++                      ret = omap_cfg_reg(R10_1510_MCLK_ON);
++
++              if (!cpu_is_omap1510 ()) {
++                      /* Get the MCLK */
++                      tsc2101_mclk_ck = clk_get(NULL, "mclk");
++                      if (NULL == tsc2101_mclk_ck) {
++                              printk(KERN_ERR "Unable to get the clock MCLK!!!\n");;
++                              ret = -EPERM;
++                              goto done;
+                       }
+-              }
+-
+-              /* Get the MCLK */
+-              tsc2101_mclk_ck = clk_get(NULL, "mclk");
+-              if (NULL == tsc2101_mclk_ck) {
+-                      printk(KERN_ERR "Unable to get the clock MCLK!!!\n");;
+-                      ret = -EPERM;
+-                      goto done;
+-              }
+-              if (clk_set_rate(tsc2101_mclk_ck, 12000000)) {
+-                      printk(KERN_ERR "Unable to set rate to the MCLK!!!\n");;
+-                      ret = -EPERM;
+-                      goto done;
+-              }
+-              clk_enable(tsc2101_mclk_ck);
++                      if (clk_set_rate(tsc2101_mclk_ck, 12000000)) {
++                              printk(KERN_ERR "Unable to set rate to the MCLK!!!\n");;
++                              ret = -EPERM;
++                              goto done;
++                      }
++                      clk_enable(tsc2101_mclk_ck);
++              } /* if (!cpu_is_omap1510 ()) */
+               ret = omap_tsc2101_configure();
+@@ -116,10 +118,16 @@
+                       }
+               }
+-              /* Release the MCLK */
+-              clk_disable(tsc2101_mclk_ck);
+-              clk_put(tsc2101_mclk_ck);
+-              tsc2101_mclk_ck = NULL;
++              if (!cpu_is_omap1510 ()) {
++                      /* Release the MCLK */
++                      clk_disable(tsc2101_mclk_ck);
++                      clk_put(tsc2101_mclk_ck);
++                      tsc2101_mclk_ck = NULL;
++              }
++
++#if defined(CONFIG_MACH_OMAP_H6300)
++              omap_free_gpio(8);
++#endif
+               module_put(THIS_MODULE);
+       }
+@@ -150,7 +158,10 @@
+                       return;
+               }
+       }
+-      if (machine_is_omap_h3()) {
++      if (machine_is_omap_h3() || machine_is_h6300 ()) {
++
++              if (machine_is_h6300 ())
++                      omap_set_gpio_dataout (8, 0);
+               ret =
+                   omap_uwire_data_transfer(0, ((page << 11) | (address << 5)),
+@@ -159,6 +170,8 @@
+                       printk(KERN_ERR
+                              "uwire-write returned error for address %x\n",
+                              address);
++              if (machine_is_h6300 ())
++                      omap_set_gpio_dataout (8, 1);
+                       return;
+               }
+               ret = omap_uwire_data_transfer(0, data, 16, 0, NULL, 0);
+@@ -166,10 +179,14 @@
+                       printk(KERN_ERR
+                              "uwire-write returned error for address %x\n",
+                              address);
++                      if (machine_is_h6300 ())
++                              omap_set_gpio_dataout (8, 1);
+                       return;
+               }
+-      }
++              if (machine_is_h6300 ())
++                      omap_set_gpio_dataout (8, 1);
++      }
+ }
+ void omap_tsc2101_reads(int page, u8 startaddress, u16 * data, int numregs)
+@@ -178,9 +195,13 @@
+       if (machine_is_omap_h2()) {
+               cs = 1;
+       }
+-      if (machine_is_omap_h3()) {
++      if (machine_is_omap_h3() || machine_is_h6300 ()) {
+               cs = 0;
+       }
++
++      if (machine_is_h6300 ())
++              omap_set_gpio_dataout(8, 0);
++
+       (void)omap_uwire_data_transfer(cs, (0x8000 | (page << 11)
+                                           | (startaddress << 5)),
+                                      16, 0, NULL, 1);
+@@ -188,6 +209,9 @@
+               omap_uwire_data_transfer(cs, 0, 0, 16, data, 1);
+       }
+       omap_uwire_data_transfer(cs, 0, 0, 16, data, 0);
++
++      if (machine_is_h6300 ())
++              omap_set_gpio_dataout(8, 1);
+ }
+ u16 omap_tsc2101_read(int page, u8 address)
+@@ -228,9 +252,24 @@
+               omap_cfg_reg(N14_1610_UWIRE_CS0);
+               omap_uwire_configure_mode(0, uwire_flags);
+       }
++      if (machine_is_h6300()) {
++              uwire_flags = UWIRE_READ_RISING_EDGE | UWIRE_WRITE_RISING_EDGE;
++              omap_cfg_reg(N14_1510_UWIRE_CS0);
++              omap_uwire_configure_mode(0, uwire_flags);
++
++              omap_request_gpio(8);
++              omap_set_gpio_dataout(8, 0);
++              omap_set_gpio_direction (8, 0);
++      }
+       /* Configure MCLK enable */
+-      omap_writel(omap_readl(PU_PD_SEL_2) | (1 << 22), PU_PD_SEL_2);  
++      if (cpu_is_omap16xx() || cpu_is_omap1710())
++              omap_writel(omap_readl(PU_PD_SEL_2) | (1 << 22), PU_PD_SEL_2);  
++      if (machine_is_h6300()) {
++              omap_cfg_reg(V19_1510_UWIRE_SCLK);
++              omap_cfg_reg(W21_1510_UWIRE_SDO);
++              omap_cfg_reg(U18_1510_UWIRE_SDI);
++      }
+       return 0;
+ }
+@@ -243,5 +282,5 @@
+ MODULE_AUTHOR("Texas Instruments");
+ MODULE_DESCRIPTION
+-    ("Glue audio driver for the TI OMAP1610/OMAP1710 TSC2101 codec.");
++    ("Glue audio driver for the TI OMAP1510/1610/OMAP1710 TSC2101 codec.");
+ MODULE_LICENSE("GPL");
+diff -Naur linux-2.6.14-omap2/drivers/ssi/omap-uwire.c linux-h6300-omap2-2.6.14.3/drivers/ssi/omap-uwire.c
+--- linux-2.6.14-omap2/drivers/ssi/omap-uwire.c        2005-12-02 01:53:33.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/drivers/ssi/omap-uwire.c        2005-08-12 13:46:22.000000000 +0300
+@@ -212,6 +212,10 @@
+               omap_cfg_reg(N14_1610_UWIRE_CS0);
+               omap_cfg_reg(P15_1610_UWIRE_CS3);
+       }
++      if (machine_is_h6300 ()) {
++              omap_cfg_reg(N14_1510_UWIRE_CS0);
++              omap_cfg_reg(P15_1510_UWIRE_CS3);
++      }
+       if (machine_is_omap_perseus2()) {
+               /* configure pins: MPU_UW_nSCS1, MPU_UW_SDO, MPU_UW_SCLK */
+               int val = omap_readl(OMAP730_IO_CONF_9) & ~0x00EEE000;
+diff -Naur linux-2.6.14-omap2/drivers/telephony/Kconfig linux-h6300-omap2-2.6.14.3/drivers/telephony/Kconfig
+--- linux-2.6.14-omap2/drivers/telephony/Kconfig       2005-10-28 03:02:08.000000000 +0300
++++ linux-h6300-omap2-2.6.14.3/drivers/telephony/Kconfig       2005-10-06 02:34:39.000000000 +0300
+@@ -41,7 +41,18 @@
+       help
+         Say Y here to configure in PCMCIA service support for the Quicknet
+         cards manufactured by Quicknet Technologies, Inc.  This changes the
+-        card initialization code to work with the card manager daemon.
++        card initialization code to work with the card manager daemon.          
++
++config GSM_H6300
++      tristate "H6300 P5186 GSM/GPRS DRIVER"
++      depends on PHONE && I2C && PCA9535
++      help
++        Bluetooth H6300 P5186 gsm/gprs driver.
++        This driver provides the firmware loading mechanism for the P5185
++        gsm/gprs hardware in iPAQ h6300.
++
++        Say Y here to compile support for P5186 gsm/gprs devices into the
++        kernel or say M to compile it as module (h6300_gsm).
+ endmenu
+diff -Naur linux-2.6.14-omap2/drivers/telephony/Makefile linux-h6300-omap2-2.6.14.3/drivers/telephony/Makefile
+--- linux-2.6.14-omap2/drivers/telephony/Makefile      2005-10-28 03:02:08.000000000 +0300
++++ linux-h6300-omap2-2.6.14.3/drivers/telephony/Makefile      2005-10-06 02:34:39.000000000 +0300
+@@ -2,6 +2,7 @@
+ # Makefile for drivers/telephony
+ #
+-obj-$(CONFIG_PHONE) += phonedev.o
+-obj-$(CONFIG_PHONE_IXJ) += ixj.o
+-obj-$(CONFIG_PHONE_IXJ_PCMCIA) += ixj_pcmcia.o
++obj-$(CONFIG_PHONE)                           += phonedev.o
++obj-$(CONFIG_PHONE_IXJ)                       += ixj.o
++obj-$(CONFIG_PHONE_IXJ_PCMCIA)        += ixj_pcmcia.o
++obj-$(CONFIG_GSM_H6300)                       += omap/
+diff -Naur linux-2.6.14-omap2/drivers/telephony/omap/h6300_gsm_led.c linux-h6300-omap2-2.6.14.3/drivers/telephony/omap/h6300_gsm_led.c
+--- linux-2.6.14-omap2/drivers/telephony/omap/h6300_gsm_led.c  1970-01-01 02:00:00.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/drivers/telephony/omap/h6300_gsm_led.c  2005-10-06 02:34:39.000000000 +0300
+@@ -0,0 +1,40 @@
++/* 
++ * GSM interface driver helper for controlling bluetooth leds available in iPAQ h6300.
++ * 
++ * Copyright (C) 2005 Mika Laitio  <lamikr@cc.jyu.fi>
++ * 
++ * This program is free software; you can 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/delay.h>
++#include <linux/device.h>
++
++#include <asm/hardware.h>
++#include <asm/arch/gpio.h>
++
++/* 
++ * Low level access for disabling h6300 gsm led.
++ *
++ * TODO: implement for h6300 
++ */
++void h6300_clear_gsm_led(int led_num)
++{
++      printk(KERN_NOTICE "h6300_gsm_led.c h6300_clear_gsm_led() done\n");
++      //hx4700_set_led(led_num, 0, 16);
++}
++EXPORT_SYMBOL(h6300_clear_gsm_led);
++
++/* 
++ * Low level access for setting up the gsm led.
++ *
++ * TODO: implement for h6300 
++ */
++void h6300_set_gsm_led(int led_num, int duty_time, int cycle_time)
++{
++      printk(KERN_NOTICE "h6300_gsm_led.c h6300_set_gsm_led() done\n");
++}
++EXPORT_SYMBOL(h6300_set_gsm_led);
+diff -Naur linux-2.6.14-omap2/drivers/telephony/omap/h6300_gsm_led.h linux-h6300-omap2-2.6.14.3/drivers/telephony/omap/h6300_gsm_led.h
+--- linux-2.6.14-omap2/drivers/telephony/omap/h6300_gsm_led.h  1970-01-01 02:00:00.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/drivers/telephony/omap/h6300_gsm_led.h  2005-10-06 02:34:39.000000000 +0300
+@@ -0,0 +1,10 @@
++#ifndef H6300_GSM_LED_H_
++#define H6300_GSM_LED_H_
++
++#define INDEX_GSM_LED 1
++
++void h6300_clear_gsm_led(int led_num);
++void h6300_set_gsm_led(int led_num, int duty_time, int cycle_time);
++
++
++#endif /*H6300_GSM_LED_H_*/
+diff -Naur linux-2.6.14-omap2/drivers/telephony/omap/h6300_gsm_p5186.c linux-h6300-omap2-2.6.14.3/drivers/telephony/omap/h6300_gsm_p5186.c
+--- linux-2.6.14-omap2/drivers/telephony/omap/h6300_gsm_p5186.c        1970-01-01 02:00:00.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/drivers/telephony/omap/h6300_gsm_p5186.c        2005-10-20 20:57:07.000000000 +0300
+@@ -0,0 +1,171 @@
++/* 
++ * Wavecom P5186 GPRS and GSM module driver for iPAQ h6300.
++ * 
++ * Copyright (C) 2005 Mika Laitio <lamikr@cc.jyu.fi>
++ * 
++ * This program is free software; you can 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/delay.h>
++#include <linux/device.h>
++
++#include <asm/hardware.h>
++#include <asm/arch/gpio.h>
++
++#include <asm/arch/pca9535.h>
++#include <asm/arch/h6300_uart_info.h>
++#include "h6300_gsm_led.h"
++
++static void
++h6300_gsm_configure(struct uart_omap_port *up, int enable)
++{
++      printk(KERN_NOTICE "h6300_gsm_p5186.c h6300_gsm_configure() started, enable = %d\n", enable);
++      
++      // printk( KERN_NOTICE "h6300 configure bluetooth: %d\n", enable );
++      if (enable == 0) {
++              pca9535_gpio_write(GPIO_I2C_GPRS_RESET, GPIO_VALUE_OFF);        // turn off gpio
++              mdelay(5);
++              h6300_clear_gsm_led(INDEX_GSM_LED);
++      }
++      else if (enable == 1) {
++              pca9535_gpio_write(GPIO_I2C_GPRS_RESET, GPIO_VALUE_ON); // turn on gpio
++              mdelay(5);                              
++      }
++      else if (enable == 2) {
++              h6300_set_gsm_led(INDEX_GSM_LED, 16, 16);
++      }
++      printk(KERN_NOTICE "h6300_gsm_p5186.c h6300_gsm_configure() done\n");
++}
++
++static void
++h6300_gsm_set_txrx(struct uart_omap_port *up, int txrx)
++{
++      printk(KERN_NOTICE "h6300_gsm_p5186.c h6300_gsm_set_txrx(), txrx = %d done\n", txrx);
++      /* do nothing */
++}
++
++static int
++h6300_gsm_get_txrx(struct uart_omap_port *up)
++{
++      printk(KERN_NOTICE "h6300_gsm_p5186.c h6300_gsm_get_txrx() done\n");
++      /* do nothing */
++      return 0;
++}
++
++static int
++h6300_gsm_probe(struct device *dev)
++{
++      int     ii;
++      int     curVal;
++      
++      struct h6300_uart_funcs *funcs = (struct h6300_uart_funcs *)dev->platform_data;
++/*
++      printk(KERN_NOTICE "h6300_gsm_p5186.c h6300_gsm_probe() started\n");    
++      for (ii = 0; ii < 8; ii++)
++      {
++              curVal  = pca9535_gpio_read(ii);
++              printk(KERN_NOTICE "I2C[%d] = %d ", ii, curVal);
++      }
++      for (ii = 10; ii < 18; ii++)
++      {
++              curVal  = pca9535_gpio_read(ii);
++              printk(KERN_NOTICE "I2C[%d] = %d ", ii, curVal);
++      }
++      printk(KERN_NOTICE "\nfirst check done\n");
++*/
++      pca9535_gpio_direction(GPIO_I2C_GPRS_RESET, GPIO_DIR_OUTPUT);   // set gpio direction to be output
++      pca9535_gpio_write(GPIO_I2C_GPRS_RESET, GPIO_VALUE_ON); // turn on gpio
++      mdelay(200);
++      
++      pca9535_gpio_direction(GPIO_I2C_MIC_OP_EN, GPIO_DIR_OUTPUT);    // set gpio direction to be output
++      pca9535_gpio_write(GPIO_I2C_MIC_OP_EN, GPIO_VALUE_ON);  // turn on gpio
++      mdelay(200);
++
++      pca9535_gpio_direction(GPIO_I2C_SPK_OP_PD, GPIO_DIR_OUTPUT);    // set gpio direction to be output
++      pca9535_gpio_write(GPIO_I2C_SPK_OP_PD, GPIO_VALUE_ON);  // pd = pulldown?, normal off = on
++
++      mdelay(200);
++      
++      //pca9535_gpio_direction(
++      /* configure bluetooth UART */
++      //h6300_gpio_mode(GPIO_NR_H6300_BT_RXD_MD);
++      //h6300_gpio_mode(GPIO_NR_H6300_BT_TXD_MD);
++      //h6300_gpio_mode(GPIO_NR_H6300_BT_UART_CTS_MD);
++      //h6300_gpio_mode(GPIO_NR_H6300_BT_UART_RTS_MD);
++
++      funcs->configure        = h6300_gsm_configure;
++      funcs->set_txrx         = h6300_gsm_set_txrx;
++      funcs->get_txrx         = h6300_gsm_get_txrx;
++
++      /* Make sure the LED is off */
++      h6300_clear_gsm_led(INDEX_GSM_LED);     
++/*    
++      for (ii = 0; ii < 8; ii++)
++      {
++              curVal  = pca9535_gpio_read(ii);
++              printk(KERN_NOTICE "I2C[%d] = %d ", ii, curVal);
++      }
++      for (ii = 10; ii < 18; ii++)
++      {
++              curVal  = pca9535_gpio_read(ii);
++              printk(KERN_NOTICE "I2C[%d] = %d ", ii, curVal);
++      }
++*/    
++      printk(KERN_NOTICE "\nh6300_gsm_p5186.c h6300_gsm_probe() done\n");
++              
++      return 0;
++}
++
++static int
++h6300_gsm_remove(struct device *dev)
++{
++      struct h6300_uart_funcs *funcs = (struct h6300_uart_funcs *)dev->platform_data;
++      
++      printk(KERN_NOTICE "h6300_gsm_p5186.c h6300_gsm_remove() started\n");   
++
++      pca9535_gpio_write(GPIO_I2C_GPRS_RESET, 0);     // turn off gpio
++      
++      funcs->configure        = NULL;
++      funcs->set_txrx         = NULL;
++      funcs->get_txrx         = NULL;
++
++      /* Make sure the LED is off */
++      h6300_clear_gsm_led(INDEX_GSM_LED);
++      
++      printk(KERN_NOTICE "h6300_gsm_p5186.c, h6300_gsm_remove() done\n");
++
++      return 0;
++}
++
++static struct device_driver gsm_driver = {
++      .name     = "h6300_gsm",
++      .bus      = &platform_bus_type,
++      .probe    = h6300_gsm_probe,
++      .remove   = h6300_gsm_remove,
++};
++
++static int __init
++h6300_gsm_init(void)
++{
++      printk(KERN_NOTICE "h6300 GSM Driver init()\n");
++      return driver_register(&gsm_driver);
++}
++
++static void __exit
++h6300_gsm_exit(void)
++{
++      printk(KERN_NOTICE "h6300 GSM Driver exit()\n");
++      driver_unregister(&gsm_driver);
++}
++
++module_init(h6300_gsm_init);
++module_exit(h6300_gsm_exit);
++
++MODULE_AUTHOR("Mika Laitio, <lamikr@cc.jyu.fi>");
++MODULE_DESCRIPTION("iPAQ h6300 Wavecom P5186 GPRS and GSM module driver.");
++MODULE_LICENSE("GPL");
++
+diff -Naur linux-2.6.14-omap2/drivers/telephony/omap/Makefile linux-h6300-omap2-2.6.14.3/drivers/telephony/omap/Makefile
+--- linux-2.6.14-omap2/drivers/telephony/omap/Makefile 1970-01-01 02:00:00.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/drivers/telephony/omap/Makefile 2005-10-06 02:34:39.000000000 +0300
+@@ -0,0 +1,6 @@
++#
++# Makefile for the Linux iPAQ H6300 BRF6100 Bluetooth device drivers.
++#
++
++h6300_gsm-objs                        := h6300_gsm_led.o h6300_gsm_p5186.o
++obj-$(CONFIG_GSM_H6300)       += h6300_gsm.o
+diff -Naur linux-2.6.14-omap2/drivers/usb/core/sysfs.c linux-h6300-omap2-2.6.14.3/drivers/usb/core/sysfs.c
+--- linux-2.6.14-omap2/drivers/usb/core/sysfs.c        2005-10-28 03:02:08.000000000 +0300
++++ linux-h6300-omap2-2.6.14.3/drivers/usb/core/sysfs.c        2005-11-23 01:44:02.000000000 +0200
+@@ -292,30 +292,23 @@
+ {
+       struct usb_interface *intf;
+       struct usb_device *udev;
+-      int len;
++      struct usb_host_interface *alt;
+       intf = to_usb_interface(dev);
+       udev = interface_to_usbdev(intf);
++      alt = intf->cur_altsetting;
+-      len = sprintf(buf, "usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic",
+-                             le16_to_cpu(udev->descriptor.idVendor),
+-                             le16_to_cpu(udev->descriptor.idProduct),
+-                             le16_to_cpu(udev->descriptor.bcdDevice),
+-                             udev->descriptor.bDeviceClass,
+-                             udev->descriptor.bDeviceSubClass,
+-                             udev->descriptor.bDeviceProtocol);
+-      buf += len;
+-
+-      if (udev->descriptor.bDeviceClass == 0) {
+-              struct usb_host_interface *alt = intf->cur_altsetting;
+-
+-              return len + sprintf(buf, "%02Xisc%02Xip%02X\n",
+-                             alt->desc.bInterfaceClass,
+-                             alt->desc.bInterfaceSubClass,
+-                             alt->desc.bInterfaceProtocol);
+-      } else {
+-              return len + sprintf(buf, "*isc*ip*\n");
+-      }
++      return sprintf(buf, "usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02X"
++                      "ic%02Xisc%02Xip%02X\n",
++                      le16_to_cpu(udev->descriptor.idVendor),
++                      le16_to_cpu(udev->descriptor.idProduct),
++                      le16_to_cpu(udev->descriptor.bcdDevice),
++                      udev->descriptor.bDeviceClass,
++                      udev->descriptor.bDeviceSubClass,
++                      udev->descriptor.bDeviceProtocol,
++                      alt->desc.bInterfaceClass,
++                      alt->desc.bInterfaceSubClass,
++                      alt->desc.bInterfaceProtocol);
+ }
+ static DEVICE_ATTR(modalias, S_IRUGO, show_modalias, NULL);
+diff -Naur linux-2.6.14-omap2/drivers/usb/core/usb.c linux-h6300-omap2-2.6.14.3/drivers/usb/core/usb.c
+--- linux-2.6.14-omap2/drivers/usb/core/usb.c  2005-10-28 03:02:08.000000000 +0300
++++ linux-h6300-omap2-2.6.14.3/drivers/usb/core/usb.c  2005-11-23 01:44:02.000000000 +0200
+@@ -557,6 +557,7 @@
+ {
+       struct usb_interface *intf;
+       struct usb_device *usb_dev;
++      struct usb_host_interface *alt;
+       int i = 0;
+       int length = 0;
+@@ -573,7 +574,8 @@
+       intf = to_usb_interface(dev);
+       usb_dev = interface_to_usbdev (intf);
+-      
++      alt = intf->cur_altsetting;
++
+       if (usb_dev->devnum < 0) {
+               pr_debug ("usb %s: already deleted?\n", dev->bus_id);
+               return -ENODEV;
+@@ -615,46 +617,27 @@
+                               usb_dev->descriptor.bDeviceProtocol))
+               return -ENOMEM;
+-      if (usb_dev->descriptor.bDeviceClass == 0) {
+-              struct usb_host_interface *alt = intf->cur_altsetting;
++      if (add_hotplug_env_var(envp, num_envp, &i,
++                              buffer, buffer_size, &length,
++                              "INTERFACE=%d/%d/%d",
++                              alt->desc.bInterfaceClass,
++                              alt->desc.bInterfaceSubClass,
++                              alt->desc.bInterfaceProtocol))
++              return -ENOMEM;
+-              /* 2.4 only exposed interface zero.  in 2.5, hotplug
+-               * agents are called for all interfaces, and can use
+-               * $DEVPATH/bInterfaceNumber if necessary.
+-               */
+-              if (add_hotplug_env_var(envp, num_envp, &i,
+-                                      buffer, buffer_size, &length,
+-                                      "INTERFACE=%d/%d/%d",
+-                                      alt->desc.bInterfaceClass,
+-                                      alt->desc.bInterfaceSubClass,
+-                                      alt->desc.bInterfaceProtocol))
+-                      return -ENOMEM;
+-
+-              if (add_hotplug_env_var(envp, num_envp, &i,
+-                                      buffer, buffer_size, &length,
+-                                      "MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X",
+-                                      le16_to_cpu(usb_dev->descriptor.idVendor),
+-                                      le16_to_cpu(usb_dev->descriptor.idProduct),
+-                                      le16_to_cpu(usb_dev->descriptor.bcdDevice),
+-                                      usb_dev->descriptor.bDeviceClass,
+-                                      usb_dev->descriptor.bDeviceSubClass,
+-                                      usb_dev->descriptor.bDeviceProtocol,
+-                                      alt->desc.bInterfaceClass,
+-                                      alt->desc.bInterfaceSubClass,
+-                                      alt->desc.bInterfaceProtocol))
+-                      return -ENOMEM;
+-      } else {
+-              if (add_hotplug_env_var(envp, num_envp, &i,
+-                                      buffer, buffer_size, &length,
+-                                      "MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic*isc*ip*",
+-                                      le16_to_cpu(usb_dev->descriptor.idVendor),
+-                                      le16_to_cpu(usb_dev->descriptor.idProduct),
+-                                      le16_to_cpu(usb_dev->descriptor.bcdDevice),
+-                                      usb_dev->descriptor.bDeviceClass,
+-                                      usb_dev->descriptor.bDeviceSubClass,
+-                                      usb_dev->descriptor.bDeviceProtocol))
+-                      return -ENOMEM;
+-      }
++      if (add_hotplug_env_var(envp, num_envp, &i,
++                              buffer, buffer_size, &length,
++                              "MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X",
++                              le16_to_cpu(usb_dev->descriptor.idVendor),
++                              le16_to_cpu(usb_dev->descriptor.idProduct),
++                              le16_to_cpu(usb_dev->descriptor.bcdDevice),
++                              usb_dev->descriptor.bDeviceClass,
++                              usb_dev->descriptor.bDeviceSubClass,
++                              usb_dev->descriptor.bDeviceProtocol,
++                              alt->desc.bInterfaceClass,
++                              alt->desc.bInterfaceSubClass,
++                              alt->desc.bInterfaceProtocol))
++              return -ENOMEM;
+       envp[i] = NULL;
+diff -Naur linux-2.6.14-omap2/drivers/usb/gadget/omap_udc.c linux-h6300-omap2-2.6.14.3/drivers/usb/gadget/omap_udc.c
+--- linux-2.6.14-omap2/drivers/usb/gadget/omap_udc.c   2005-12-02 01:53:33.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/drivers/usb/gadget/omap_udc.c   2005-11-11 04:13:42.000000000 +0200
+@@ -59,7 +59,8 @@
+ #undef        USB_TRACE
+ /* bulk DMA seems to be behaving for both IN and OUT */
+-#define       USE_DMA
++//#define     USE_DMA
++#undef USE_DMA
+ /* ISO too */
+ #define       USE_ISO
+@@ -2109,7 +2110,7 @@
+       /* boards that don't have VBUS sensing can't autogate 48MHz;
+        * can't enter deep sleep while a gadget driver is active.
+        */
+-      if (machine_is_omap_innovator() || machine_is_omap_osk())
++      if (machine_is_omap_innovator() || machine_is_omap_osk() || machine_is_h6300())
+               omap_vbus_session(&udc->gadget, 1);
+ done:
+@@ -2127,7 +2128,7 @@
+       if (!driver || driver != udc->driver)
+               return -EINVAL;
+-      if (machine_is_omap_innovator() || machine_is_omap_osk())
++      if (machine_is_omap_innovator() || machine_is_omap_osk() || machine_is_h6300())
+               omap_vbus_session(&udc->gadget, 0);
+       if (udc->transceiver)
+@@ -2735,7 +2736,7 @@
+               hmc = HMC_1510;
+               type = "(unknown)";
+-              if (machine_is_omap_innovator()) {
++              if (machine_is_omap_innovator() || machine_is_h6300()) {
+                       /* just set up software VBUS detect, and then
+                        * later rig it so we always report VBUS.
+                        * FIXME without really sensing VBUS, we can't
+diff -Naur linux-2.6.14-omap2/drivers/video/omap/lcd_h6300.c linux-h6300-omap2-2.6.14.3/drivers/video/omap/lcd_h6300.c
+--- linux-2.6.14-omap2/drivers/video/omap/lcd_h6300.c  1970-01-01 02:00:00.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/drivers/video/omap/lcd_h6300.c  2005-11-11 04:13:42.000000000 +0200
+@@ -0,0 +1,107 @@
++/*
++ * File: drivers/video/omap_new/lcd-h6300.c
++ *
++ * LCD panel support for the TI OMAP1510 Innovator board
++ *
++ * Copyright (C) 2004 Nokia Corporation
++ * Author: Imre Deak <imre.deak@nokia.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
++ */
++
++#include <linux/module.h>
++#include <asm/io.h>
++
++#include <asm/hardware/clock.h>
++#include <asm/arch/omapfb.h>
++
++/* #define OMAPFB_DBG 1 */
++
++#include "debug.h"
++
++//static struct clk *h6300_lcd_ck;
++
++static int h6300_panel_init(struct omapfb_device *fbdev)
++{
++      DBGENTER(1);
++/*
++      if ((h6300_lcd_ck = clk_get (NULL, "lcd_ck")) == NULL) {
++              printk(KERN_ERR "Unable to get the clock LCD_CK!!!\n");
++              return -EPERM;
++      } clk_enable(h6300_lcd_ck);
++*/
++      DBGLEAVE(1);
++      printk(KERN_INFO "lcd_h6300.c: h6300_panel_init() done\n");
++      return 0;
++}
++
++static void h6300_panel_cleanup(void)
++{
++      DBGENTER(1);
++/*
++      if (h6300_lcd_ck) {
++              clk_disable(h6300_lcd_ck);
++              clk_put (h6300_lcd_ck);
++              h6300_lcd_ck = NULL;
++      }
++*/
++      DBGLEAVE(1);
++      printk(KERN_INFO "lcd_h6300.c: h6300_panel_cleanup() done\n");
++}
++
++static int h6300_panel_enable(void)
++{
++      DBGENTER(1);
++      DBGLEAVE(1);
++      printk(KERN_INFO "lcd_h6300.c: h6300_panel_enable() done\n");
++      return 0;
++}
++
++static void h6300_panel_disable(void)
++{
++      DBGENTER(1);
++      DBGLEAVE(1);
++      printk(KERN_INFO "lcd_h6300.c: h6300_panel_disable() done\n");  
++}
++
++static unsigned long h6300_panel_get_caps(void)
++{
++      printk(KERN_INFO "lcd_h6300.c: h6300_panel_get_caps() called\n");       
++      return 0;
++}
++
++struct lcd_panel h6300_panel = {
++      .name           = "h6300",
++      .config         = OMAP_LCDC_PANEL_TFT,
++
++      .bpp            = 16,
++      .data_lines     = 16,
++      .x_res          = 240,
++      .y_res          = 320,
++      .pixel_clock    = 21000,
++      .hsw            = 12,
++      .hfp            = 10,
++      .hbp            = 10,
++      .vsw            = 3,
++      .vfp            = 10,
++      .vbp            = 3,
++      .pcd            = 0,
++
++      .init           = h6300_panel_init,
++      .cleanup        = h6300_panel_cleanup,
++      .enable         = h6300_panel_enable,
++      .disable        = h6300_panel_disable,
++      .get_caps       = h6300_panel_get_caps,
++};
+diff -Naur linux-2.6.14-omap2/drivers/video/omap/Makefile linux-h6300-omap2-2.6.14.3/drivers/video/omap/Makefile
+--- linux-2.6.14-omap2/drivers/video/omap/Makefile     2005-12-02 01:53:33.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/drivers/video/omap/Makefile     2005-10-22 03:52:45.000000000 +0300
+@@ -21,6 +21,7 @@
+ objs-$(CONFIG_ARCH_OMAP15XX)$(CONFIG_MACH_OMAP_INNOVATOR) += lcd_inn1510.o
+ objs-y$(CONFIG_MACH_OMAP_OSK) += lcd_osk.o
+ objs-y$(CONFIG_MACH_OMAP_PERSEUS2) += lcd_p2.o
++objs-$(CONFIG_ARCH_OMAP15XX)$(CONFIG_MACH_OMAP_H6300) += lcd_h6300.o
+ omapfb-objs := $(objs-yy)
+diff -Naur linux-2.6.14-omap2/drivers/video/omap/omapfb_main.c linux-h6300-omap2-2.6.14.3/drivers/video/omap/omapfb_main.c
+--- linux-2.6.14-omap2/drivers/video/omap/omapfb_main.c        2005-12-02 01:53:33.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/drivers/video/omap/omapfb_main.c        2005-10-24 19:16:46.000000000 +0300
+@@ -89,6 +89,7 @@
+ extern struct lcd_panel innovator1610_panel;
+ extern struct lcd_panel innovator1510_panel;
+ extern struct lcd_panel lph8923_panel;
++extern struct lcd_panel h6300_panel;
+ static struct lcd_panel *panels[] = {
+ #ifdef CONFIG_MACH_OMAP_H2
+@@ -109,6 +110,9 @@
+ #ifdef CONFIG_MACH_OMAP_PALMTE
+       &palmte_panel,
+ #endif
++#ifdef CONFIG_MACH_OMAP_H6300
++      &h6300_panel,
++#endif
+ #ifdef CONFIG_MACH_OMAP_INNOVATOR
+diff -Naur linux-2.6.14-omap2/fs/exec.c linux-h6300-omap2-2.6.14.3/fs/exec.c
+--- linux-2.6.14-omap2/fs/exec.c       2005-10-28 03:02:08.000000000 +0300
++++ linux-h6300-omap2-2.6.14.3/fs/exec.c       2005-11-23 01:44:02.000000000 +0200
+@@ -593,6 +593,7 @@
+       struct signal_struct *sig = tsk->signal;
+       struct sighand_struct *newsighand, *oldsighand = tsk->sighand;
+       spinlock_t *lock = &oldsighand->siglock;
++      struct task_struct *leader = NULL;
+       int count;
+       /*
+@@ -668,7 +669,7 @@
+        * and to assume its PID:
+        */
+       if (!thread_group_leader(current)) {
+-              struct task_struct *leader = current->group_leader, *parent;
++              struct task_struct *parent;
+               struct dentry *proc_dentry1, *proc_dentry2;
+               unsigned long exit_state, ptrace;
+@@ -677,6 +678,7 @@
+                * It should already be zombie at this point, most
+                * of the time.
+                */
++              leader = current->group_leader;
+               while (leader->exit_state != EXIT_ZOMBIE)
+                       yield();
+@@ -736,7 +738,6 @@
+               proc_pid_flush(proc_dentry2);
+               BUG_ON(exit_state != EXIT_ZOMBIE);
+-              release_task(leader);
+         }
+       /*
+@@ -746,8 +747,11 @@
+       sig->flags = 0;
+ no_thread_group:
+-      BUG_ON(atomic_read(&sig->count) != 1);
+       exit_itimers(sig);
++      if (leader)
++              release_task(leader);
++
++      BUG_ON(atomic_read(&sig->count) != 1);
+       if (atomic_read(&oldsighand->count) == 1) {
+               /*
+diff -Naur linux-2.6.14-omap2/fs/locks.c linux-h6300-omap2-2.6.14.3/fs/locks.c
+--- linux-2.6.14-omap2/fs/locks.c      2005-10-28 03:02:08.000000000 +0300
++++ linux-h6300-omap2-2.6.14.3/fs/locks.c      2005-12-02 01:34:35.000000000 +0200
+@@ -1418,7 +1418,7 @@
+       lock_kernel();
+       error = __setlease(filp, arg, &flp);
+-      if (error)
++      if (error || arg == F_UNLCK)
+               goto out_unlock;
+       error = fasync_helper(fd, filp, 1, &flp->fl_fasync);
+diff -Naur linux-2.6.14-omap2/fs/xfs/Kconfig linux-h6300-omap2-2.6.14.3/fs/xfs/Kconfig
+--- linux-2.6.14-omap2/fs/xfs/Kconfig  2005-10-28 03:02:08.000000000 +0300
++++ linux-h6300-omap2-2.6.14.3/fs/xfs/Kconfig  2005-11-23 01:44:02.000000000 +0200
+@@ -24,7 +24,7 @@
+       default y
+ config XFS_QUOTA
+-      tristate "XFS Quota support"
++      bool "XFS Quota support"
+       depends on XFS_FS
+       help
+         If you say Y here, you will be able to set limits for disk usage on
+diff -Naur linux-2.6.14-omap2/include/asm-alpha/barrier.h linux-h6300-omap2-2.6.14.3/include/asm-alpha/barrier.h
+--- linux-2.6.14-omap2/include/asm-alpha/barrier.h     2005-10-28 03:02:08.000000000 +0300
++++ linux-h6300-omap2-2.6.14.3/include/asm-alpha/barrier.h     2005-11-23 01:44:02.000000000 +0200
+@@ -1,6 +1,8 @@
+ #ifndef __BARRIER_H
+ #define __BARRIER_H
++#include <asm/compiler.h>
++
+ #define mb() \
+ __asm__ __volatile__("mb": : :"memory")
+diff -Naur linux-2.6.14-omap2/include/asm-arm/arch-omap/board-h6300.h linux-h6300-omap2-2.6.14.3/include/asm-arm/arch-omap/board-h6300.h
+--- linux-2.6.14-omap2/include/asm-arm/arch-omap/board-h6300.h 1970-01-01 02:00:00.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/include/asm-arm/arch-omap/board-h6300.h 2005-08-12 13:46:22.000000000 +0300
+@@ -0,0 +1,40 @@
++/*
++ * linux/include/asm-arm/arch-omap/board-innovator.h
++ *
++ * Copyright (C) 2001 RidgeRun, Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ *
++ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
++ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
++ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
++ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
++ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++#ifndef __ASM_ARCH_H6300_H
++#define __ASM_ARCH_H6300_H
++
++#ifndef OMAP_SDRAM_DEVICE
++#define OMAP_SDRAM_DEVICE                     D256M_1X16_4B
++#endif
++
++#define OMAP1510P1_IMIF_PRI_VALUE             0x00
++#define OMAP1510P1_EMIFS_PRI_VALUE            0x00
++#define OMAP1510P1_EMIFF_PRI_VALUE            0x00
++
++#define NR_FPGA_IRQS          24
++#define NR_IRQS                 IH_BOARD_BASE + NR_FPGA_IRQS
++
++#endif /* __ASM_ARCH_H6300_H */
+diff -Naur linux-2.6.14-omap2/include/asm-arm/arch-omap/h6300_uart_info.h linux-h6300-omap2-2.6.14.3/include/asm-arm/arch-omap/h6300_uart_info.h
+--- linux-2.6.14-omap2/include/asm-arm/arch-omap/h6300_uart_info.h     1970-01-01 02:00:00.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/include/asm-arm/arch-omap/h6300_uart_info.h     2005-10-14 18:55:31.000000000 +0300
+@@ -0,0 +1,33 @@
++/*
++ * Support file for calling h6300 uart configuration functions.
++ * Used at least by h6300_bt driver.
++ * 
++ * Copyright (c) 2005 SDG Systems, LLC
++ * 2005-03-29   Todd Blumer     Converted  basic structure to support hx4700
++ * 2005-10-03   Mika Laitio (lamikr@cc.jyu.fi)        Reorganized for the iPAQ h6300 bt driver.
++ */
++
++#ifndef _H6300_UART_INFO_H
++#define _H6300_UART_INFO_H
++
++#include "omap_serial.h"
++
++#define GPIO_BT_PWR_EN 3
++#define GPIO_N_BT_RST 9
++
++#define GPIO_I2C_GPRS_RESET 16
++#define GPIO_I2C_MIC_OP_EN 10
++#define GPIO_I2C_SPK_OP_PD 11
++
++#define GPIO_VALUE_OFF        0
++#define GPIO_VALUE_ON 1
++
++#define GPIO_DIR_OUTPUT 1
++
++struct h6300_uart_funcs {
++      void (*configure)( struct uart_omap_port *up, int state);
++      void (*set_txrx)( struct uart_omap_port *up, int txrx);
++      int (*get_txrx)( struct uart_omap_port *up);
++};
++
++#endif
+diff -Naur linux-2.6.14-omap2/include/asm-arm/arch-omap/hardware.h linux-h6300-omap2-2.6.14.3/include/asm-arm/arch-omap/hardware.h
+--- linux-2.6.14-omap2/include/asm-arm/arch-omap/hardware.h    2005-12-02 01:53:34.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/include/asm-arm/arch-omap/hardware.h    2005-10-22 03:52:45.000000000 +0300
+@@ -290,6 +290,10 @@
+ #include "board-innovator.h"
+ #endif
++#ifdef CONFIG_MACH_OMAP_H6300
++#include "board-h6300.h"
++#endif
++
+ #ifdef CONFIG_MACH_OMAP_H2
+ #include "board-h2.h"
+ #endif
+diff -Naur linux-2.6.14-omap2/include/asm-arm/arch-omap/irqs.h linux-h6300-omap2-2.6.14.3/include/asm-arm/arch-omap/irqs.h
+--- linux-2.6.14-omap2/include/asm-arm/arch-omap/irqs.h        2005-12-02 01:53:34.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/include/asm-arm/arch-omap/irqs.h        2005-11-11 04:13:42.000000000 +0200
+@@ -237,7 +237,7 @@
+ #define INT_24XX_SDMA_IRQ1    13
+ #define INT_24XX_SDMA_IRQ2    14
+ #define INT_24XX_SDMA_IRQ3    15
+-#define INT_24XX_DSS_IRQ      25
++#define INT_24XX_DSS_IRQ              25
+ #define INT_24XX_GPIO_BANK1   29
+ #define INT_24XX_GPIO_BANK2   30
+ #define INT_24XX_GPIO_BANK3   31
+diff -Naur linux-2.6.14-omap2/include/asm-arm/arch-omap/mux.h linux-h6300-omap2-2.6.14.3/include/asm-arm/arch-omap/mux.h
+--- linux-2.6.14-omap2/include/asm-arm/arch-omap/mux.h 2005-12-02 01:53:34.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/include/asm-arm/arch-omap/mux.h 2005-10-14 18:55:31.000000000 +0300
+@@ -316,6 +316,13 @@
+       P15_1610_UWIRE_CS3,
+       N15_1610_UWIRE_CS1,
++      /* OMAP-1510 uWire */
++      P15_1510_UWIRE_CS3,
++      N14_1510_UWIRE_CS0,
++      V19_1510_UWIRE_SCLK,
++      W21_1510_UWIRE_SDO,
++      U18_1510_UWIRE_SDI,
++
+       /* OMAP-1610 Flash */
+       L3_1610_FLASH_CS2B_OE,
+       M8_1610_FLASH_CS2B_WE,
+@@ -380,6 +387,7 @@
+       T20_1610_LOW_PWR,
+       /* MCLK Settings */
++      R10_1510_MCLK_ON,
+       V5_1710_MCLK_ON,
+       V5_1710_MCLK_OFF,
+       R10_1610_MCLK_ON,
+diff -Naur linux-2.6.14-omap2/include/asm-arm/arch-omap/omapfb.h linux-h6300-omap2-2.6.14.3/include/asm-arm/arch-omap/omapfb.h
+--- linux-2.6.14-omap2/include/asm-arm/arch-omap/omapfb.h      2005-12-02 01:53:34.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/include/asm-arm/arch-omap/omapfb.h      2005-11-11 04:13:42.000000000 +0200
+@@ -267,6 +267,7 @@
+ extern struct lcd_panel osk_panel;
+ extern struct lcd_panel innovator1610_panel;
+ extern struct lcd_panel innovator1510_panel;
++extern struct lcd_panel h6300_panel;
+ #ifdef CONFIG_ARCH_OMAP1
+ extern struct lcd_ctrl omap1_lcd_ctrl;
+diff -Naur linux-2.6.14-omap2/include/asm-arm/arch-omap/omap_serial.h linux-h6300-omap2-2.6.14.3/include/asm-arm/arch-omap/omap_serial.h
+--- linux-2.6.14-omap2/include/asm-arm/arch-omap/omap_serial.h 1970-01-01 02:00:00.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/include/asm-arm/arch-omap/omap_serial.h 2005-10-04 00:58:34.000000000 +0300
+@@ -0,0 +1,62 @@
++/*
++ * Omap/h6300 serial driver private interface. 
++ * Code originates from the pxa-serial.h available in the handheld org drivers
++ * for iPAQ PXA4700.
++ *
++ * Copyright (c) 2005 SDG Systems, LLC
++ * 2005-03-29   Todd Blumer     Converted  basic structure to support hx4700
++ * 2005-10-03   Mika Laitio (lamikr@cc.jyu.fi)        Reorganized for the iPAQ h6300 bt driver.
++ */
++ 
++#ifndef _OMAP_SERIAL_H
++#define _OMAP_SERIAL_H
++
++#define OMAP_SERIAL_TX 1
++#define OMAP_SERIAL_RX 2
++
++#include <linux/tty.h>
++#include <linux/serial_core.h>
++
++struct platform_omap_serial_funcs;
++
++struct uart_omap_port {
++      struct uart_port                        port;
++      unsigned char                           ier;
++      unsigned char                           lcr;
++      unsigned char                           mcr;
++      unsigned int                            lsr_break_flag;
++      unsigned int                            cken;
++      char                                    *name;
++      struct platform_omap_serial_funcs       *pf;
++};
++
++/* A pointer to such a structure can be contained in the platform_data
++ * field of every PXA UART platform_device. If the field is NULL, the
++ * serial port works as usual.
++ *
++ * For the sake of simplicity/performance no one of the function pointers
++ * in the structure below can be NULL.
++ */
++struct platform_omap_serial_funcs {
++      /* Platform-specific function to initialize whatever is connected
++         to this serial port... enable=1 -> enable transceiver,
++         0 -> disable transceiver. */
++      void (*configure) (struct uart_omap_port *up, int enable);
++        /* Platform-specific function to 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) (struct uart_omap_port *up, int txrx);
++      /* Get the current state of tx/rx (see bitflags above) */
++      int (*get_txrx) (struct uart_omap_port *up);
++};
++
++/*
++ * The variables below are located in arch/arm/mach-omap/board_h6300.c
++ * Machine-specific code may want to put a pointer to a static
++ * platform_pxa_serial_funcs structure in the dev.platform_data
++ * field of the respective port device.
++ */
++extern struct platform_device btuart_device;
++
++#endif
+diff -Naur linux-2.6.14-omap2/include/asm-arm/arch-omap/pca9535.h linux-h6300-omap2-2.6.14.3/include/asm-arm/arch-omap/pca9535.h
+--- linux-2.6.14-omap2/include/asm-arm/arch-omap/pca9535.h     1970-01-01 02:00:00.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/include/asm-arm/arch-omap/pca9535.h     2005-10-25 03:24:45.000000000 +0300
+@@ -0,0 +1,39 @@
++#ifndef _PCA9535_H
++#define _PCA9535_H
++
++enum  pca9535_gpios {
++      GPIO0 = 0,
++      GPIO1 = 1,
++      GPIO2 = 2,
++      GPIO3 = 3,
++      GPIO4 = 4,
++      GPIO5 = 5,
++      GPIO6 = 6,
++      GPIO7 = 7,
++      GPIO8 = 8,
++      GPIO9 = 9,
++      GPIO10 = 10,
++      GPIO11 = 11,
++      GPIO12 = 12,
++      GPIO13 = 13,
++      GPIO14 = 14,
++      GPIO15 = 15,
++      GPIO16 = 16,
++      GPIO17 = 17
++};
++
++enum gpio_values {
++      HI      = 0,
++      LOW     = 1
++};
++
++enum gpio_direction {
++      GPIO_INPUT      = 0,
++      GPIO_OUTPUT     = 1
++};
++
++extern int pca9535_gpio_read(int gpio);
++extern int pca9535_gpio_write(int gpio, unsigned char val);   
++extern int pca9535_gpio_direction(int gpio, unsigned char direction);
++
++#endif
+diff -Naur linux-2.6.14-omap2/include/linux/proc_fs.h linux-h6300-omap2-2.6.14.3/include/linux/proc_fs.h
+--- linux-2.6.14-omap2/include/linux/proc_fs.h 2005-10-28 03:02:08.000000000 +0300
++++ linux-h6300-omap2-2.6.14.3/include/linux/proc_fs.h 2005-11-23 01:44:02.000000000 +0200
+@@ -66,6 +66,7 @@
+       write_proc_t *write_proc;
+       atomic_t count;         /* use count */
+       int deleted;            /* delete flag */
++      void *set;
+ };
+ struct kcore_list {
+diff -Naur linux-2.6.14-omap2/include/linux/sysctl.h linux-h6300-omap2-2.6.14.3/include/linux/sysctl.h
+--- linux-2.6.14-omap2/include/linux/sysctl.h  2005-10-28 03:02:08.000000000 +0300
++++ linux-h6300-omap2-2.6.14.3/include/linux/sysctl.h  2005-11-23 01:44:02.000000000 +0200
+@@ -24,6 +24,7 @@
+ #include <linux/compiler.h>
+ struct file;
++struct completion;
+ #define CTL_MAXNAME 10                /* how many path components do we allow in a
+                                  call to sysctl?   In other words, what is
+@@ -925,6 +926,8 @@
+ {
+       ctl_table *ctl_table;
+       struct list_head ctl_entry;
++      int used;
++      struct completion *unregistering;
+ };
+ struct ctl_table_header * register_sysctl_table(ctl_table * table, 
+diff -Naur linux-2.6.14-omap2/include/net/ipv6.h linux-h6300-omap2-2.6.14.3/include/net/ipv6.h
+--- linux-2.6.14-omap2/include/net/ipv6.h      2005-10-28 03:02:08.000000000 +0300
++++ linux-h6300-omap2-2.6.14.3/include/net/ipv6.h      2005-12-02 01:34:35.000000000 +0200
+@@ -237,6 +237,8 @@
+                                                  int newtype,
+                                                  struct ipv6_opt_hdr __user *newopt,
+                                                  int newoptlen);
++struct ipv6_txoptions *ipv6_fixup_options(struct ipv6_txoptions *opt_space,
++                                        struct ipv6_txoptions *opt);
+ extern int ip6_frag_nqueues;
+ extern atomic_t ip6_frag_mem;
+diff -Naur linux-2.6.14-omap2/kernel/ptrace.c linux-h6300-omap2-2.6.14.3/kernel/ptrace.c
+--- linux-2.6.14-omap2/kernel/ptrace.c 2005-10-28 03:02:08.000000000 +0300
++++ linux-h6300-omap2-2.6.14.3/kernel/ptrace.c 2005-11-23 01:44:02.000000000 +0200
+@@ -152,7 +152,7 @@
+       retval = -EPERM;
+       if (task->pid <= 1)
+               goto bad;
+-      if (task == current)
++      if (task->tgid == current->tgid)
+               goto bad;
+       /* the same process cannot be attached many times */
+       if (task->ptrace & PT_PTRACED)
+diff -Naur linux-2.6.14-omap2/kernel/signal.c linux-h6300-omap2-2.6.14.3/kernel/signal.c
+--- linux-2.6.14-omap2/kernel/signal.c 2005-10-28 03:02:08.000000000 +0300
++++ linux-h6300-omap2-2.6.14.3/kernel/signal.c 2005-12-02 01:34:35.000000000 +0200
+@@ -406,6 +406,8 @@
+ void exit_signal(struct task_struct *tsk)
+ {
++      atomic_dec(&tsk->signal->live);
++
+       write_lock_irq(&tasklist_lock);
+       __exit_signal(tsk);
+       write_unlock_irq(&tasklist_lock);
+@@ -1522,7 +1524,7 @@
+       psig = tsk->parent->sighand;
+       spin_lock_irqsave(&psig->siglock, flags);
+-      if (sig == SIGCHLD &&
++      if (!tsk->ptrace && sig == SIGCHLD &&
+           (psig->action[SIGCHLD-1].sa.sa_handler == SIG_IGN ||
+            (psig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDWAIT))) {
+               /*
+diff -Naur linux-2.6.14-omap2/kernel/sysctl.c linux-h6300-omap2-2.6.14.3/kernel/sysctl.c
+--- linux-2.6.14-omap2/kernel/sysctl.c 2005-10-28 03:02:08.000000000 +0300
++++ linux-h6300-omap2-2.6.14.3/kernel/sysctl.c 2005-11-23 01:44:02.000000000 +0200
+@@ -169,7 +169,7 @@
+ extern struct proc_dir_entry *proc_sys_root;
+-static void register_proc_table(ctl_table *, struct proc_dir_entry *);
++static void register_proc_table(ctl_table *, struct proc_dir_entry *, void *);
+ static void unregister_proc_table(ctl_table *, struct proc_dir_entry *);
+ #endif
+@@ -992,10 +992,51 @@
+ extern void init_irq_proc (void);
++static DEFINE_SPINLOCK(sysctl_lock);
++
++/* called under sysctl_lock */
++static int use_table(struct ctl_table_header *p)
++{
++      if (unlikely(p->unregistering))
++              return 0;
++      p->used++;
++      return 1;
++}
++
++/* called under sysctl_lock */
++static void unuse_table(struct ctl_table_header *p)
++{
++      if (!--p->used)
++              if (unlikely(p->unregistering))
++                      complete(p->unregistering);
++}
++
++/* called under sysctl_lock, will reacquire if has to wait */
++static void start_unregistering(struct ctl_table_header *p)
++{
++      /*
++       * if p->used is 0, nobody will ever touch that entry again;
++       * we'll eliminate all paths to it before dropping sysctl_lock
++       */
++      if (unlikely(p->used)) {
++              struct completion wait;
++              init_completion(&wait);
++              p->unregistering = &wait;
++              spin_unlock(&sysctl_lock);
++              wait_for_completion(&wait);
++              spin_lock(&sysctl_lock);
++      }
++      /*
++       * do not remove from the list until nobody holds it; walking the
++       * list in do_sysctl() relies on that.
++       */
++      list_del_init(&p->ctl_entry);
++}
++
+ void __init sysctl_init(void)
+ {
+ #ifdef CONFIG_PROC_FS
+-      register_proc_table(root_table, proc_sys_root);
++      register_proc_table(root_table, proc_sys_root, &root_table_header);
+       init_irq_proc();
+ #endif
+ }
+@@ -1004,6 +1045,7 @@
+              void __user *newval, size_t newlen)
+ {
+       struct list_head *tmp;
++      int error = -ENOTDIR;
+       if (nlen <= 0 || nlen >= CTL_MAXNAME)
+               return -ENOTDIR;
+@@ -1012,20 +1054,30 @@
+               if (!oldlenp || get_user(old_len, oldlenp))
+                       return -EFAULT;
+       }
++      spin_lock(&sysctl_lock);
+       tmp = &root_table_header.ctl_entry;
+       do {
+               struct ctl_table_header *head =
+                       list_entry(tmp, struct ctl_table_header, ctl_entry);
+               void *context = NULL;
+-              int error = parse_table(name, nlen, oldval, oldlenp, 
++
++              if (!use_table(head))
++                      continue;
++
++              spin_unlock(&sysctl_lock);
++
++              error = parse_table(name, nlen, oldval, oldlenp, 
+                                       newval, newlen, head->ctl_table,
+                                       &context);
+               kfree(context);
++
++              spin_lock(&sysctl_lock);
++              unuse_table(head);
+               if (error != -ENOTDIR)
+-                      return error;
+-              tmp = tmp->next;
+-      } while (tmp != &root_table_header.ctl_entry);
+-      return -ENOTDIR;
++                      break;
++      } while ((tmp = tmp->next) != &root_table_header.ctl_entry);
++      spin_unlock(&sysctl_lock);
++      return error;
+ }
+ asmlinkage long sys_sysctl(struct __sysctl_args __user *args)
+@@ -1236,12 +1288,16 @@
+               return NULL;
+       tmp->ctl_table = table;
+       INIT_LIST_HEAD(&tmp->ctl_entry);
++      tmp->used = 0;
++      tmp->unregistering = NULL;
++      spin_lock(&sysctl_lock);
+       if (insert_at_head)
+               list_add(&tmp->ctl_entry, &root_table_header.ctl_entry);
+       else
+               list_add_tail(&tmp->ctl_entry, &root_table_header.ctl_entry);
++      spin_unlock(&sysctl_lock);
+ #ifdef CONFIG_PROC_FS
+-      register_proc_table(table, proc_sys_root);
++      register_proc_table(table, proc_sys_root, tmp);
+ #endif
+       return tmp;
+ }
+@@ -1255,10 +1311,13 @@
+  */
+ void unregister_sysctl_table(struct ctl_table_header * header)
+ {
+-      list_del(&header->ctl_entry);
++      might_sleep();
++      spin_lock(&sysctl_lock);
++      start_unregistering(header);
+ #ifdef CONFIG_PROC_FS
+       unregister_proc_table(header->ctl_table, proc_sys_root);
+ #endif
++      spin_unlock(&sysctl_lock);
+       kfree(header);
+ }
+@@ -1269,7 +1328,7 @@
+ #ifdef CONFIG_PROC_FS
+ /* Scan the sysctl entries in table and add them all into /proc */
+-static void register_proc_table(ctl_table * table, struct proc_dir_entry *root)
++static void register_proc_table(ctl_table * table, struct proc_dir_entry *root, void *set)
+ {
+       struct proc_dir_entry *de;
+       int len;
+@@ -1305,13 +1364,14 @@
+                       de = create_proc_entry(table->procname, mode, root);
+                       if (!de)
+                               continue;
++                      de->set = set;
+                       de->data = (void *) table;
+                       if (table->proc_handler)
+                               de->proc_fops = &proc_sys_file_operations;
+               }
+               table->de = de;
+               if (de->mode & S_IFDIR)
+-                      register_proc_table(table->child, de);
++                      register_proc_table(table->child, de, set);
+       }
+ }
+@@ -1336,6 +1396,13 @@
+                               continue;
+               }
++              /*
++               * In any case, mark the entry as goner; we'll keep it
++               * around if it's busy, but we'll know to do nothing with
++               * its fields.  We are under sysctl_lock here.
++               */
++              de->data = NULL;
++
+               /* Don't unregister proc entries that are still being used.. */
+               if (atomic_read(&de->count))
+                       continue;
+@@ -1349,27 +1416,38 @@
+                         size_t count, loff_t *ppos)
+ {
+       int op;
+-      struct proc_dir_entry *de;
++      struct proc_dir_entry *de = PDE(file->f_dentry->d_inode);
+       struct ctl_table *table;
+       size_t res;
+-      ssize_t error;
+-      
+-      de = PDE(file->f_dentry->d_inode);
+-      if (!de || !de->data)
+-              return -ENOTDIR;
+-      table = (struct ctl_table *) de->data;
+-      if (!table || !table->proc_handler)
+-              return -ENOTDIR;
+-      op = (write ? 002 : 004);
+-      if (ctl_perm(table, op))
+-              return -EPERM;
++      ssize_t error = -ENOTDIR;
+       
+-      res = count;
+-
+-      error = (*table->proc_handler) (table, write, file, buf, &res, ppos);
+-      if (error)
+-              return error;
+-      return res;
++      spin_lock(&sysctl_lock);
++      if (de && de->data && use_table(de->set)) {
++              /*
++               * at that point we know that sysctl was not unregistered
++               * and won't be until we finish
++               */
++              spin_unlock(&sysctl_lock);
++              table = (struct ctl_table *) de->data;
++              if (!table || !table->proc_handler)
++                      goto out;
++              error = -EPERM;
++              op = (write ? 002 : 004);
++              if (ctl_perm(table, op))
++                      goto out;
++              
++              /* careful: calling conventions are nasty here */
++              res = count;
++              error = (*table->proc_handler)(table, write, file,
++                                              buf, &res, ppos);
++              if (!error)
++                      error = res;
++      out:
++              spin_lock(&sysctl_lock);
++              unuse_table(de->set);
++      }
++      spin_unlock(&sysctl_lock);
++      return error;
+ }
+ static int proc_opensys(struct inode *inode, struct file *file)
+diff -Naur linux-2.6.14-omap2/Makefile linux-h6300-omap2-2.6.14.3/Makefile
+--- linux-2.6.14-omap2/Makefile        2005-12-02 01:53:31.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/Makefile        2005-12-02 01:34:34.000000000 +0200
+@@ -1,7 +1,7 @@
+ VERSION = 2
+ PATCHLEVEL = 6
+ SUBLEVEL = 14
+-EXTRAVERSION =
++EXTRAVERSION = .3
+ NAME=Affluent Albatross
+ # *DOCUMENTATION*
+@@ -11,7 +11,7 @@
+ # expect to learn how to build the kernel reading this file.
+ # Add custom flags here to avoid conflict with updates
+-EXTRAVERSION := $(EXTRAVERSION)-omap2
++EXTRAVERSION := $(EXTRAVERSION)-omap1-h6300
+ # Do not print "Entering directory ..."
+ MAKEFLAGS += --no-print-directory
+diff -Naur linux-2.6.14-omap2/net/core/datagram.c linux-h6300-omap2-2.6.14.3/net/core/datagram.c
+--- linux-2.6.14-omap2/net/core/datagram.c     2005-10-28 03:02:08.000000000 +0300
++++ linux-h6300-omap2-2.6.14.3/net/core/datagram.c     2005-11-23 01:44:02.000000000 +0200
+@@ -213,6 +213,10 @@
+ {
+       int i, err, fraglen, end = 0;
+       struct sk_buff *next = skb_shinfo(skb)->frag_list;
++
++      if (!len)
++              return 0;
++
+ next_skb:
+       fraglen = skb_headlen(skb);
+       i = -1;
+diff -Naur linux-2.6.14-omap2/net/ipv4/ipvs/ip_vs_core.c linux-h6300-omap2-2.6.14.3/net/ipv4/ipvs/ip_vs_core.c
+--- linux-2.6.14-omap2/net/ipv4/ipvs/ip_vs_core.c      2005-10-28 03:02:08.000000000 +0300
++++ linux-h6300-omap2-2.6.14.3/net/ipv4/ipvs/ip_vs_core.c      2005-11-23 01:44:02.000000000 +0200
+@@ -1009,11 +1009,10 @@
+               if (sysctl_ip_vs_expire_nodest_conn) {
+                       /* try to expire the connection immediately */
+                       ip_vs_conn_expire_now(cp);
+-              } else {
+-                      /* don't restart its timer, and silently
+-                         drop the packet. */
+-                      __ip_vs_conn_put(cp);
+               }
++              /* don't restart its timer, and silently
++                 drop the packet. */
++              __ip_vs_conn_put(cp);
+               return NF_DROP;
+       }
+diff -Naur linux-2.6.14-omap2/net/ipv4/netfilter/ip_conntrack_ftp.c linux-h6300-omap2-2.6.14.3/net/ipv4/netfilter/ip_conntrack_ftp.c
+--- linux-2.6.14-omap2/net/ipv4/netfilter/ip_conntrack_ftp.c   2005-10-28 03:02:08.000000000 +0300
++++ linux-h6300-omap2-2.6.14.3/net/ipv4/netfilter/ip_conntrack_ftp.c   2005-12-02 01:34:35.000000000 +0200
+@@ -29,9 +29,9 @@
+ static DEFINE_SPINLOCK(ip_ftp_lock);
+ #define MAX_PORTS 8
+-static short ports[MAX_PORTS];
++static unsigned short ports[MAX_PORTS];
+ static int ports_c;
+-module_param_array(ports, short, &ports_c, 0400);
++module_param_array(ports, ushort, &ports_c, 0400);
+ static int loose;
+ module_param(loose, int, 0600);
+diff -Naur linux-2.6.14-omap2/net/ipv4/netfilter/ip_conntrack_irc.c linux-h6300-omap2-2.6.14.3/net/ipv4/netfilter/ip_conntrack_irc.c
+--- linux-2.6.14-omap2/net/ipv4/netfilter/ip_conntrack_irc.c   2005-10-28 03:02:08.000000000 +0300
++++ linux-h6300-omap2-2.6.14.3/net/ipv4/netfilter/ip_conntrack_irc.c   2005-12-02 01:34:35.000000000 +0200
+@@ -34,7 +34,7 @@
+ #include <linux/moduleparam.h>
+ #define MAX_PORTS 8
+-static short ports[MAX_PORTS];
++static unsigned short ports[MAX_PORTS];
+ static int ports_c;
+ static int max_dcc_channels = 8;
+ static unsigned int dcc_timeout = 300;
+@@ -52,7 +52,7 @@
+ MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
+ MODULE_DESCRIPTION("IRC (DCC) connection tracking helper");
+ MODULE_LICENSE("GPL");
+-module_param_array(ports, short, &ports_c, 0400);
++module_param_array(ports, ushort, &ports_c, 0400);
+ MODULE_PARM_DESC(ports, "port numbers of IRC servers");
+ module_param(max_dcc_channels, int, 0400);
+ MODULE_PARM_DESC(max_dcc_channels, "max number of expected DCC channels per IRC session");
+diff -Naur linux-2.6.14-omap2/net/ipv4/netfilter/ip_conntrack_netlink.c linux-h6300-omap2-2.6.14.3/net/ipv4/netfilter/ip_conntrack_netlink.c
+--- linux-2.6.14-omap2/net/ipv4/netfilter/ip_conntrack_netlink.c       2005-10-28 03:02:08.000000000 +0300
++++ linux-h6300-omap2-2.6.14.3/net/ipv4/netfilter/ip_conntrack_netlink.c       2005-12-02 01:34:35.000000000 +0200
+@@ -58,14 +58,17 @@
+                           const struct ip_conntrack_tuple *tuple)
+ {
+       struct ip_conntrack_protocol *proto;
++      int ret = 0;
+       NFA_PUT(skb, CTA_PROTO_NUM, sizeof(u_int8_t), &tuple->dst.protonum);
+       proto = ip_conntrack_proto_find_get(tuple->dst.protonum);
+-      if (proto && proto->tuple_to_nfattr)
+-              return proto->tuple_to_nfattr(skb, tuple);
++      if (likely(proto && proto->tuple_to_nfattr)) {
++              ret = proto->tuple_to_nfattr(skb, tuple);
++              ip_conntrack_proto_put(proto);
++      }
+-      return 0;
++      return ret;
+ nfattr_failure:
+       return -1;
+diff -Naur linux-2.6.14-omap2/net/ipv4/netfilter/ip_conntrack_proto_icmp.c linux-h6300-omap2-2.6.14.3/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
+--- linux-2.6.14-omap2/net/ipv4/netfilter/ip_conntrack_proto_icmp.c    2005-10-28 03:02:08.000000000 +0300
++++ linux-h6300-omap2-2.6.14.3/net/ipv4/netfilter/ip_conntrack_proto_icmp.c    2005-12-02 01:34:35.000000000 +0200
+@@ -296,7 +296,8 @@
+                               struct ip_conntrack_tuple *tuple)
+ {
+       if (!tb[CTA_PROTO_ICMP_TYPE-1]
+-          || !tb[CTA_PROTO_ICMP_CODE-1])
++          || !tb[CTA_PROTO_ICMP_CODE-1]
++          || !tb[CTA_PROTO_ICMP_ID-1])
+               return -1;
+       tuple->dst.u.icmp.type = 
+diff -Naur linux-2.6.14-omap2/net/ipv4/netfilter/ip_conntrack_proto_tcp.c linux-h6300-omap2-2.6.14.3/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
+--- linux-2.6.14-omap2/net/ipv4/netfilter/ip_conntrack_proto_tcp.c     2005-10-28 03:02:08.000000000 +0300
++++ linux-h6300-omap2-2.6.14.3/net/ipv4/netfilter/ip_conntrack_proto_tcp.c     2005-12-02 01:34:35.000000000 +0200
+@@ -362,6 +362,11 @@
+       struct nfattr *attr = cda[CTA_PROTOINFO_TCP-1];
+       struct nfattr *tb[CTA_PROTOINFO_TCP_MAX];
++      /* updates could not contain anything about the private
++       * protocol info, in that case skip the parsing */
++      if (!attr)
++              return 0;
++
+         if (nfattr_parse_nested(tb, CTA_PROTOINFO_TCP_MAX, attr) < 0)
+                 goto nfattr_failure;
+@@ -813,6 +818,7 @@
+ {
+       [TH_SYN]                        = 1,
+       [TH_SYN|TH_ACK]                 = 1,
++      [TH_SYN|TH_PUSH]                = 1,
+       [TH_SYN|TH_ACK|TH_PUSH]         = 1,
+       [TH_RST]                        = 1,
+       [TH_RST|TH_ACK]                 = 1,
+diff -Naur linux-2.6.14-omap2/net/ipv4/netfilter/ip_conntrack_tftp.c linux-h6300-omap2-2.6.14.3/net/ipv4/netfilter/ip_conntrack_tftp.c
+--- linux-2.6.14-omap2/net/ipv4/netfilter/ip_conntrack_tftp.c  2005-10-28 03:02:08.000000000 +0300
++++ linux-h6300-omap2-2.6.14.3/net/ipv4/netfilter/ip_conntrack_tftp.c  2005-12-02 01:34:35.000000000 +0200
+@@ -26,9 +26,9 @@
+ MODULE_LICENSE("GPL");
+ #define MAX_PORTS 8
+-static short ports[MAX_PORTS];
++static unsigned short ports[MAX_PORTS];
+ static int ports_c;
+-module_param_array(ports, short, &ports_c, 0400);
++module_param_array(ports, ushort, &ports_c, 0400);
+ MODULE_PARM_DESC(ports, "port numbers of tftp servers");
+ #if 0
+diff -Naur linux-2.6.14-omap2/net/ipv4/netfilter/ip_nat_core.c linux-h6300-omap2-2.6.14.3/net/ipv4/netfilter/ip_nat_core.c
+--- linux-2.6.14-omap2/net/ipv4/netfilter/ip_nat_core.c        2005-10-28 03:02:08.000000000 +0300
++++ linux-h6300-omap2-2.6.14.3/net/ipv4/netfilter/ip_nat_core.c        2005-12-02 01:34:35.000000000 +0200
+@@ -66,10 +66,8 @@
+        * removed until we've grabbed the reference */
+       preempt_disable();
+       p = __ip_nat_proto_find(protonum);
+-      if (p) {
+-              if (!try_module_get(p->me))
+-                      p = &ip_nat_unknown_protocol;
+-      }
++      if (!try_module_get(p->me))
++              p = &ip_nat_unknown_protocol;
+       preempt_enable();
+       return p;
+diff -Naur linux-2.6.14-omap2/net/ipv4/netfilter/ip_nat_helper_pptp.c linux-h6300-omap2-2.6.14.3/net/ipv4/netfilter/ip_nat_helper_pptp.c
+--- linux-2.6.14-omap2/net/ipv4/netfilter/ip_nat_helper_pptp.c 2005-10-28 03:02:08.000000000 +0300
++++ linux-h6300-omap2-2.6.14.3/net/ipv4/netfilter/ip_nat_helper_pptp.c 2005-12-02 01:34:35.000000000 +0200
+@@ -73,6 +73,7 @@
+       struct ip_conntrack_tuple t;
+       struct ip_ct_pptp_master *ct_pptp_info;
+       struct ip_nat_pptp *nat_pptp_info;
++      struct ip_nat_range range;
+       ct_pptp_info = &master->help.ct_pptp_info;
+       nat_pptp_info = &master->nat.help.nat_pptp_info;
+@@ -110,7 +111,30 @@
+               DEBUGP("not found!\n");
+       }
+-      ip_nat_follow_master(ct, exp);
++      /* This must be a fresh one. */
++      BUG_ON(ct->status & IPS_NAT_DONE_MASK);
++
++      /* Change src to where master sends to */
++      range.flags = IP_NAT_RANGE_MAP_IPS;
++      range.min_ip = range.max_ip
++              = ct->master->tuplehash[!exp->dir].tuple.dst.ip;
++      if (exp->dir == IP_CT_DIR_ORIGINAL) {
++              range.flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
++              range.min = range.max = exp->saved_proto;
++      }
++      /* hook doesn't matter, but it has to do source manip */
++      ip_nat_setup_info(ct, &range, NF_IP_POST_ROUTING);
++
++      /* For DST manip, map port here to where it's expected. */
++      range.flags = IP_NAT_RANGE_MAP_IPS;
++      range.min_ip = range.max_ip
++              = ct->master->tuplehash[!exp->dir].tuple.src.ip;
++      if (exp->dir == IP_CT_DIR_REPLY) {
++              range.flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
++              range.min = range.max = exp->saved_proto;
++      }
++      /* hook doesn't matter, but it has to do destination manip */
++      ip_nat_setup_info(ct, &range, NF_IP_PRE_ROUTING);
+ }
+ /* outbound packets == from PNS to PAC */
+@@ -213,7 +237,7 @@
+       /* alter expectation for PNS->PAC direction */
+       invert_tuplepr(&inv_t, &expect_orig->tuple);
+-      expect_orig->saved_proto.gre.key = htons(nat_pptp_info->pac_call_id);
++      expect_orig->saved_proto.gre.key = htons(ct_pptp_info->pns_call_id);
+       expect_orig->tuple.src.u.gre.key = htons(nat_pptp_info->pns_call_id);
+       expect_orig->tuple.dst.u.gre.key = htons(ct_pptp_info->pac_call_id);
+       inv_t.src.ip = reply_t->src.ip;
+diff -Naur linux-2.6.14-omap2/net/ipv4/netfilter/ip_nat_proto_gre.c linux-h6300-omap2-2.6.14.3/net/ipv4/netfilter/ip_nat_proto_gre.c
+--- linux-2.6.14-omap2/net/ipv4/netfilter/ip_nat_proto_gre.c   2005-10-28 03:02:08.000000000 +0300
++++ linux-h6300-omap2-2.6.14.3/net/ipv4/netfilter/ip_nat_proto_gre.c   2005-12-02 01:34:35.000000000 +0200
+@@ -139,8 +139,8 @@
+                       break;
+               case GRE_VERSION_PPTP:
+                       DEBUGP("call_id -> 0x%04x\n", 
+-                              ntohl(tuple->dst.u.gre.key));
+-                      pgreh->call_id = htons(ntohl(tuple->dst.u.gre.key));
++                              ntohs(tuple->dst.u.gre.key));
++                      pgreh->call_id = tuple->dst.u.gre.key;
+                       break;
+               default:
+                       DEBUGP("can't nat unknown GRE version\n");
+diff -Naur linux-2.6.14-omap2/net/ipv4/netfilter/ip_nat_proto_unknown.c linux-h6300-omap2-2.6.14.3/net/ipv4/netfilter/ip_nat_proto_unknown.c
+--- linux-2.6.14-omap2/net/ipv4/netfilter/ip_nat_proto_unknown.c       2005-10-28 03:02:08.000000000 +0300
++++ linux-h6300-omap2-2.6.14.3/net/ipv4/netfilter/ip_nat_proto_unknown.c       2005-12-02 01:34:35.000000000 +0200
+@@ -62,7 +62,7 @@
+ struct ip_nat_protocol ip_nat_unknown_protocol = {
+       .name                   = "unknown",
+-      .me                     = THIS_MODULE,
++      /* .me isn't set: getting a ref to this cannot fail. */
+       .manip_pkt              = unknown_manip_pkt,
+       .in_range               = unknown_in_range,
+       .unique_tuple           = unknown_unique_tuple,
+diff -Naur linux-2.6.14-omap2/net/ipv4/tcp_bic.c linux-h6300-omap2-2.6.14.3/net/ipv4/tcp_bic.c
+--- linux-2.6.14-omap2/net/ipv4/tcp_bic.c      2005-10-28 03:02:08.000000000 +0300
++++ linux-h6300-omap2-2.6.14.3/net/ipv4/tcp_bic.c      2005-11-23 01:44:02.000000000 +0200
+@@ -27,7 +27,7 @@
+                                         */
+ static int fast_convergence = 1;
+-static int max_increment = 32;
++static int max_increment = 16;
+ static int low_window = 14;
+ static int beta = 819;                /* = 819/1024 (BICTCP_BETA_SCALE) */
+ static int low_utilization_threshold = 153;
+diff -Naur linux-2.6.14-omap2/net/ipv6/datagram.c linux-h6300-omap2-2.6.14.3/net/ipv6/datagram.c
+--- linux-2.6.14-omap2/net/ipv6/datagram.c     2005-10-28 03:02:08.000000000 +0300
++++ linux-h6300-omap2-2.6.14.3/net/ipv6/datagram.c     2005-12-02 01:34:35.000000000 +0200
+@@ -437,7 +437,7 @@
+                               break;
+                       case IPPROTO_AH:
+                               nexthdr = ptr[0];
+-                              len = (ptr[1] + 1) << 2;
++                              len = (ptr[1] + 2) << 2;
+                               break;
+                       default:
+                               nexthdr = ptr[0];
+diff -Naur linux-2.6.14-omap2/net/ipv6/exthdrs.c linux-h6300-omap2-2.6.14.3/net/ipv6/exthdrs.c
+--- linux-2.6.14-omap2/net/ipv6/exthdrs.c      2005-10-28 03:02:08.000000000 +0300
++++ linux-h6300-omap2-2.6.14.3/net/ipv6/exthdrs.c      2005-12-02 01:34:35.000000000 +0200
+@@ -628,6 +628,7 @@
+       if (!tot_len)
+               return NULL;
++      tot_len += sizeof(*opt2);
+       opt2 = sock_kmalloc(sk, tot_len, GFP_ATOMIC);
+       if (!opt2)
+               return ERR_PTR(-ENOBUFS);
+@@ -668,7 +669,26 @@
+       return opt2;
+ out:
+-      sock_kfree_s(sk, p, tot_len);
++      sock_kfree_s(sk, opt2, opt2->tot_len);
+       return ERR_PTR(err);
+ }
++struct ipv6_txoptions *ipv6_fixup_options(struct ipv6_txoptions *opt_space,
++                                        struct ipv6_txoptions *opt)
++{
++      /*
++       * ignore the dest before srcrt unless srcrt is being included.
++       * --yoshfuji
++       */
++      if (opt && opt->dst0opt && !opt->srcrt) {
++              if (opt_space != opt) {
++                      memcpy(opt_space, opt, sizeof(*opt_space));
++                      opt = opt_space;
++              }
++              opt->opt_nflen -= ipv6_optlen(opt->dst0opt);
++              opt->dst0opt = NULL;
++      }
++
++      return opt;
++}
++
+diff -Naur linux-2.6.14-omap2/net/ipv6/ip6_flowlabel.c linux-h6300-omap2-2.6.14.3/net/ipv6/ip6_flowlabel.c
+--- linux-2.6.14-omap2/net/ipv6/ip6_flowlabel.c        2005-10-28 03:02:08.000000000 +0300
++++ linux-h6300-omap2-2.6.14.3/net/ipv6/ip6_flowlabel.c        2005-12-02 01:34:35.000000000 +0200
+@@ -225,20 +225,16 @@
+                                        struct ip6_flowlabel * fl,
+                                        struct ipv6_txoptions * fopt)
+ {
+-      struct ipv6_txoptions * fl_opt = fl ? fl->opt : NULL;
++      struct ipv6_txoptions * fl_opt = fl->opt;
+-      if (fopt == NULL || fopt->opt_flen == 0) {
+-              if (!fl_opt || !fl_opt->dst0opt || fl_opt->srcrt)
+-                      return fl_opt;
+-      }
++      if (fopt == NULL || fopt->opt_flen == 0)
++              return fl_opt;
+       if (fl_opt != NULL) {
+               opt_space->hopopt = fl_opt->hopopt;
+-              opt_space->dst0opt = fl_opt->srcrt ? fl_opt->dst0opt : NULL;
++              opt_space->dst0opt = fl_opt->dst0opt;
+               opt_space->srcrt = fl_opt->srcrt;
+               opt_space->opt_nflen = fl_opt->opt_nflen;
+-              if (fl_opt->dst0opt && !fl_opt->srcrt)
+-                      opt_space->opt_nflen -= ipv6_optlen(fl_opt->dst0opt);
+       } else {
+               if (fopt->opt_nflen == 0)
+                       return fopt;
+diff -Naur linux-2.6.14-omap2/net/ipv6/raw.c linux-h6300-omap2-2.6.14.3/net/ipv6/raw.c
+--- linux-2.6.14-omap2/net/ipv6/raw.c  2005-10-28 03:02:08.000000000 +0300
++++ linux-h6300-omap2-2.6.14.3/net/ipv6/raw.c  2005-12-02 01:34:35.000000000 +0200
+@@ -756,7 +756,9 @@
+       }
+       if (opt == NULL)
+               opt = np->opt;
+-      opt = fl6_merge_options(&opt_space, flowlabel, opt);
++      if (flowlabel)
++              opt = fl6_merge_options(&opt_space, flowlabel, opt);
++      opt = ipv6_fixup_options(&opt_space, opt);
+       fl.proto = proto;
+       rawv6_probe_proto_opt(&fl, msg);
+diff -Naur linux-2.6.14-omap2/net/ipv6/udp.c linux-h6300-omap2-2.6.14.3/net/ipv6/udp.c
+--- linux-2.6.14-omap2/net/ipv6/udp.c  2005-10-28 03:02:08.000000000 +0300
++++ linux-h6300-omap2-2.6.14.3/net/ipv6/udp.c  2005-12-02 01:34:35.000000000 +0200
+@@ -778,7 +778,9 @@
+       }
+       if (opt == NULL)
+               opt = np->opt;
+-      opt = fl6_merge_options(&opt_space, flowlabel, opt);
++      if (flowlabel)
++              opt = fl6_merge_options(&opt_space, flowlabel, opt);
++      opt = ipv6_fixup_options(&opt_space, opt);
+       fl->proto = IPPROTO_UDP;
+       ipv6_addr_copy(&fl->fl6_dst, daddr);
+diff -Naur linux-2.6.14-omap2/net/netfilter/nf_queue.c linux-h6300-omap2-2.6.14.3/net/netfilter/nf_queue.c
+--- linux-2.6.14-omap2/net/netfilter/nf_queue.c        2005-10-28 03:02:08.000000000 +0300
++++ linux-h6300-omap2-2.6.14.3/net/netfilter/nf_queue.c        2005-12-02 01:34:35.000000000 +0200
+@@ -117,7 +117,7 @@
+       /* QUEUE == DROP if noone is waiting, to be safe. */
+       read_lock(&queue_handler_lock);
+-      if (!queue_handler[pf]->outfn) {
++      if (!queue_handler[pf] || !queue_handler[pf]->outfn) {
+               read_unlock(&queue_handler_lock);
+               kfree_skb(*skb);
+               return 1;
+diff -Naur linux-2.6.14-omap2/sound/arm/Kconfig linux-h6300-omap2-2.6.14.3/sound/arm/Kconfig
+--- linux-2.6.14-omap2/sound/arm/Kconfig       2005-12-02 01:53:34.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/sound/arm/Kconfig       2005-11-13 02:15:10.000000000 +0200
+@@ -45,5 +45,15 @@
+         To compile this driver as a module, choose M here: the module
+         will be called snd-omap-aic23.
++        
++config SND_OMAP_TSC2101
++      tristate "OMAP TSC2101 driver (iPaq H63xx)"
++      depends ARCH_OMAP && SND
++      select SND_PCM
++      help
++              ALSA driver for TI TSC2101.
++
++              To compile this driver as a module, choose M here: the module
++              will be called snd-omap-tsc2101.
+ endmenu
+diff -Naur linux-2.6.14-omap2/sound/arm/Makefile linux-h6300-omap2-2.6.14.3/sound/arm/Makefile
+--- linux-2.6.14-omap2/sound/arm/Makefile      2005-12-02 01:53:34.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/sound/arm/Makefile      2005-11-13 02:15:10.000000000 +0200
+@@ -16,3 +16,6 @@
+ obj-$(CONFIG_SND_OMAP_AIC23) += snd-omap-aic23.o
+ snd-omap-aic23-objs := omap-aic23.o omap-alsa-dma.o omap-alsa-mixer.o
++
++obj-$(CONFIG_SND_OMAP_TSC2101) += snd-omap-tsc2101.o
++snd-omap-tsc2101-objs := omap-tsc2101.o omap-alsa-dma.o
+diff -Naur linux-2.6.14-omap2/sound/arm/omap-aic23.c linux-h6300-omap2-2.6.14.3/sound/arm/omap-aic23.c
+--- linux-2.6.14-omap2/sound/arm/omap-aic23.c  2005-12-02 01:53:34.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/sound/arm/omap-aic23.c  2005-11-13 02:15:10.000000000 +0200
+@@ -262,144 +262,6 @@
+ }
+ /* 
+- * DMA functions 
+- * Depends on omap-aic23-dma.c functions and (omap) dma.c
+- * 
+- */
+-#define DMA_BUF_SIZE  1024 * 8
+-
+-static int audio_dma_request(struct audio_stream *s,
+-                           void (*callback) (void *))
+-{
+-      int err;
+-
+-      err = omap_request_sound_dma(s->dma_dev, s->id, s, &s->lch);
+-      if (err < 0)
+-              printk(KERN_ERR "unable to grab audio dma 0x%x\n",
+-                     s->dma_dev);
+-      return err;
+-}
+-
+-static int audio_dma_free(struct audio_stream *s)
+-{
+-      int err = 0;
+-
+-      err = omap_free_sound_dma(s, &s->lch);
+-      if (err < 0)
+-              printk(KERN_ERR "Unable to free audio dma channels!\n");
+-      return err;
+-}
+-
+-/*
+- *  This function should calculate the current position of the dma in the
+- *  buffer. It will help alsa middle layer to continue update the buffer.
+- *  Its correctness is crucial for good functioning.
+- */
+-static u_int audio_get_dma_pos(struct audio_stream *s)
+-{
+-      snd_pcm_substream_t *substream = s->stream;
+-      snd_pcm_runtime_t *runtime = substream->runtime;
+-      unsigned int offset;
+-      unsigned long flags;
+-      dma_addr_t count;
+-      ADEBUG();
+-
+-      /* this must be called w/ interrupts locked as requested in dma.c */
+-      spin_lock_irqsave(&s->dma_lock, flags);
+-
+-      /* For the current period let's see where we are */
+-      count = omap_get_dma_src_addr_counter(s->lch[s->dma_q_head]);
+-
+-      spin_unlock_irqrestore(&s->dma_lock, flags);
+-
+-      /* Now, the position related to the end of that period */
+-      offset = bytes_to_frames(runtime, s->offset) - bytes_to_frames(runtime, count);
+-
+-      if (offset >= runtime->buffer_size || offset < 0)
+-              offset = 0;
+-
+-      return offset;
+-}
+-
+-/*
+- * this stops the dma and clears the dma ptrs
+- */
+-static void audio_stop_dma(struct audio_stream *s)
+-{
+-      unsigned long flags;
+-      ADEBUG();
+-
+-      spin_lock_irqsave(&s->dma_lock, flags);
+-      s->active = 0;
+-      s->period = 0;
+-      s->periods = 0;
+-
+-      /* this stops the dma channel and clears the buffer ptrs */
+-      omap_audio_stop_dma(s);
+-
+-      omap_clear_sound_dma(s);
+-
+-      spin_unlock_irqrestore(&s->dma_lock, flags);
+-}
+-
+-/*
+- *  Main dma routine, requests dma according where you are in main alsa buffer
+- */
+-static void audio_process_dma(struct audio_stream *s)
+-{
+-      snd_pcm_substream_t *substream = s->stream;
+-      snd_pcm_runtime_t *runtime;
+-      unsigned int dma_size;
+-      unsigned int offset;
+-      int ret;
+-
+-      runtime = substream->runtime;
+-      if (s->active) {
+-              dma_size = frames_to_bytes(runtime, runtime->period_size);
+-              offset = dma_size * s->period;
+-              snd_assert(dma_size <= DMA_BUF_SIZE,);
+-              ret =
+-                  omap_start_sound_dma(s,
+-                                       (dma_addr_t) runtime->dma_area +
+-                                       offset, dma_size);
+-              if (ret) {
+-                      printk(KERN_ERR
+-                             "audio_process_dma: cannot queue DMA buffer (%i)\n",
+-                             ret);
+-                      return;
+-              }
+-
+-              s->period++;
+-              s->period %= runtime->periods;
+-              s->periods++;
+-              s->offset = offset;
+-      }
+-}
+-
+-/* 
+- *  This is called when dma IRQ occurs at the end of each transmited block
+- */
+-void audio_dma_callback(void *data)
+-{
+-      struct audio_stream *s = data;
+-
+-      /* 
+-       * If we are getting a callback for an active stream then we inform
+-       * the PCM middle layer we've finished a period
+-       */
+-      if (s->active)
+-              snd_pcm_period_elapsed(s->stream);
+-
+-      spin_lock(&s->dma_lock);
+-      if (s->periods > 0) {
+-              s->periods--;
+-      }
+-      audio_process_dma(s);
+-      spin_unlock(&s->dma_lock);
+-}
+-
+-
+-/* 
+  * Alsa section
+  * PCM settings and callbacks
+  */
+diff -Naur linux-2.6.14-omap2/sound/arm/omap-aic23.h linux-h6300-omap2-2.6.14.3/sound/arm/omap-aic23.h
+--- linux-2.6.14-omap2/sound/arm/omap-aic23.h  2005-12-02 01:53:34.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/sound/arm/omap-aic23.h  2005-11-13 02:15:10.000000000 +0200
+@@ -43,6 +43,7 @@
+ #include <asm/arch/dma.h>
+ #include <sound/core.h>
+ #include <sound/pcm.h>
++#include "omap-alsa-dma.h"
+ #define DEFAULT_OUTPUT_VOLUME         0x60
+ #define DEFAULT_INPUT_VOLUME          0x00    /* 0 ==> mute line in */
+@@ -67,27 +68,6 @@
+ #define DEFAULT_ANALOG_AUDIO_CONTROL  DAC_SELECTED | STE_ENABLED | BYPASS_ON | INSEL_MIC | MICB_20DB
+ /*
+- * Buffer management for alsa and dma
+- */
+-struct audio_stream {
+-      char *id;               /* identification string */
+-      int stream_id;          /* numeric identification */
+-      int dma_dev;            /* dma number of that device */
+-      int *lch;               /* Chain of channels this stream is linked to */
+-      char started;           /* to store if the chain was started or not */
+-      int dma_q_head;         /* DMA Channel Q Head */
+-      int dma_q_tail;         /* DMA Channel Q Tail */
+-      char dma_q_count;       /* DMA Channel Q Count */
+-      int active:1;           /* we are using this stream for transfer now */
+-      int period;             /* current transfer period */
+-      int periods;            /* current count of periods registerd in the DMA engine */
+-      spinlock_t dma_lock;    /* for locking in DMA operations */
+-      snd_pcm_substream_t *stream;    /* the pcm stream */
+-      unsigned linked:1;      /* dma channels linked */
+-      int offset;             /* store start position of the last period in the alsa buffer */
+-};
+-
+-/*
+  * Alsa card structure for aic23
+  */
+ struct snd_card_omap_aic23 {
+@@ -99,7 +79,6 @@
+ /*********** Function Prototypes *************************/
+-void audio_dma_callback(void *);
+ int snd_omap_mixer(struct snd_card_omap_aic23 *);
+ void snd_omap_init_mixer(void);
+ /* Clock functions */
+diff -Naur linux-2.6.14-omap2/sound/arm/omap-alsa-dma.c linux-h6300-omap2-2.6.14.3/sound/arm/omap-alsa-dma.c
+--- linux-2.6.14-omap2/sound/arm/omap-alsa-dma.c       2005-12-02 01:53:34.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/sound/arm/omap-alsa-dma.c       2005-11-13 02:15:10.000000000 +0200
+@@ -440,6 +440,134 @@
+       return;
+ }
++int audio_dma_request(struct audio_stream *s,
++                           void (*callback) (void *))
++{
++      int err;
++
++      err = omap_request_sound_dma(s->dma_dev, s->id, s, &s->lch);
++      if (err < 0)
++              printk(KERN_ERR "unable to grab audio dma 0x%x\n",
++                     s->dma_dev);
++      return err;
++}
++
++int audio_dma_free(struct audio_stream *s)
++{
++      int err = 0;
++
++      err = omap_free_sound_dma(s, &s->lch);
++      if (err < 0)
++              printk(KERN_ERR "Unable to free audio dma channels!\n");
++      return err;
++}
++
++/*
++ *  This function should calculate the current position of the dma in the
++ *  buffer. It will help alsa middle layer to continue update the buffer.
++ *  Its correctness is crucial for good functioning.
++ */
++u_int audio_get_dma_pos(struct audio_stream *s)
++{
++      snd_pcm_substream_t *substream = s->stream;
++      snd_pcm_runtime_t *runtime = substream->runtime;
++      unsigned int offset;
++      unsigned long flags;
++      dma_addr_t count;
++
++      /* this must be called w/ interrupts locked as requested in dma.c */
++      spin_lock_irqsave(&s->dma_lock, flags);
++
++      /* For the current period let's see where we are */
++      count = omap_get_dma_src_addr_counter(s->lch[s->dma_q_head]);
++
++      spin_unlock_irqrestore(&s->dma_lock, flags);
++
++      /* Now, the position related to the end of that period */
++      offset = bytes_to_frames(runtime, s->offset) - bytes_to_frames(runtime, count);
++
++      if (offset >= runtime->buffer_size || offset < 0)
++              offset = 0;
++
++      return offset;
++}
++
++/*
++ * this stops the dma and clears the dma ptrs
++ */
++void audio_stop_dma(struct audio_stream *s)
++{
++      unsigned long flags;
++
++      spin_lock_irqsave(&s->dma_lock, flags);
++      s->active = 0;
++      s->period = 0;
++      s->periods = 0;
++
++      /* this stops the dma channel and clears the buffer ptrs */
++      omap_audio_stop_dma(s);
++
++      omap_clear_sound_dma(s);
++
++      spin_unlock_irqrestore(&s->dma_lock, flags);
++}
++
++/*
++ *  Main dma routine, requests dma according where you are in main alsa buffer
++ */
++void audio_process_dma(struct audio_stream *s)
++{
++      snd_pcm_substream_t *substream = s->stream;
++      snd_pcm_runtime_t *runtime;
++      unsigned int dma_size;
++      unsigned int offset;
++      int ret;
++
++      runtime = substream->runtime;
++      if (s->active) {
++              dma_size = frames_to_bytes(runtime, runtime->period_size);
++              offset = dma_size * s->period;
++              snd_assert(dma_size <= DMA_BUF_SIZE,);
++              ret =
++                  omap_start_sound_dma(s,
++                                       (dma_addr_t) runtime->dma_area +
++                                       offset, dma_size);
++              if (ret) {
++                      printk(KERN_ERR
++                             "audio_process_dma: cannot queue DMA buffer (%i)\n",
++                             ret);
++                      return;
++              }
++
++              s->period++;
++              s->period %= runtime->periods;
++              s->periods++;
++              s->offset = offset;
++      }
++}
++
++/* 
++ *  This is called when dma IRQ occurs at the end of each transmited block
++ */
++void audio_dma_callback(void *data)
++{
++      struct audio_stream *s = data;
++
++      /* 
++       * If we are getting a callback for an active stream then we inform
++       * the PCM middle layer we've finished a period
++       */
++      if (s->active)
++              snd_pcm_period_elapsed(s->stream);
++
++      spin_lock(&s->dma_lock);
++      if (s->periods > 0) {
++              s->periods--;
++      }
++      audio_process_dma(s);
++      spin_unlock(&s->dma_lock);
++}
++
+ MODULE_AUTHOR("Texas Instruments");
+ MODULE_DESCRIPTION
+     ("Common DMA handling for Audio driver on OMAP processors");
+diff -Naur linux-2.6.14-omap2/sound/arm/omap-alsa-dma.h linux-h6300-omap2-2.6.14.3/sound/arm/omap-alsa-dma.h
+--- linux-2.6.14-omap2/sound/arm/omap-alsa-dma.h       2005-12-02 01:53:34.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/sound/arm/omap-alsa-dma.h       2005-11-13 02:15:10.000000000 +0200
+@@ -30,7 +30,13 @@
+ /************************** INCLUDES *************************************/
+-#include "omap-aic23.h"
++/* h6300 tsc2101 changes start */
++//#include "omap-aic23.h"
++#include <sound/driver.h>
++#include <asm/arch/dma.h>
++#include <sound/core.h>
++#include <sound/pcm.h>
++/* h6300 tsc2101 changes end */
+ /************************** GLOBAL MACROS *************************************/
+@@ -39,8 +45,33 @@
+ #define DMA_FREE(s)           omap_free_sound_dma(s, &s->lch)
+ #define DMA_CLEAR(s)          omap_clear_sound_dma(s)
++/* h6300 tsc2101 changes start */
++#define DMA_BUF_SIZE  1024 * 8
++
+ /************************** GLOBAL DATA STRUCTURES *********************************/
++/*
++ * Buffer management for alsa and dma
++ */
++struct audio_stream {
++      char *id;               /* identification string */
++      int stream_id;          /* numeric identification */
++      int dma_dev;            /* dma number of that device */
++      int *lch;               /* Chain of channels this stream is linked to */
++      char started;           /* to store if the chain was started or not */
++      int dma_q_head;         /* DMA Channel Q Head */
++      int dma_q_tail;         /* DMA Channel Q Tail */
++      char dma_q_count;       /* DMA Channel Q Count */
++      int active:1;           /* we are using this stream for transfer now */
++      int period;             /* current transfer period */
++      int periods;            /* current count of periods registerd in the DMA engine */
++      spinlock_t dma_lock;    /* for locking in DMA operations */
++      snd_pcm_substream_t *stream;    /* the pcm stream */
++      unsigned linked:1;      /* dma channels linked */
++      int offset;             /* store start position of the last period in the alsa buffer */
++};
++/* h6300 tsc2101 changes end */
++
+ typedef void (*dma_callback_t) (int lch, u16 ch_status, void *data);
+ /**************** ARCH SPECIFIC FUNCIONS *******************************************/
+@@ -54,6 +85,14 @@
+ int omap_start_sound_dma(struct audio_stream *s, dma_addr_t dma_ptr,
+                        u_int dma_size);
++/* h6300 tsc2101 changes start */
+ void omap_audio_stop_dma(struct audio_stream *s);
++void audio_dma_callback(void *);
++void audio_process_dma(struct audio_stream *s);
++u_int audio_get_dma_pos(struct audio_stream *s);
++int audio_dma_request(struct audio_stream *s, void (*callback) (void *));
++int audio_dma_free(struct audio_stream *s);
++void audio_stop_dma(struct audio_stream *s);
++/* h6300 tsc2101 changes end */
+ #endif
+diff -Naur linux-2.6.14-omap2/sound/arm/omap-tsc2101.c linux-h6300-omap2-2.6.14.3/sound/arm/omap-tsc2101.c
+--- linux-2.6.14-omap2/sound/arm/omap-tsc2101.c        1970-01-01 02:00:00.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/sound/arm/omap-tsc2101.c        2005-11-13 02:15:10.000000000 +0200
+@@ -0,0 +1,665 @@
++#include <linux/config.h>
++#include <sound/driver.h>
++#include <linux/module.h>
++#include <linux/device.h>
++#include <linux/moduleparam.h>
++#include <linux/init.h>
++#include <linux/errno.h>
++#include <linux/ioctl.h>
++#include <linux/delay.h>
++#include <linux/slab.h>
++
++#ifdef CONFIG_PM
++#include <linux/pm.h>
++#endif
++
++#include <asm/hardware.h>
++#include <asm/mach-types.h>
++#include <asm/arch/dma.h>
++#include <asm/hardware/tsc2101.h>
++#include <../drivers/ssi/omap-tsc2101.h>
++#include <asm/arch/mcbsp.h>
++
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/initval.h>
++#include <sound/memalloc.h>
++
++#include "omap-alsa-dma.h"
++#include "omap-tsc2101.h"
++
++//#undef DEBUG
++#define DEBUG
++
++#ifdef DEBUG
++#define ADEBUG() printk("XXX Alsa debug f:%s, l:%d\n", __FUNCTION__, __LINE__)
++#else
++#define ADEBUG()              /* nop */
++#endif
++
++#define TSC2101_MASTER
++
++#define DEFAULT_BITPERSAMPLE          16
++#define AUDIO_RATE_DEFAULT              44100
++#define AUDIO_MCBSP                   OMAP_MCBSP1
++#define NUMBER_SAMPLE_RATES_SUPPORTED 16
++#define PAGE2_AUDIO_CODEC_REGISTERS   (2)
++
++MODULE_AUTHOR("Everett Coleman, Daniel Petrini, David Cohen, Anderson Briglia - INdT");
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("OMAP TSC2101 driver for ALSA");
++MODULE_SUPPORTED_DEVICE("{{TSC2101,OMAP TSC2101}}");
++MODULE_ALIAS("omap_mcbsp.1");
++
++static char *id = NULL;       
++MODULE_PARM_DESC(id, "OMAP ALSA Driver for TSC2101 chip.");
++
++static struct snd_card_omap_tsc2101 *omap_tsc2101 = NULL;
++
++static struct omap_mcbsp_reg_cfg initial_config_mcbsp = {
++#ifdef CONFIG_MACH_H6300
++      .spcr2 = 0x0005,
++      .spcr1 = 0x0005,
++      .rcr2  = 0x8041,
++      .rcr1  = 0x8041,
++      .xcr2  = 0x00a1,
++      .xcr1  = 0x00a1,
++      .srgr2 = 0xb000,
++      .srgr1 = 0xb000,
++      .pcr0  = 0x0081,
++#else
++      .spcr2 = FREE | FRST | GRST | XRST | XINTM(3),
++      .spcr1 = RINTM(3) | RRST,
++      .rcr2  = RPHASE | RFRLEN2(OMAP_MCBSP_WORD_8) |
++               RWDLEN2(OMAP_MCBSP_WORD_16) | RDATDLY(1),
++      .rcr1  = RFRLEN1(OMAP_MCBSP_WORD_8) | RWDLEN1(OMAP_MCBSP_WORD_16),
++      .xcr2  = XPHASE | XFRLEN2(OMAP_MCBSP_WORD_8) |
++               XWDLEN2(OMAP_MCBSP_WORD_16) | XDATDLY(1) | XFIG,
++      .xcr1  = XFRLEN1(OMAP_MCBSP_WORD_8) | XWDLEN1(OMAP_MCBSP_WORD_16),
++      .srgr1 = FWID(15),
++      .srgr2 = GSYNC | CLKSP | FSGM | FPER(31),
++
++      /* platform specific initialization */
++# if defined(CONFIG_MACH_OMAP_H2)
++      .pcr0  = CLKXM | CLKRM | FSXP | FSRP | CLKXP | CLKRP,
++# elif defined(CONFIG_MACH_OMAP_H3)
++
++#  ifndef TSC2101_MASTER
++      .pcr0  = FSXM | FSRM | CLKXM | CLKRM | CLKXP | CLKRP,
++#  else
++      .pcr0  = CLKRM | SCLKME | FSXP | FSRP | CLKXP | CLKRP,
++#  endif /* !TSC2101_MASTER */
++# endif       /* CONFIG_MACH_OMAP_H2 */
++#endif /* CONFIG_MACH_H6300 */
++};
++
++static unsigned int rates[] = {
++      7350,  8000,  8018,  8727,  
++      8820,  9600,  11025, 12000, 
++      14700, 16000, 22050, 24000, 
++      29400, 32000, 44100, 48000
++};
++
++static snd_pcm_hw_constraint_list_t hw_constraints_rates = {
++      .count = ARRAY_SIZE(rates),
++      .list = rates,
++      .mask = 0,
++};
++
++struct sample_rate_reg_info {
++      u16 sample_rate;
++      u8  divisor;
++      u8  fs_44kHz;
++};
++
++static const struct sample_rate_reg_info
++reg_info[NUMBER_SAMPLE_RATES_SUPPORTED] = {
++      {48000, 0, 0}, {44100, 0, 1}, {32000, 1, 0}, {29400, 1, 1},
++      {24000, 2, 0}, {22050, 2, 1}, {16000, 3, 0}, {14700, 3, 1},
++      {12000, 4, 0}, {11025, 4, 1}, {9600,  5, 0}, {8820,  5, 1},
++      {8727,  6, 0}, {8018,  6, 1}, {8000,  7, 0}, {7350,  7, 1}
++};
++
++static snd_pcm_hardware_t snd_omap_tsc2101_capture = {
++      .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
++               SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID),
++      .formats = (SNDRV_PCM_FMTBIT_S16_LE),
++      .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
++                SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 |
++                SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
++                SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
++                SNDRV_PCM_RATE_KNOT),
++      .rate_min = 7350,
++      .rate_max = 48000,
++      .channels_min = 2,
++      .channels_max = 2,
++      .buffer_bytes_max = 128 * 1024,
++      .period_bytes_min = 32,
++      .period_bytes_max = 8 * 1024,
++      .periods_min = 16,
++      .periods_max = 255,
++      .fifo_size = 0,
++};
++
++static snd_pcm_hardware_t snd_omap_tsc2101_playback = {
++      .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
++               SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID),      
++      .formats = (SNDRV_PCM_FMTBIT_S16_LE),
++      .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
++                SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 |
++                SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
++                SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
++                SNDRV_PCM_RATE_KNOT),
++      .rate_min = 7350,
++      .rate_max = 48000,
++      .channels_min = 2,
++      .channels_max = 2,
++      .buffer_bytes_max = 128 * 1024,
++      .period_bytes_min = 32,
++      .period_bytes_max = 8 * 1024,
++      .periods_min = 16,
++      .periods_max = 255,
++      .fifo_size = 0,
++};
++
++static __inline__ void
++audio_tsc2101_write (u8 address, u16 data) {
++      omap_tsc2101_write (PAGE2_AUDIO_CODEC_REGISTERS, address, data);
++} /* audio_tsc2101_write */
++
++static __inline__ u16
++audio_tsc2101_read (u8 address) {
++      return (omap_tsc2101_read(PAGE2_AUDIO_CODEC_REGISTERS, address));
++} /* audio_tsc2101_read */
++
++
++
++
++
++
++
++
++
++
++void
++snd_omap_tsc2101_free (snd_card_t * card) {
++      struct snd_card_omap_tsc2101 *chip = card->private_data;
++      ADEBUG();
++      
++      /* TODO
++       * Turn off codec after it is done.
++       * Can't do it immediately, since it may still have
++       * buffered data.
++       */
++
++
++
++
++      audio_dma_free (&chip->s[SNDRV_PCM_STREAM_PLAYBACK]);
++      audio_dma_free (&chip->s[SNDRV_PCM_STREAM_CAPTURE]);
++} /* snd_omap_tsc2101_free */
++
++#ifdef CONFIG_PM
++static int
++snd_omap_tsc2101_suspend (snd_card_t * card, pm_message_t state) {
++      // TODO: function
++      return 0;
++} /* snd_omap_tsc2101_suspend */
++
++static int
++snd_omap_tsc2101_resume (snd_card_t * card) {
++      // TODO: function
++      return 0;
++} /* snd_omap_tsc2101_resume */
++
++static int
++omap_tsc2101_suspend (struct device *dev, pm_message_t state, u32 level) {
++      // TODO: function
++      return 0;
++} /* omap_tsc2101_suspend */
++
++static int
++omap_tsc2101_resume (struct device *dev, u32 level) {
++      // TODO: function
++      return 0;
++} /* omap_tsc2101_resume */
++
++#else
++# define snd_omap_tsc2101_suspend NULL
++# define snd_omap_tsc2101_resume  NULL
++# define omap_tsc2101_suspend     NULL
++# define omap_tsc2101_resume      NULL
++#endif        /* CONFIG_PM */
++
++static inline void
++tsc2101_configure (void) {
++      audio_tsc2101_write (TSC2101_CODEC_POWER_CTRL, 0x0000);
++
++      /*Mute Analog Sidetone */
++      /*Select MIC_INHED input for headset */
++      /*Cell Phone In not connected */
++      audio_tsc2101_write (TSC2101_MIXER_PGA_CTRL,
++                          MPC_ASTMU | MPC_ASTG(0x40) | MPC_MICADC);
++
++      /* Set record source */
++      // TODO:MIXER tsc2101_update (SET_RECSRC, tsc2101_local.recsrc);
++
++      /* ADC, DAC, Analog Sidetone, cellphone, buzzer softstepping enabled */
++      /* 1dB AGC hysteresis */
++      /* MICes bias 2V */
++      audio_tsc2101_write (TSC2101_AUDIO_CTRL_4, AC4_MB_HED(0));
++
++      /* Set codec output volume */
++      audio_tsc2101_write (TSC2101_DAC_GAIN_CTRL, 0x0000);
++
++      /* DAC left and right routed to SPK2 */
++      /* SPK1/2 unmuted */
++      audio_tsc2101_write (TSC2101_AUDIO_CTRL_5,
++                          AC5_DAC2SPK1(3) | AC5_AST2SPK1 | AC5_KCL2SPK1 |
++                          AC5_DAC2SPK2(3) | AC5_AST2SPK2 | AC5_KCL2SPK2 |
++                          AC5_HDSCPTC);
++
++      /* OUT8P/N muted, CPOUT muted */
++
++      audio_tsc2101_write (TSC2101_AUDIO_CTRL_6,
++                          AC6_MUTLSPK | AC6_MUTSPK2 | AC6_LDSCPTC |
++                          AC6_VGNDSCPTC);
++
++      /* Headset/Hook switch detect disabled */
++      audio_tsc2101_write (TSC2101_AUDIO_CTRL_7, 0x0000);
++
++      /* Left line input volume control */
++      // TODO:MIXER tsc2101_update (SET_LINE, tsc2101_local.line);
++
++      /* mic input volume control */
++      // TODO:MIXER tsc2101_update(SET_MIC, tsc2101_local.mic);
++
++      /* Left/Right headphone channel volume control */
++      /* Zero-cross detect on */
++      // TODO:MIXER tsc2101_update (SET_VOLUME, tsc2101_local.volume);
++} /* tsc2101_configure */
++
++static int
++snd_card_omap_tsc2101_open (snd_pcm_substream_t * substream) {
++      struct snd_card_omap_tsc2101 *chip = snd_pcm_substream_chip(substream);
++      snd_pcm_runtime_t *runtime = substream->runtime;
++      int stream_id = substream->pstr->stream;
++      int err;
++      ADEBUG();
++
++      chip->s[stream_id].stream = substream;
++      
++//    TODO: turn audio on, power on
++      
++      if (stream_id == SNDRV_PCM_STREAM_PLAYBACK)
++              runtime->hw = snd_omap_tsc2101_playback;
++      else
++              runtime->hw = snd_omap_tsc2101_capture;
++      if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
++              return err;
++      if ((err = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates)) < 0)
++              return err;
++      return 0;
++} /* snd_card_omap_tsc2101_open */
++
++static int
++snd_card_omap_tsc2101_close (snd_pcm_substream_t *substream) {
++      struct snd_card_omap_tsc2101 *chip = snd_pcm_substream_chip(substream);
++      ADEBUG();
++      
++      // TODO: omap_tsc2101_clock_off();
++      chip->s[substream->pstr->stream].stream = NULL;
++      return 0;
++} /* snd_card_omap_tsc2101_close */
++
++static int
++snd_omap_tsc2101_hw_params (snd_pcm_substream_t *substream, snd_pcm_hw_params_t *hw_params) {
++      return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
++} /* snd_omap_tsc2101_hw_params */
++
++static int
++snd_omap_tsc2101_hw_free (snd_pcm_substream_t *substream) {
++      return snd_pcm_lib_free_pages(substream);
++} /* snd_omap_tsc2101_hw_free */
++
++static int
++omap_tsc2101_set_samplerate (struct snd_card_omap_tsc2101 *omap_tsc2101, long rate) {
++      u8 count = 0;
++      u16 data = 0;
++      int clkgdv = 0;
++
++      if (rate >= 48000)
++              rate = 48000;
++      else if (rate >= 44100)
++              rate = 44100;
++      else if (rate >= 32000)
++              rate = 32000;
++      else if (rate >= 29400)
++              rate = 29400;
++      else if (rate >= 24000)
++              rate = 24000;
++      else if (rate >= 22050)
++              rate = 22050;
++      else if (rate >= 16000)
++              rate = 16000;
++      else if (rate >= 14700)
++              rate = 14700;
++      else if (rate >= 12000)
++              rate = 12000;
++      else if (rate >= 11025)
++              rate = 11025;
++      else if (rate >= 9600)
++              rate = 9600;
++      else if (rate >= 8820)
++              rate = 8820;
++      else if (rate >= 8727)
++              rate = 8727;
++      else if (rate >= 8018)
++              rate = 8018;
++      else if (rate >= 8000)
++              rate = 8000;
++      else
++              rate = 7350;
++
++      /* wait for any frame to complete */
++      udelay(125);
++
++      /* Search for the right sample rate */
++      while ((reg_info[count].sample_rate != rate) &&
++             (count < NUMBER_SAMPLE_RATES_SUPPORTED)) {
++              count++;
++      }
++      if (count == NUMBER_SAMPLE_RATES_SUPPORTED) {
++              printk(KERN_ERR "Invalid Sample Rate %d requested\n",
++                     (int)rate);
++              return -EPERM;
++      }
++
++      /* Set AC1 */
++      data = audio_tsc2101_read(TSC2101_AUDIO_CTRL_1);
++      /*Clear prev settings */
++      data &= ~(AC1_DACFS(0x07) | AC1_ADCFS(0x07));
++      data |=
++          AC1_DACFS(reg_info[count].divisor) | AC1_ADCFS(reg_info[count].
++                                                         divisor);
++      audio_tsc2101_write(TSC2101_AUDIO_CTRL_1, data);
++
++      /* Set the AC3 */
++      data = audio_tsc2101_read(TSC2101_AUDIO_CTRL_3);
++      /*Clear prev settings */
++      data &= ~(AC3_REFFS | AC3_SLVMS);
++      data |= (reg_info[count].fs_44kHz) ? AC3_REFFS : 0;
++#ifdef TSC2101_MASTER
++      data |= AC3_SLVMS;
++#endif                                /* #ifdef TSC2101_MASTER */
++      audio_tsc2101_write(TSC2101_AUDIO_CTRL_3, data);
++
++      /* program the PLLs */
++      if (reg_info[count].fs_44kHz) {
++              /* 44.1 khz - 12 MHz Mclk */
++              audio_tsc2101_write(TSC2101_PLL_PROG_1, PLL1_PLLSEL | PLL1_PVAL(1) | PLL1_I_VAL(7));    /* PVAL 1; I_VAL 7 */
++              audio_tsc2101_write(TSC2101_PLL_PROG_2, PLL2_D_VAL(0x1490));    /* D_VAL 5264 */
++      } else {
++              /* 48 khz - 12 Mhz Mclk */
++              audio_tsc2101_write(TSC2101_PLL_PROG_1, PLL1_PLLSEL | PLL1_PVAL(1) | PLL1_I_VAL(8));    /* PVAL 1; I_VAL 8 */
++              audio_tsc2101_write(TSC2101_PLL_PROG_2, PLL2_D_VAL(0x780));     /* D_VAL 1920 */
++      }
++
++      omap_tsc2101->samplerate = rate;
++
++      /* Set the sample rate */
++#ifndef TSC2101_MASTER
++      clkgdv =
++          DEFAULT_MCBSP_CLOCK / (rate *
++                                 (DEFAULT_BITPERSAMPLE * 2 - 1));
++      if (clkgdv)
++              initial_config_mcbsp.srgr1 =
++                  (FWID(DEFAULT_BITPERSAMPLE - 1) | CLKGDV(clkgdv));
++      else
++              return (1);
++
++      /* Stereo Mode */
++      initial_config_mcbsp.srgr2 =
++          (CLKSM | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1));
++#else
++      initial_config_mcbsp.srgr1 =
++          (FWID(DEFAULT_BITPERSAMPLE - 1) | CLKGDV(clkgdv));
++      initial_config_mcbsp.srgr2 =
++          ((GSYNC | CLKSP | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1)));
++
++#endif                                /* end of #ifdef TSC2101_MASTER */
++      omap_mcbsp_config(AUDIO_MCBSP, &initial_config_mcbsp);
++      return 0;
++} /* omap_tsc2101_set_samplerate */
++
++static int
++snd_omap_tsc2101_prepare (snd_pcm_substream_t *substream) {
++      struct snd_card_omap_tsc2101 *chip = snd_pcm_substream_chip(substream);
++      snd_pcm_runtime_t *runtime = substream->runtime;
++      struct audio_stream *s = &chip->s[substream->pstr->stream];
++
++      /* set requested samplerate */
++      omap_tsc2101_set_samplerate (chip, runtime->rate);
++
++      s->period = 0;
++      s->periods = 0;
++      return 0;
++} /* snd_omap_tsc2101_prepare */
++
++static int
++snd_omap_tsc2101_trigger (snd_pcm_substream_t *substream, int cmd) {
++      struct snd_card_omap_tsc2101 *chip = snd_pcm_substream_chip(substream);
++      int stream_id = substream->pstr->stream;
++      struct audio_stream *s = &chip->s[stream_id];
++      int err = 0;
++      ADEBUG();
++
++      /* note local interrupts are already disabled in the midlevel code */
++      spin_lock(&s->dma_lock);
++      switch (cmd) {
++      case SNDRV_PCM_TRIGGER_START:
++              /* requested stream startup */
++              s->active = 1;
++              audio_process_dma(s);
++              break;
++      case SNDRV_PCM_TRIGGER_STOP:
++              /* requested stream shutdown */
++              audio_stop_dma(s);
++              break;
++      default:
++              err = -EINVAL;
++              break;
++      }
++      spin_unlock(&s->dma_lock);
++      return err;
++} /* snd_omap_tsc2101_trigger */
++
++static snd_pcm_uframes_t
++snd_omap_tsc2101_pointer (snd_pcm_substream_t *substream) {
++      struct snd_card_omap_tsc2101 *chip = snd_pcm_substream_chip(substream);
++      return audio_get_dma_pos(&chip->s[substream->pstr->stream]);
++} /* snd_omap_tsc2101_pointer */
++
++static snd_pcm_ops_t snd_card_omap_tsc2101_playback_ops = {
++      .open      = snd_card_omap_tsc2101_open,
++      .close     = snd_card_omap_tsc2101_close,
++      .ioctl     = snd_pcm_lib_ioctl,
++      .hw_params = snd_omap_tsc2101_hw_params,
++      .hw_free   = snd_omap_tsc2101_hw_free,
++      .prepare   = snd_omap_tsc2101_prepare,
++      .trigger   = snd_omap_tsc2101_trigger,
++      .pointer   = snd_omap_tsc2101_pointer,
++};
++
++static snd_pcm_ops_t snd_card_omap_tsc2101_capture_ops = {
++      .open      = snd_card_omap_tsc2101_open,
++      .close     = snd_card_omap_tsc2101_close,
++      .ioctl     = snd_pcm_lib_ioctl,
++      .hw_params = snd_omap_tsc2101_hw_params,
++      .hw_free   = snd_omap_tsc2101_hw_free,
++      .prepare   = snd_omap_tsc2101_prepare,
++      .trigger   = snd_omap_tsc2101_trigger,
++      .pointer   = snd_omap_tsc2101_pointer,
++};
++
++static void
++omap_tsc2101_audio_init (struct snd_card_omap_tsc2101 *omap_tsc2101) {
++      /* Setup DMA stuff */
++      omap_tsc2101->s[SNDRV_PCM_STREAM_PLAYBACK].id = "Alsa TSC2101 out";
++      omap_tsc2101->s[SNDRV_PCM_STREAM_PLAYBACK].stream_id =
++          SNDRV_PCM_STREAM_PLAYBACK;
++      omap_tsc2101->s[SNDRV_PCM_STREAM_PLAYBACK].dma_dev =
++          OMAP_DMA_MCBSP1_TX;
++
++      omap_tsc2101->s[SNDRV_PCM_STREAM_CAPTURE].id = "Alsa TSC2101 in";
++      omap_tsc2101->s[SNDRV_PCM_STREAM_CAPTURE].stream_id =
++          SNDRV_PCM_STREAM_CAPTURE;
++      omap_tsc2101->s[SNDRV_PCM_STREAM_CAPTURE].dma_dev =
++          OMAP_DMA_MCBSP1_RX;
++
++      /* configuring the McBSP */
++      omap_mcbsp_request (AUDIO_MCBSP);
++
++      /* if configured, then stop mcbsp */
++      omap_mcbsp_stop (AUDIO_MCBSP);
++
++      omap_mcbsp_config (AUDIO_MCBSP, &initial_config_mcbsp);
++      omap_mcbsp_start (AUDIO_MCBSP);
++
++      tsc2101_configure ();
++} /* omap_tsc2101_audio_init */
++
++static int __init
++snd_card_omap_tsc2101_pcm (struct snd_card_omap_tsc2101 *omap_tsc2101, int device) {
++      snd_pcm_t *pcm;
++      int err;
++      ADEBUG();
++
++      if ((err = snd_pcm_new (omap_tsc2101->card, "TSC2101 PCM", device, 1, 1, &pcm)) < 0)
++              return err;
++
++      snd_pcm_lib_preallocate_pages_for_all (pcm,
++                      SNDRV_DMA_TYPE_CONTINUOUS,
++                      snd_dma_continuous_data (GFP_KERNEL),
++                      128 * 1024, 128 * 1024);
++
++      snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
++                      &snd_card_omap_tsc2101_playback_ops);
++      snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
++                      &snd_card_omap_tsc2101_capture_ops);
++
++      pcm->private_data = omap_tsc2101;
++      pcm->info_flags = 0;
++      strcpy (pcm->name, "omap tsc2101 pcm");
++
++      omap_tsc2101_audio_init (omap_tsc2101);
++
++      audio_dma_request(&omap_tsc2101->s[SNDRV_PCM_STREAM_PLAYBACK],
++                        audio_dma_callback);
++      audio_dma_request(&omap_tsc2101->s[SNDRV_PCM_STREAM_CAPTURE],
++                        audio_dma_callback);
++
++      omap_tsc2101->pcm = pcm;
++      return 0;
++} /* snd_card_omap_tsc2101_pcm */
++
++static int __init
++snd_omap_tsc2101_probe (struct device *dev) {
++      int err = 0;
++      snd_card_t *card;
++      ADEBUG();
++
++      if ((card = snd_card_new (-1, id, THIS_MODULE, sizeof (omap_tsc2101))) == NULL)
++              return -ENOMEM;
++      if ((omap_tsc2101 = kcalloc (1, sizeof (*omap_tsc2101), GFP_KERNEL)) == NULL)
++              return -ENOMEM;
++
++      card->private_data = (void *)omap_tsc2101;
++      card->private_free = snd_omap_tsc2101_free;
++      omap_tsc2101->card       = card;
++      omap_tsc2101->samplerate = AUDIO_RATE_DEFAULT;
++
++      spin_lock_init(&omap_tsc2101->s[0].dma_lock);
++      spin_lock_init(&omap_tsc2101->s[1].dma_lock);
++
++      // TODO: setup mixer (fail, goto nodev)
++
++      if ((err = snd_card_omap_tsc2101_pcm (omap_tsc2101, 0)) < 0)
++              goto nodev;
++
++      snd_card_set_pm_callback (card, snd_omap_tsc2101_suspend, snd_omap_tsc2101_resume, omap_tsc2101);
++
++      strcpy (card->driver,    "TSC2101");
++      strcpy (card->shortname, "TI TSC2101");
++      strcpy (card->longname,  "TI OMAP TSC2101");
++
++      // TODO: init mixer
++
++      if ((err = snd_card_register (card)) == 0) {
++              printk(KERN_INFO "TSC2101 audio support initialized\n");
++              dev_set_drvdata(dev, card); 
++              return 0;
++      }
++      
++nodev:
++      printk  (KERN_ERR "failed to initialize TSC2101\n");
++      snd_omap_tsc2101_free (card);
++      return err;
++} /* snd_omap_tsc2101_probe */
++
++static int
++snd_omap_tsc2101_remove (struct device *dev) {
++      snd_card_t *card = dev_get_drvdata(dev);
++      struct snd_card_omap_tsc2101 *chip = card->private_data;
++      
++      snd_card_free(card);
++      omap_tsc2101       = NULL;
++      card->private_data = NULL;
++      kfree (chip);
++      dev_set_drvdata (dev, NULL); 
++      return 0;
++} /* snd_omap_tsc2101_remove */
++
++static struct device_driver omap_alsa_driver = {
++      .name    = "omap_mcbsp",
++      .bus     = &platform_bus_type,
++      .probe   = snd_omap_tsc2101_probe,
++      .remove  = snd_omap_tsc2101_remove,
++      .suspend = omap_tsc2101_suspend, 
++      .resume  = omap_tsc2101_resume, 
++};
++
++static void
++omap_alsa_device_release (struct device *dev) {
++      /* Nothing */
++}
++
++static struct platform_device omap_alsa_device = {
++      .name = "omap_mcbsp",
++      .id   = -1,
++      .dev  = {
++              .release = omap_alsa_device_release,
++      },
++};
++
++static int __init
++omap_tsc2101_init (void) {
++      int err;
++
++      ADEBUG();
++      if ((err = platform_device_register (&omap_alsa_device)) != 0)
++              return err;
++      if ((err = driver_register (&omap_alsa_driver)) != 0)
++              platform_device_unregister (&omap_alsa_device);
++      return err;
++} /* omap_tsc2101_init */
++
++static void __exit
++omap_tsc2101_exit (void) {
++      ADEBUG();
++      driver_unregister (&omap_alsa_driver);
++      platform_device_unregister (&omap_alsa_device);
++} /* omap_tsc2101_exit */
++
++module_init (omap_tsc2101_init);
++module_exit (omap_tsc2101_exit);
+diff -Naur linux-2.6.14-omap2/sound/arm/omap-tsc2101.h linux-h6300-omap2-2.6.14.3/sound/arm/omap-tsc2101.h
+--- linux-2.6.14-omap2/sound/arm/omap-tsc2101.h        1970-01-01 02:00:00.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/sound/arm/omap-tsc2101.h        2005-11-13 02:15:10.000000000 +0200
+@@ -0,0 +1,13 @@
++#ifndef __OMAP_AUDIO_TSC2101_H
++#define __OMAP_AUDIO_TSC2101_H
++
++# include "omap-alsa-dma.h"
++
++struct snd_card_omap_tsc2101 {
++      snd_card_t *card;
++      snd_pcm_t *pcm;
++      long samplerate;
++      struct audio_stream s[2];       /* playback & capture */
++};
++
++#endif /* __OMAP_AUDIO_TSC2101_H */
+diff -Naur linux-2.6.14-omap2/sound/oss/Kconfig linux-h6300-omap2-2.6.14.3/sound/oss/Kconfig
+--- linux-2.6.14-omap2/sound/oss/Kconfig       2005-12-02 01:53:34.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/sound/oss/Kconfig       2005-10-22 03:52:45.000000000 +0300
+@@ -12,7 +12,7 @@
+ config SOUND_OMAP_TSC2101
+       tristate "TSC2101 Stereo Codec"
+-      depends on SOUND_OMAP && ( MACH_OMAP_H2 || MACH_OMAP_H3 )
++      depends on SOUND_OMAP && ( MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_H6300)
+       select OMAP_TSC2101
+       select OMAP_UWIRE if ARCH_OMAP
+       ---help---
+diff -Naur linux-2.6.14-omap2/sound/oss/omap-audio-tsc2101.c linux-h6300-omap2-2.6.14.3/sound/oss/omap-audio-tsc2101.c
+--- linux-2.6.14-omap2/sound/oss/omap-audio-tsc2101.c  2005-12-02 01:53:34.000000000 +0200
++++ linux-h6300-omap2-2.6.14.3/sound/oss/omap-audio-tsc2101.c  2005-10-22 03:52:45.000000000 +0300
+@@ -48,7 +48,7 @@
+ #include "omap-audio.h"
+ #include "omap-audio-dma-intfc.h"
+ #include <asm/arch/mcbsp.h>
+-#if CONFIG_ARCH_OMAP16XX
++#if defined (CONFIG_ARCH_OMAP16XX) || defined (CONFIG_MACH_OMAP_H6300)
+ #include <../drivers/ssi/omap-uwire.h>
+ #include <asm/arch/dsp_common.h>
+ #else
+@@ -72,6 +72,8 @@
+ #if CONFIG_ARCH_OMAP16XX
+ #define PLATFORM_NAME "OMAP16XX"
++#elif CONFIG_MACH_OMAP_H6300
++#define PLATFORM_NAME "OMAP15XX"
+ #endif
+ #if CONFIG_ARCH_OMAP16XX
+@@ -90,7 +92,7 @@
+ #define LEAVE_CS                                0x80
+ /* Select the McBSP For Audio */
+-#if CONFIG_ARCH_OMAP16XX
++#if defined (CONFIG_ARCH_OMAP16XX) || defined(CONFIG_MACH_OMAP_H6300)
+ #define AUDIO_MCBSP                   OMAP_MCBSP1
+ #else
+ #error "UnSupported Configuration"
+@@ -124,7 +126,7 @@
+ /*********** Debug Macros ********/
+ /* To Generate a rather shrill tone -test the entire path */
+ //#define TONE_GEN
+-/* To Generate a tone for each keyclick - test the tsc,spi paths*/
++///* To Generate a tone for each keyclick - test the tsc,spi paths*/
+ //#define TEST_KEYCLICK
+ /* To dump the tsc registers for debug */
+ //#define TSC_DUMP_REGISTERS
+@@ -215,6 +217,17 @@
+ };
+ static struct omap_mcbsp_reg_cfg initial_config = {
++#ifdef CONFIG_MACH_OMAP_H6300
++      .spcr2 = 0x0005,
++      .spcr1 = 0x0005,
++      .rcr2  = 0x8041,
++      .rcr1  = 0x8041,
++      .xcr2  = 0x00a1,
++      .xcr1  = 0x00a1,
++      .srgr2 = 0xb000,
++      .srgr1 = 0xb000,
++      .pcr0  = 0x0081,
++#else
+       .spcr2 = FREE | FRST | GRST | XRST | XINTM(3),
+       .spcr1 = RINTM(3) | RRST,
+       .rcr2  = RPHASE | RFRLEN2(OMAP_MCBSP_WORD_8) |
+@@ -238,6 +251,7 @@
+ #endif                                /* tsc Master defs */
+ #endif                                /* platform specific inits */
++#endif /* CONFIG_MACH_OMAP_H6300 */
+ };
+ /***************************** MODULES SPECIFIC FUNCTION PROTOTYPES ********************/
diff --git a/packages/linux/linux-h6300-omap1_2.6.14-rc5.bb b/packages/linux/linux-h6300-omap1_2.6.14-rc5.bb
deleted file mode 100644 (file)
index 5053f95..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-DESCRIPTION = "Linux kernel for h6300 devices."
-MAINTAINER = "Mika Laitio <lamikr@cc.jyu.fi>"
-SECTION = "kernel"
-LICENSE = "GPL"
-
-SRC_URI = "http://www.kernel.org/pub/linux/kernel/v2.6/testing/linux-2.6.14-rc5.tar.bz2 \
-           http://www.muru.com/linux/omap/patches/patch-2.6.14-rc5-omap1.bz2;patch=1 \
-           file://h6300_omap1_2614rc5.patch;patch=1 \
-           file://defconfig"
-
-S = "${WORKDIR}/linux-2.6.14-rc5"
-
-inherit kernel
-
-do_configure_prepend() {
-       install -m 0644 ${WORKDIR}/defconfig ${S}/.config
-        oe_runmake oldconfig
-}
diff --git a/packages/linux/linux-h6300-omap1_2.6.14.3.bb b/packages/linux/linux-h6300-omap1_2.6.14.3.bb
new file mode 100644 (file)
index 0000000..3e40f12
--- /dev/null
@@ -0,0 +1,18 @@
+DESCRIPTION = "Linux kernel for h6300 devices."
+MAINTAINER = "Mika Laitio <lamikr@cc.jyu.fi>"
+SECTION = "kernel"
+LICENSE = "GPL"
+
+SRC_URI = "http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.14.tar.bz2 \
+           http://www.muru.com/linux/omap/patches/patch-2.6.14-omap2.bz2;patch=1 \
+           file://patch-linux-2614-omap2-to-2614_3-omap1-h6300;patch=1 \
+           file://defconfig"
+
+S = "${WORKDIR}/linux-2.6.14"
+
+inherit kernel
+
+do_configure_prepend() {
+       install -m 0644 ${WORKDIR}/defconfig ${S}/.config
+        oe_runmake oldconfig
+}