From 709c4d66e0b107ca606941b988bad717c0b45d9b Mon Sep 17 00:00:00 2001 From: Denys Dmytriyenko Date: Tue, 17 Mar 2009 14:32:59 -0400 Subject: 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 Acked-by: Mike Westerhof Acked-by: Philip Balister Acked-by: Khem Raj Acked-by: Marcin Juszkiewicz Acked-by: Koen Kooi Acked-by: Frans Meulenbroeks --- .../linux/linux-h6300-omap1-2.6.14.3/defconfig | 1568 - .../patch-linux-2614-omap2-to-2614_3-omap1-h6300 | 32978 ------------------- 2 files changed, 34546 deletions(-) delete mode 100644 packages/linux/linux-h6300-omap1-2.6.14.3/defconfig delete mode 100644 packages/linux/linux-h6300-omap1-2.6.14.3/patch-linux-2614-omap2-to-2614_3-omap1-h6300 (limited to 'packages/linux/linux-h6300-omap1-2.6.14.3') 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 -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include -+#include -+ -+#include -+ -+#include -+ -+/* -+ * 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 ") */ -+ .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 - #include - #include -+#include - - #include - -@@ -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 **************************/ -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 -+ * 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 -+#include -+#include -+#include -+ -+#include -+#include -+ -+#include -+#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, "); -+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 -+ * 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 -+#include -+#include -+#include -+ -+#include -+#include -+ -+/* -+ * 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<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 -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+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 "); -+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 -+ * 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 - - #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 - #include - #include -+#include - - #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 - #include - -+#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 - #include - -+#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 ':' 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 : 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 -+/* #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 -+#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 /* request_firmware() */ -+#include /* 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 -+#include -+#include -+#include -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10) -+#include -+#endif -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#if WIRELESS_EXT >= 13 -+#include -+#endif -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#if WIRELESS_EXT >= 13 -+#include -+#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 "); */ -+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, "\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 -+#include -+#include -+#include -+#include -+#include -+#if WIRELESS_EXT >= 13 -+#include -+#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 -+#include -+#include -+#include -+#include -+#include /* required for 2.4.x kernels; verify_write() */ -+ -+#include -+#include -+#if WIRELESS_EXT >= 13 -+#include -+#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 ap 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 -+#include -+#include -+#include -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10) -+#include -+#endif -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#if WIRELESS_EXT >= 13 -+#include -+#endif -+#include -+#include -+#include -+#include -+ -+#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=DOT11_RATE_6) return DOT11_MOD_OFDM; */ -+ return default_modulation[r_enum]; -+ } -+ if(suffix=='c') { -+ if(r_enumDOT11_RATE_11) return -EINVAL; -+ return DOT11_MOD_CCK; -+ } -+ if(suffix=='p') { -+ if(r_enumDOT11_RATE_33) return -EINVAL; -+ return DOT11_MOD_PBCC; -+ } -+ if(suffix=='o') { -+ if(r_enumINT_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 -+** Andreas Mohr -+** -+** 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 -+#include -+#include -+#include -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10) -+#include -+#endif -+#include -+#include -+#include -+#include -+#include -+#include -+#if WIRELESS_EXT >= 13 -+#include -+#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 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 -+#include -+ -+#include -+#include -+#include -+#if WIRELESS_EXT >= 13 -+#include -+#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 - #include - #include -+#include - - #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 -+ * -+ * 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 -+#include -+#include -+#include -+ -+#include -+#include -+ -+/* -+ * 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 -+ * -+ * 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 -+#include -+#include -+#include -+ -+#include -+#include -+ -+#include -+#include -+#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, "); -+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 -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the 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 -+#include -+ -+#include -+#include -+ -+/* #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 -+ - #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 -+#include -+ -+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 - - 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 - - #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 "); - 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 - #include - #include -+#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 -+#include -+#include -+#include -+/* 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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#ifdef CONFIG_PM -+#include -+#endif -+ -+#include -+#include -+#include -+#include -+#include <../drivers/ssi/omap-tsc2101.h> -+#include -+ -+#include -+#include -+#include -+#include -+ -+#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 --#if CONFIG_ARCH_OMAP16XX -+#if defined (CONFIG_ARCH_OMAP16XX) || defined (CONFIG_MACH_OMAP_H6300) - #include <../drivers/ssi/omap-uwire.h> - #include - #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 ********************/ -- cgit v1.2.3