summaryrefslogtreecommitdiff
path: root/packages/linux/linux-h6300-omap1-2.6.14.3
diff options
context:
space:
mode:
authorDenys Dmytriyenko <denis@denix.org>2009-03-17 14:32:59 -0400
committerDenys Dmytriyenko <denis@denix.org>2009-03-17 14:32:59 -0400
commit709c4d66e0b107ca606941b988bad717c0b45d9b (patch)
tree37ee08b1eb308f3b2b6426d5793545c38396b838 /packages/linux/linux-h6300-omap1-2.6.14.3
parentfa6cd5a3b993f16c27de4ff82b42684516d433ba (diff)
rename packages/ to recipes/ per earlier agreement
See links below for more details: http://thread.gmane.org/gmane.comp.handhelds.openembedded/21326 http://thread.gmane.org/gmane.comp.handhelds.openembedded/21816 Signed-off-by: Denys Dmytriyenko <denis@denix.org> Acked-by: Mike Westerhof <mwester@dls.net> Acked-by: Philip Balister <philip@balister.org> Acked-by: Khem Raj <raj.khem@gmail.com> Acked-by: Marcin Juszkiewicz <hrw@openembedded.org> Acked-by: Koen Kooi <koen@openembedded.org> Acked-by: Frans Meulenbroeks <fransmeulenbroeks@gmail.com>
Diffstat (limited to 'packages/linux/linux-h6300-omap1-2.6.14.3')
-rw-r--r--packages/linux/linux-h6300-omap1-2.6.14.3/defconfig1568
-rw-r--r--packages/linux/linux-h6300-omap1-2.6.14.3/patch-linux-2614-omap2-to-2614_3-omap1-h630032978
2 files changed, 0 insertions, 34546 deletions
diff --git a/packages/linux/linux-h6300-omap1-2.6.14.3/defconfig b/packages/linux/linux-h6300-omap1-2.6.14.3/defconfig
deleted file mode 100644
index 40f2840644..0000000000
--- a/packages/linux/linux-h6300-omap1-2.6.14.3/defconfig
+++ /dev/null
@@ -1,1568 +0,0 @@
-#
-# 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
deleted file mode 100644
index e7e442e7c2..0000000000
--- a/packages/linux/linux-h6300-omap1-2.6.14.3/patch-linux-2614-omap2-to-2614_3-omap1-h6300
+++ /dev/null
@@ -1,32978 +0,0 @@
-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 ********************/