1 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
2 --- linux-2.6.14-omap2/arch/arm/configs/omap_h6300_defconfig 1970-01-01 02:00:00.000000000 +0200
3 +++ linux-h6300-omap2-2.6.14.3/arch/arm/configs/omap_h6300_defconfig 2005-11-11 04:13:42.000000000 +0200
6 +# Automatically generated make config: don't edit
7 +# Linux kernel version: 2.6.14-omap1-h6300
8 +# Thu Nov 10 05:21:43 2005
13 +CONFIG_RWSEM_GENERIC_SPINLOCK=y
14 +CONFIG_GENERIC_CALIBRATE_DELAY=y
17 +# Code maturity level options
19 +CONFIG_EXPERIMENTAL=y
20 +# CONFIG_CLEAN_COMPILE is not set
22 +CONFIG_BROKEN_ON_SMP=y
23 +CONFIG_INIT_ENV_ARG_LIMIT=32
28 +CONFIG_LOCALVERSION=""
29 +CONFIG_LOCALVERSION_AUTO=y
32 +CONFIG_POSIX_MQUEUE=y
33 +CONFIG_BSD_PROCESS_ACCT=y
34 +CONFIG_BSD_PROCESS_ACCT_V3=y
36 +# CONFIG_AUDIT is not set
38 +CONFIG_KOBJECT_UEVENT=y
40 +CONFIG_IKCONFIG_PROC=y
41 +CONFIG_INITRAMFS_SOURCE=""
44 +# CONFIG_KALLSYMS_ALL is not set
45 +# CONFIG_KALLSYMS_EXTRA_PASS is not set
51 +CONFIG_CC_OPTIMIZE_FOR_SIZE=y
53 +CONFIG_CC_ALIGN_FUNCTIONS=0
54 +CONFIG_CC_ALIGN_LABELS=0
55 +CONFIG_CC_ALIGN_LOOPS=0
56 +CONFIG_CC_ALIGN_JUMPS=0
57 +# CONFIG_TINY_SHMEM is not set
61 +# Loadable module support
64 +CONFIG_MODULE_UNLOAD=y
65 +CONFIG_MODULE_FORCE_UNLOAD=y
66 +CONFIG_OBSOLETE_MODPARM=y
67 +# CONFIG_MODVERSIONS is not set
68 +# CONFIG_MODULE_SRCVERSION_ALL is not set
74 +# CONFIG_ARCH_CLPS7500 is not set
75 +# CONFIG_ARCH_CLPS711X is not set
76 +# CONFIG_ARCH_CO285 is not set
77 +# CONFIG_ARCH_EBSA110 is not set
78 +# CONFIG_ARCH_CAMELOT is not set
79 +# CONFIG_ARCH_FOOTBRIDGE is not set
80 +# CONFIG_ARCH_INTEGRATOR is not set
81 +# CONFIG_ARCH_IOP3XX is not set
82 +# CONFIG_ARCH_IXP4XX is not set
83 +# CONFIG_ARCH_IXP2000 is not set
84 +# CONFIG_ARCH_L7200 is not set
85 +# CONFIG_ARCH_PXA is not set
86 +# CONFIG_ARCH_RPC is not set
87 +# CONFIG_ARCH_SA1100 is not set
88 +# CONFIG_ARCH_S3C2410 is not set
89 +# CONFIG_ARCH_SHARK is not set
90 +# CONFIG_ARCH_LH7A40X is not set
92 +# CONFIG_ARCH_VERSATILE is not set
93 +# CONFIG_ARCH_IMX is not set
94 +# CONFIG_ARCH_H720X is not set
95 +# CONFIG_ARCH_AAEC2000 is not set
98 +# TI OMAP Implementations
101 +# CONFIG_ARCH_OMAP2 is not set
104 +# OMAP Feature Selections
106 +# CONFIG_OMAP_RESET_CLOCKS is not set
107 +# CONFIG_OMAP_BOOT_TAG is not set
109 +# CONFIG_OMAP_MUX_DEBUG is not set
110 +CONFIG_OMAP_MUX_WARNINGS=y
111 +CONFIG_OMAP_MPU_TIMER=y
112 +# CONFIG_OMAP_32K_TIMER is not set
113 +CONFIG_OMAP_LL_DEBUG_UART1=y
114 +# CONFIG_OMAP_LL_DEBUG_UART2 is not set
115 +# CONFIG_OMAP_LL_DEBUG_UART3 is not set
116 +CONFIG_OMAP_SERIAL_WAKE=y
121 +# CONFIG_ARCH_OMAP730 is not set
122 +CONFIG_ARCH_OMAP15XX=y
123 +# CONFIG_ARCH_OMAP16XX is not set
128 +# CONFIG_MACH_OMAP_INNOVATOR is not set
129 +CONFIG_MACH_OMAP_H6300=y
130 +# CONFIG_MACH_VOICEBLUE is not set
131 +# CONFIG_MACH_NETSTAR is not set
132 +# CONFIG_MACH_OMAP_PALMTE is not set
133 +# CONFIG_MACH_OMAP_GENERIC is not set
138 +# CONFIG_OMAP_CLOCKS_SET_BY_BOOTLOADER is not set
139 +CONFIG_OMAP_ARM_168MHZ=y
140 +CONFIG_OMAP_ARM_150MHZ=y
141 +CONFIG_OMAP_ARM_120MHZ=y
142 +CONFIG_OMAP_ARM_60MHZ=y
143 +CONFIG_OMAP_ARM_30MHZ=y
145 +CONFIG_OMAP_DSP_MBCMD_VERBOSE=y
146 +CONFIG_OMAP_DSP_TASK_MULTIOPEN=y
147 +CONFIG_OMAP_DSP_FBEXPORT=y
153 +CONFIG_CPU_ARM925T=y
155 +CONFIG_CPU_ABRT_EV4T=y
156 +CONFIG_CPU_CACHE_V4WT=y
157 +CONFIG_CPU_CACHE_VIVT=y
158 +CONFIG_CPU_COPY_V4WB=y
159 +CONFIG_CPU_TLB_V4WBI=y
162 +# Processor Features
165 +# CONFIG_CPU_ICACHE_DISABLE is not set
166 +# CONFIG_CPU_DCACHE_DISABLE is not set
167 +CONFIG_CPU_DCACHE_WRITETHROUGH=y
172 +CONFIG_ISA_DMA_API=y
175 +# PCCARD (PCMCIA/CardBus) support
178 +# CONFIG_PCMCIA_DEBUG is not set
180 +CONFIG_PCMCIA_LOAD_CIS=y
181 +CONFIG_PCMCIA_IOCTL=y
190 +# CONFIG_SMP is not set
191 +# CONFIG_PREEMPT is not set
192 +# CONFIG_NO_IDLE_HZ is not set
193 +# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
194 +CONFIG_SELECT_MEMORY_MODEL=y
195 +CONFIG_FLATMEM_MANUAL=y
196 +# CONFIG_DISCONTIGMEM_MANUAL is not set
197 +# CONFIG_SPARSEMEM_MANUAL is not set
199 +CONFIG_FLAT_NODE_MEM_MAP=y
200 +# CONFIG_SPARSEMEM_STATIC is not set
204 +CONFIG_ALIGNMENT_TRAP=y
209 +CONFIG_ZBOOT_ROM_TEXT=0x0
210 +CONFIG_ZBOOT_ROM_BSS=0x0
211 +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:"
212 +# CONFIG_XIP_KERNEL is not set
215 +# CPU Frequency scaling
218 +CONFIG_CPU_FREQ_TABLE=y
219 +CONFIG_CPU_FREQ_DEBUG=y
220 +CONFIG_CPU_FREQ_STAT=y
221 +CONFIG_CPU_FREQ_STAT_DETAILS=y
222 +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
223 +CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
224 +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
225 +CONFIG_CPU_FREQ_GOV_POWERSAVE=y
226 +CONFIG_CPU_FREQ_GOV_USERSPACE=y
227 +CONFIG_CPU_FREQ_GOV_ONDEMAND=y
228 +# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
231 +# Floating point emulation
235 +# At least one emulation must be selected
238 +CONFIG_FPE_NWFPE_XP=y
239 +# CONFIG_FPE_FASTFPE is not set
242 +# Userspace binary formats
245 +CONFIG_BINFMT_AOUT=y
246 +CONFIG_BINFMT_MISC=y
247 +# CONFIG_ARTHUR is not set
250 +# Power management options
261 +# Networking options
264 +# CONFIG_PACKET_MMAP is not set
268 +# CONFIG_NET_KEY is not set
270 +CONFIG_IP_MULTICAST=y
271 +# CONFIG_IP_ADVANCED_ROUTER is not set
272 +CONFIG_IP_FIB_HASH=y
274 +CONFIG_IP_PNP_DHCP=y
275 +CONFIG_IP_PNP_BOOTP=y
276 +CONFIG_IP_PNP_RARP=y
277 +# CONFIG_NET_IPIP is not set
278 +# CONFIG_NET_IPGRE is not set
279 +# CONFIG_IP_MROUTE is not set
280 +# CONFIG_ARPD is not set
281 +CONFIG_SYN_COOKIES=y
284 +CONFIG_INET_IPCOMP=m
285 +CONFIG_INET_TUNNEL=m
287 +CONFIG_INET_TCP_DIAG=y
288 +# CONFIG_TCP_CONG_ADVANCED is not set
289 +CONFIG_TCP_CONG_BIC=y
292 +# IP: Virtual Server Configuration
294 +# CONFIG_IP_VS is not set
296 +CONFIG_IPV6_PRIVACY=y
299 +CONFIG_INET6_IPCOMP=m
300 +CONFIG_INET6_TUNNEL=m
301 +CONFIG_IPV6_TUNNEL=m
303 +# CONFIG_NETFILTER_DEBUG is not set
304 +CONFIG_BRIDGE_NETFILTER=y
305 +# CONFIG_NETFILTER_NETLINK is not set
308 +# IP: Netfilter Configuration
310 +CONFIG_IP_NF_CONNTRACK=m
311 +CONFIG_IP_NF_CT_ACCT=y
312 +CONFIG_IP_NF_CONNTRACK_MARK=y
313 +# CONFIG_IP_NF_CONNTRACK_EVENTS is not set
314 +CONFIG_IP_NF_CT_PROTO_SCTP=m
317 +# CONFIG_IP_NF_NETBIOS_NS is not set
319 +# CONFIG_IP_NF_AMANDA is not set
320 +# CONFIG_IP_NF_PPTP is not set
321 +CONFIG_IP_NF_QUEUE=m
322 +CONFIG_IP_NF_IPTABLES=m
323 +CONFIG_IP_NF_MATCH_LIMIT=m
324 +CONFIG_IP_NF_MATCH_IPRANGE=m
325 +CONFIG_IP_NF_MATCH_MAC=m
326 +CONFIG_IP_NF_MATCH_PKTTYPE=m
327 +# CONFIG_IP_NF_MATCH_MARK is not set
328 +# CONFIG_IP_NF_MATCH_MULTIPORT is not set
329 +# CONFIG_IP_NF_MATCH_TOS is not set
330 +# CONFIG_IP_NF_MATCH_RECENT is not set
331 +# CONFIG_IP_NF_MATCH_ECN is not set
332 +# CONFIG_IP_NF_MATCH_DSCP is not set
333 +# CONFIG_IP_NF_MATCH_AH_ESP is not set
334 +# CONFIG_IP_NF_MATCH_LENGTH is not set
335 +# CONFIG_IP_NF_MATCH_TTL is not set
336 +# CONFIG_IP_NF_MATCH_TCPMSS is not set
337 +# CONFIG_IP_NF_MATCH_HELPER is not set
338 +# CONFIG_IP_NF_MATCH_STATE is not set
339 +# CONFIG_IP_NF_MATCH_CONNTRACK is not set
340 +# CONFIG_IP_NF_MATCH_OWNER is not set
341 +# CONFIG_IP_NF_MATCH_PHYSDEV is not set
342 +# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
343 +# CONFIG_IP_NF_MATCH_REALM is not set
344 +# CONFIG_IP_NF_MATCH_SCTP is not set
345 +# CONFIG_IP_NF_MATCH_DCCP is not set
346 +# CONFIG_IP_NF_MATCH_COMMENT is not set
347 +# CONFIG_IP_NF_MATCH_CONNMARK is not set
348 +# CONFIG_IP_NF_MATCH_CONNBYTES is not set
349 +# CONFIG_IP_NF_MATCH_HASHLIMIT is not set
350 +# CONFIG_IP_NF_MATCH_STRING is not set
351 +# CONFIG_IP_NF_FILTER is not set
352 +# CONFIG_IP_NF_TARGET_LOG is not set
353 +# CONFIG_IP_NF_TARGET_ULOG is not set
354 +# CONFIG_IP_NF_TARGET_TCPMSS is not set
355 +# CONFIG_IP_NF_TARGET_NFQUEUE is not set
356 +# CONFIG_IP_NF_NAT is not set
357 +CONFIG_IP_NF_MANGLE=m
358 +# CONFIG_IP_NF_TARGET_TOS is not set
359 +# CONFIG_IP_NF_TARGET_ECN is not set
360 +# CONFIG_IP_NF_TARGET_DSCP is not set
361 +# CONFIG_IP_NF_TARGET_MARK is not set
362 +# CONFIG_IP_NF_TARGET_CLASSIFY is not set
363 +# CONFIG_IP_NF_TARGET_TTL is not set
364 +# CONFIG_IP_NF_TARGET_CONNMARK is not set
365 +# CONFIG_IP_NF_TARGET_CLUSTERIP is not set
366 +# CONFIG_IP_NF_RAW is not set
367 +# CONFIG_IP_NF_ARPTABLES is not set
370 +# IPv6: Netfilter Configuration (EXPERIMENTAL)
372 +CONFIG_IP6_NF_QUEUE=m
373 +CONFIG_IP6_NF_IPTABLES=m
374 +# CONFIG_IP6_NF_MATCH_LIMIT is not set
375 +CONFIG_IP6_NF_MATCH_MAC=m
376 +CONFIG_IP6_NF_MATCH_RT=m
377 +# CONFIG_IP6_NF_MATCH_OPTS is not set
378 +# CONFIG_IP6_NF_MATCH_FRAG is not set
379 +# CONFIG_IP6_NF_MATCH_HL is not set
380 +# CONFIG_IP6_NF_MATCH_MULTIPORT is not set
381 +# CONFIG_IP6_NF_MATCH_OWNER is not set
382 +# CONFIG_IP6_NF_MATCH_MARK is not set
383 +CONFIG_IP6_NF_MATCH_IPV6HEADER=m
384 +# CONFIG_IP6_NF_MATCH_AHESP is not set
385 +# CONFIG_IP6_NF_MATCH_LENGTH is not set
386 +# CONFIG_IP6_NF_MATCH_EUI64 is not set
387 +# CONFIG_IP6_NF_MATCH_PHYSDEV is not set
388 +CONFIG_IP6_NF_FILTER=m
389 +# CONFIG_IP6_NF_TARGET_LOG is not set
390 +# CONFIG_IP6_NF_TARGET_REJECT is not set
391 +# CONFIG_IP6_NF_TARGET_NFQUEUE is not set
392 +CONFIG_IP6_NF_MANGLE=m
393 +# CONFIG_IP6_NF_TARGET_MARK is not set
394 +# CONFIG_IP6_NF_TARGET_HL is not set
398 +# Bridge: Netfilter Configuration
400 +CONFIG_BRIDGE_NF_EBTABLES=m
401 +# CONFIG_BRIDGE_EBT_BROUTE is not set
402 +# CONFIG_BRIDGE_EBT_T_FILTER is not set
403 +# CONFIG_BRIDGE_EBT_T_NAT is not set
404 +# CONFIG_BRIDGE_EBT_802_3 is not set
405 +# CONFIG_BRIDGE_EBT_AMONG is not set
406 +# CONFIG_BRIDGE_EBT_ARP is not set
407 +# CONFIG_BRIDGE_EBT_IP is not set
408 +# CONFIG_BRIDGE_EBT_LIMIT is not set
409 +# CONFIG_BRIDGE_EBT_MARK is not set
410 +# CONFIG_BRIDGE_EBT_PKTTYPE is not set
411 +# CONFIG_BRIDGE_EBT_STP is not set
412 +# CONFIG_BRIDGE_EBT_VLAN is not set
413 +# CONFIG_BRIDGE_EBT_ARPREPLY is not set
414 +# CONFIG_BRIDGE_EBT_DNAT is not set
415 +# CONFIG_BRIDGE_EBT_MARK_T is not set
416 +# CONFIG_BRIDGE_EBT_REDIRECT is not set
417 +# CONFIG_BRIDGE_EBT_SNAT is not set
418 +# CONFIG_BRIDGE_EBT_LOG is not set
419 +# CONFIG_BRIDGE_EBT_ULOG is not set
422 +# DCCP Configuration (EXPERIMENTAL)
424 +# CONFIG_IP_DCCP is not set
427 +# SCTP Configuration (EXPERIMENTAL)
429 +# CONFIG_IP_SCTP is not set
430 +# CONFIG_ATM is not set
432 +# CONFIG_VLAN_8021Q is not set
433 +# CONFIG_DECNET is not set
434 +# CONFIG_LLC2 is not set
435 +# CONFIG_IPX is not set
436 +# CONFIG_ATALK is not set
437 +# CONFIG_X25 is not set
438 +# CONFIG_LAPB is not set
439 +# CONFIG_NET_DIVERT is not set
440 +# CONFIG_ECONET is not set
441 +# CONFIG_WAN_ROUTER is not set
442 +# CONFIG_NET_SCHED is not set
443 +# CONFIG_NET_CLS_ROUTE is not set
448 +# CONFIG_NET_PKTGEN is not set
449 +# CONFIG_HAMRADIO is not set
463 +CONFIG_IRDA_CACHE_LAST_LSAP=y
464 +CONFIG_IRDA_FAST_RR=y
465 +# CONFIG_IRDA_DEBUG is not set
468 +# Infrared-port device drivers
472 +# SIR device drivers
474 +# CONFIG_IRTTY_SIR is not set
481 +# Old SIR device drivers
483 +# CONFIG_IRPORT_SIR is not set
486 +# Old Serial dongle support
490 +# FIR device drivers
492 +# CONFIG_USB_IRDA is not set
493 +# CONFIG_SIGMATEL_FIR is not set
494 +# CONFIG_NSC_FIR is not set
495 +# CONFIG_WINBOND_FIR is not set
496 +CONFIG_OMAP1610_IR=m
497 +CONFIG_SMC_IRCC_FIR=m
498 +# CONFIG_ALI_FIR is not set
499 +# CONFIG_VIA_FIR is not set
502 +# CONFIG_BT_SCO is not set
504 +CONFIG_BT_RFCOMM_TTY=y
506 +CONFIG_BT_BNEP_MC_FILTER=y
507 +CONFIG_BT_BNEP_PROTO_FILTER=y
511 +# Bluetooth device drivers
513 +# CONFIG_BT_HCIUSB is not set
515 +CONFIG_BT_HCIUART_H4=y
516 +CONFIG_BT_HCIUART_BCSP=y
517 +# CONFIG_BT_HCIUART_BCSP_TXCRC is not set
518 +# CONFIG_BT_HCIBCM203X is not set
519 +# CONFIG_BT_HCIBPA10X is not set
520 +# CONFIG_BT_HCIBFUSB is not set
521 +# CONFIG_BT_HCIDTL1 is not set
522 +# CONFIG_BT_HCIBT3C is not set
523 +# CONFIG_BT_HCIBLUECARD is not set
524 +# CONFIG_BT_HCIBTUART is not set
527 +# CONFIG_IEEE80211 is not set
534 +# Generic Driver Options
537 +CONFIG_PREVENT_FIRMWARE_BUILD=y
539 +# CONFIG_DEBUG_DRIVER is not set
542 +# Memory Technology Devices (MTD)
545 +# CONFIG_MTD_DEBUG is not set
547 +CONFIG_MTD_PARTITIONS=y
548 +CONFIG_MTD_REDBOOT_PARTS=y
549 +CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
550 +# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
551 +# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
552 +# CONFIG_MTD_CMDLINE_PARTS is not set
553 +# CONFIG_MTD_AFS_PARTS is not set
556 +# User Modules And Translation Layers
560 +# CONFIG_FTL is not set
561 +# CONFIG_NFTL is not set
562 +# CONFIG_INFTL is not set
565 +# RAM/ROM/Flash chip drivers
568 +CONFIG_MTD_JEDECPROBE=m
569 +CONFIG_MTD_GEN_PROBE=m
570 +CONFIG_MTD_CFI_ADV_OPTIONS=y
571 +CONFIG_MTD_CFI_NOSWAP=y
572 +# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
573 +# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
574 +# CONFIG_MTD_CFI_GEOMETRY is not set
575 +CONFIG_MTD_MAP_BANK_WIDTH_1=y
576 +CONFIG_MTD_MAP_BANK_WIDTH_2=y
577 +CONFIG_MTD_MAP_BANK_WIDTH_4=y
578 +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
579 +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
580 +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
583 +# CONFIG_MTD_CFI_I4 is not set
584 +# CONFIG_MTD_CFI_I8 is not set
585 +# CONFIG_MTD_OTP is not set
586 +CONFIG_MTD_CFI_INTELEXT=m
587 +CONFIG_MTD_CFI_AMDSTD=m
588 +CONFIG_MTD_CFI_AMDSTD_RETRY=1
589 +CONFIG_MTD_CFI_STAA=m
590 +CONFIG_MTD_CFI_UTIL=m
591 +# CONFIG_MTD_RAM is not set
592 +# CONFIG_MTD_ROM is not set
594 +# CONFIG_MTD_OBSOLETE_CHIPS is not set
595 +# CONFIG_MTD_XIP is not set
598 +# Mapping drivers for chip access
600 +CONFIG_MTD_COMPLEX_MAPPINGS=y
601 +CONFIG_MTD_PHYSMAP=m
602 +CONFIG_MTD_PHYSMAP_START=0x8000000
603 +CONFIG_MTD_PHYSMAP_LEN=0x4000000
604 +CONFIG_MTD_PHYSMAP_BANKWIDTH=2
605 +# CONFIG_MTD_ARM_INTEGRATOR is not set
606 +# CONFIG_MTD_EDB7312 is not set
607 +# CONFIG_MTD_IMPA7 is not set
608 +# CONFIG_MTD_OMAP_NOR is not set
609 +# CONFIG_MTD_PCMCIA is not set
610 +# CONFIG_MTD_PLATRAM is not set
613 +# Self-contained MTD device drivers
618 +CONFIG_MTDRAM_TOTAL_SIZE=4096
619 +CONFIG_MTDRAM_ERASE_SIZE=128
621 +# CONFIG_MTD_BLOCK2MTD is not set
624 +# Disk-On-Chip Device Drivers
626 +CONFIG_MTD_DOC2000=m
627 +CONFIG_MTD_DOC2001=m
628 +CONFIG_MTD_DOC2001PLUS=m
629 +CONFIG_MTD_DOCPROBE=m
631 +CONFIG_MTD_DOCPROBE_ADVANCED=y
632 +CONFIG_MTD_DOCPROBE_ADDRESS=0x0000
633 +CONFIG_MTD_DOCPROBE_HIGH=y
634 +CONFIG_MTD_DOCPROBE_55AA=y
637 +# NAND Flash Device Drivers
640 +# CONFIG_MTD_NAND_VERIFY_WRITE is not set
641 +# CONFIG_MTD_NAND_TOTO is not set
642 +CONFIG_MTD_NAND_IDS=m
643 +CONFIG_MTD_NAND_DISKONCHIP=m
644 +CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED=y
645 +CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0x0
646 +# CONFIG_MTD_NAND_DISKONCHIP_PROBE_HIGH is not set
647 +CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE=y
648 +# CONFIG_MTD_NAND_NANDSIM is not set
651 +# Parallel port support
653 +# CONFIG_PARPORT is not set
656 +# Plug and Play support
662 +# CONFIG_BLK_DEV_COW_COMMON is not set
663 +CONFIG_BLK_DEV_LOOP=y
664 +CONFIG_BLK_DEV_CRYPTOLOOP=m
665 +# CONFIG_BLK_DEV_NBD is not set
666 +# CONFIG_BLK_DEV_UB is not set
667 +CONFIG_BLK_DEV_RAM=y
668 +CONFIG_BLK_DEV_RAM_COUNT=16
669 +CONFIG_BLK_DEV_RAM_SIZE=16384
670 +CONFIG_BLK_DEV_INITRD=y
671 +# CONFIG_CDROM_PKTCDVD is not set
676 +CONFIG_IOSCHED_NOOP=y
678 +CONFIG_IOSCHED_DEADLINE=y
679 +CONFIG_IOSCHED_CFQ=y
680 +# CONFIG_ATA_OVER_ETH is not set
683 +# ATA/ATAPI/MFM/RLL support
685 +# CONFIG_IDE is not set
688 +# SCSI device support
690 +# CONFIG_RAID_ATTRS is not set
691 +# CONFIG_SCSI is not set
694 +# Multi-device support (RAID and LVM)
696 +# CONFIG_MD is not set
699 +# Fusion MPT device support
701 +# CONFIG_FUSION is not set
704 +# IEEE 1394 (FireWire) support
706 +# CONFIG_IEEE1394 is not set
709 +# I2O device support
713 +# Network device support
716 +# CONFIG_DUMMY is not set
717 +# CONFIG_BONDING is not set
718 +# CONFIG_EQUALIZER is not set
719 +# CONFIG_TUN is not set
722 +# PHY device support
724 +# CONFIG_PHYLIB is not set
727 +# Ethernet (10 or 100Mbit)
729 +CONFIG_NET_ETHERNET=y
732 +# CONFIG_DM9000 is not set
735 +# Ethernet (1000 Mbit)
739 +# Ethernet (10000 Mbit)
743 +# Token Ring devices
747 +# Wireless LAN (non-hamradio)
752 +# Obsolete Wireless cards support (pre-802.11)
755 +# CONFIG_PCMCIA_WAVELAN is not set
756 +# CONFIG_PCMCIA_NETWAVE is not set
759 +# Wireless 802.11 Frequency Hopping cards support
761 +# CONFIG_PCMCIA_RAYCS is not set
764 +# Wireless 802.11b ISA/PCI cards support
766 +# CONFIG_AIRO is not set
767 +# CONFIG_HERMES is not set
771 +# Wireless 802.11b Pcmcia/Cardbus cards support
773 +# CONFIG_AIRO_CS is not set
774 +# CONFIG_PCMCIA_ATMEL is not set
775 +# CONFIG_PCMCIA_WL3501 is not set
776 +# CONFIG_HOSTAP is not set
777 +CONFIG_NET_WIRELESS=y
779 +# CONFIG_ACX_USB is not set
783 +# PCMCIA network device support
785 +# CONFIG_NET_PCMCIA is not set
790 +# CONFIG_WAN is not set
792 +CONFIG_PPP_MULTILINK=y
795 +CONFIG_PPP_SYNC_TTY=y
796 +CONFIG_PPP_DEFLATE=y
797 +CONFIG_PPP_BSDCOMP=y
799 +# CONFIG_SLIP is not set
800 +# CONFIG_SHAPER is not set
801 +# CONFIG_NETCONSOLE is not set
802 +# CONFIG_NETPOLL is not set
803 +# CONFIG_NET_POLL_CONTROLLER is not set
808 +# CONFIG_ISDN is not set
811 +# Input device support
816 +# Userland interfaces
818 +# CONFIG_INPUT_MOUSEDEV is not set
819 +# CONFIG_INPUT_JOYDEV is not set
820 +CONFIG_INPUT_TSDEV=y
821 +CONFIG_INPUT_TSDEV_SCREEN_X=240
822 +CONFIG_INPUT_TSDEV_SCREEN_Y=320
823 +CONFIG_INPUT_EVDEV=y
824 +# CONFIG_INPUT_EVBUG is not set
827 +# Input Device Drivers
829 +CONFIG_INPUT_KEYBOARD=y
830 +# CONFIG_KEYBOARD_ATKBD is not set
831 +# CONFIG_KEYBOARD_SUNKBD is not set
832 +# CONFIG_KEYBOARD_LKKBD is not set
833 +# CONFIG_KEYBOARD_XTKBD is not set
834 +# CONFIG_KEYBOARD_NEWTON is not set
835 +CONFIG_KEYBOARD_OMAP=m
836 +CONFIG_INPUT_MOUSE=y
838 +CONFIG_MOUSE_SERIAL=y
839 +# CONFIG_MOUSE_VSXXXAA is not set
840 +# CONFIG_INPUT_JOYSTICK is not set
841 +CONFIG_INPUT_TOUCHSCREEN=y
842 +# CONFIG_TOUCHSCREEN_GUNZE is not set
843 +# CONFIG_TOUCHSCREEN_ELO is not set
844 +# CONFIG_TOUCHSCREEN_MTOUCH is not set
845 +# CONFIG_TOUCHSCREEN_MK712 is not set
846 +CONFIG_TOUCHSCREEN_OMAP=m
848 +CONFIG_INPUT_UINPUT=m
851 +# Hardware I/O ports
854 +CONFIG_SERIO_SERPORT=y
855 +CONFIG_SERIO_LIBPS2=y
857 +# CONFIG_GAMEPORT is not set
865 +# CONFIG_SERIAL_NONSTANDARD is not set
870 +CONFIG_SERIAL_8250=y
871 +# CONFIG_SERIAL_8250_CONSOLE is not set
872 +# CONFIG_SERIAL_8250_CS is not set
873 +CONFIG_SERIAL_8250_NR_UARTS=4
874 +# CONFIG_SERIAL_8250_EXTENDED is not set
877 +# Non-8250 serial port support
879 +CONFIG_SERIAL_CORE=y
880 +CONFIG_UNIX98_PTYS=y
881 +CONFIG_LEGACY_PTYS=y
882 +CONFIG_LEGACY_PTY_COUNT=256
887 +# CONFIG_IPMI_HANDLER is not set
893 +CONFIG_WATCHDOG_NOWAYOUT=y
896 +# Watchdog Device Drivers
898 +CONFIG_SOFT_WATCHDOG=m
901 +# USB-based Watchdog Cards
903 +# CONFIG_USBPCWATCHDOG is not set
905 +# CONFIG_RTC is not set
907 +# CONFIG_DTLK is not set
908 +# CONFIG_R3964 is not set
911 +# Ftape, the floppy tape device driver
915 +# PCMCIA character devices
917 +# CONFIG_SYNCLINK_CS is not set
918 +# CONFIG_RAW_DRIVER is not set
928 +CONFIG_I2C_CHARDEV=m
933 +CONFIG_I2C_ALGOBIT=m
934 +CONFIG_I2C_ALGOPCF=m
935 +CONFIG_I2C_ALGOPCA=m
938 +# I2C Hardware Bus support
940 +CONFIG_I2C_PARPORT_LIGHT=m
941 +# CONFIG_I2C_STUB is not set
942 +# CONFIG_I2C_PCA_ISA is not set
946 +# Miscellaneous I2C Chip support
948 +# CONFIG_SENSORS_DS1337 is not set
949 +# CONFIG_SENSORS_DS1374 is not set
950 +# CONFIG_SENSORS_EEPROM is not set
951 +# CONFIG_SENSORS_PCF8574 is not set
952 +# CONFIG_SENSORS_PCA9539 is not set
954 +# CONFIG_SENSORS_PCF8591 is not set
955 +# CONFIG_SENSORS_RTC8564 is not set
956 +# CONFIG_TPS65010 is not set
957 +CONFIG_SENSORS_TLV320AIC23=m
958 +# CONFIG_SENSORS_MAX6875 is not set
959 +# CONFIG_I2C_DEBUG_CORE is not set
960 +# CONFIG_I2C_DEBUG_ALGO is not set
961 +# CONFIG_I2C_DEBUG_BUS is not set
962 +# CONFIG_I2C_DEBUG_CHIP is not set
965 +# Hardware Monitoring support
968 +# CONFIG_HWMON_VID is not set
969 +# CONFIG_SENSORS_ADM1021 is not set
970 +# CONFIG_SENSORS_ADM1025 is not set
971 +# CONFIG_SENSORS_ADM1026 is not set
972 +# CONFIG_SENSORS_ADM1031 is not set
973 +# CONFIG_SENSORS_ADM9240 is not set
974 +# CONFIG_SENSORS_ASB100 is not set
975 +# CONFIG_SENSORS_ATXP1 is not set
976 +# CONFIG_SENSORS_DS1621 is not set
977 +# CONFIG_SENSORS_FSCHER is not set
978 +# CONFIG_SENSORS_FSCPOS is not set
979 +# CONFIG_SENSORS_GL518SM is not set
980 +# CONFIG_SENSORS_GL520SM is not set
981 +# CONFIG_SENSORS_IT87 is not set
982 +# CONFIG_SENSORS_LM63 is not set
983 +# CONFIG_SENSORS_LM75 is not set
984 +# CONFIG_SENSORS_LM77 is not set
985 +# CONFIG_SENSORS_LM78 is not set
986 +# CONFIG_SENSORS_LM80 is not set
987 +# CONFIG_SENSORS_LM83 is not set
988 +# CONFIG_SENSORS_LM85 is not set
989 +# CONFIG_SENSORS_LM87 is not set
990 +# CONFIG_SENSORS_LM90 is not set
991 +# CONFIG_SENSORS_LM92 is not set
992 +# CONFIG_SENSORS_MAX1619 is not set
993 +# CONFIG_SENSORS_PC87360 is not set
994 +# CONFIG_SENSORS_SMSC47M1 is not set
995 +# CONFIG_SENSORS_SMSC47B397 is not set
996 +# CONFIG_SENSORS_W83781D is not set
997 +# CONFIG_SENSORS_W83792D is not set
998 +# CONFIG_SENSORS_W83L785TS is not set
999 +# CONFIG_SENSORS_W83627HF is not set
1000 +# CONFIG_SENSORS_W83627EHF is not set
1001 +# CONFIG_HWMON_DEBUG_CHIP is not set
1008 +# Multimedia Capabilities Port drivers
1012 +# Multimedia devices
1014 +# CONFIG_VIDEO_DEV is not set
1017 +# Digital Video Broadcasting Devices
1019 +# CONFIG_DVB is not set
1025 +# CONFIG_FB_CFB_FILLRECT is not set
1026 +# CONFIG_FB_CFB_COPYAREA is not set
1027 +# CONFIG_FB_CFB_IMAGEBLIT is not set
1028 +CONFIG_FB_SOFT_CURSOR=y
1029 +# CONFIG_FB_MACMODES is not set
1030 +CONFIG_FB_MODE_HELPERS=y
1031 +# CONFIG_FB_TILEBLITTING is not set
1032 +# CONFIG_FB_S1D13XXX is not set
1034 +CONFIG_FB_OMAP_LCDC_INTERNAL=y
1035 +# CONFIG_FB_OMAP_LCDC_EXTERNAL is not set
1036 +CONFIG_FB_OMAP_DMA_TUNE=y
1037 +# CONFIG_FB_VIRTUAL is not set
1040 +# Console display driver support
1042 +# CONFIG_VGA_CONSOLE is not set
1043 +CONFIG_DUMMY_CONSOLE=y
1044 +CONFIG_FRAMEBUFFER_CONSOLE=y
1046 +# CONFIG_FONT_8x8 is not set
1047 +# CONFIG_FONT_8x16 is not set
1048 +# CONFIG_FONT_6x11 is not set
1049 +# CONFIG_FONT_7x14 is not set
1050 +# CONFIG_FONT_PEARL_8x8 is not set
1051 +# CONFIG_FONT_ACORN_8x8 is not set
1052 +CONFIG_FONT_MINI_4x6=y
1053 +# CONFIG_FONT_SUN8x16 is not set
1054 +# CONFIG_FONT_SUN12x22 is not set
1055 +# CONFIG_FONT_10x18 is not set
1058 +# Logo configuration
1061 +# CONFIG_LOGO_LINUX_MONO is not set
1062 +CONFIG_LOGO_LINUX_VGA16=y
1063 +# CONFIG_LOGO_LINUX_CLUT224 is not set
1064 +CONFIG_BACKLIGHT_LCD_SUPPORT=y
1065 +CONFIG_BACKLIGHT_CLASS_DEVICE=y
1066 +CONFIG_BACKLIGHT_DEVICE=y
1067 +CONFIG_LCD_CLASS_DEVICE=y
1068 +CONFIG_LCD_DEVICE=y
1071 +# Telephony Support
1074 +# CONFIG_PHONE_IXJ is not set
1083 +# Advanced Linux Sound Architecture
1085 +# CONFIG_SND is not set
1088 +# Open Sound System
1090 +CONFIG_SOUND_PRIME=m
1091 +CONFIG_SOUND_OMAP=m
1092 +CONFIG_SOUND_OMAP_TSC2101=m
1093 +# CONFIG_SOUND_MSNDCLAS is not set
1094 +# CONFIG_SOUND_MSNDPIN is not set
1095 +# CONFIG_SOUND_OSS is not set
1096 +# CONFIG_SOUND_TVMIXER is not set
1097 +# CONFIG_SOUND_AD1980 is not set
1102 +CONFIG_USB_ARCH_HAS_HCD=y
1103 +CONFIG_USB_ARCH_HAS_OHCI=y
1108 +# Miscellaneous USB options
1110 +CONFIG_USB_DEVICEFS=y
1111 +# CONFIG_USB_BANDWIDTH is not set
1112 +# CONFIG_USB_DYNAMIC_MINORS is not set
1113 +# CONFIG_USB_SUSPEND is not set
1114 +# CONFIG_USB_OTG is not set
1117 +# USB Host Controller Drivers
1119 +# CONFIG_USB_ISP116X_HCD is not set
1120 +CONFIG_USB_OHCI_HCD=y
1121 +# CONFIG_USB_OHCI_BIG_ENDIAN is not set
1122 +CONFIG_USB_OHCI_LITTLE_ENDIAN=y
1123 +# CONFIG_USB_SL811_HCD is not set
1126 +# USB Device Class drivers
1128 +# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set
1131 +# USB Bluetooth TTY can only be used with disabled Bluetooth subsystem
1134 +# CONFIG_USB_PRINTER is not set
1137 +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
1139 +# CONFIG_USB_STORAGE is not set
1142 +# USB Input Devices
1144 +# CONFIG_USB_HID is not set
1147 +# USB HID Boot Protocol drivers
1149 +# CONFIG_USB_KBD is not set
1150 +# CONFIG_USB_MOUSE is not set
1151 +# CONFIG_USB_AIPTEK is not set
1152 +# CONFIG_USB_WACOM is not set
1153 +# CONFIG_USB_ACECAD is not set
1154 +# CONFIG_USB_KBTAB is not set
1155 +# CONFIG_USB_POWERMATE is not set
1156 +# CONFIG_USB_MTOUCH is not set
1157 +# CONFIG_USB_ITMTOUCH is not set
1158 +# CONFIG_USB_EGALAX is not set
1159 +# CONFIG_USB_YEALINK is not set
1160 +# CONFIG_USB_XPAD is not set
1161 +# CONFIG_USB_ATI_REMOTE is not set
1162 +# CONFIG_USB_KEYSPAN_REMOTE is not set
1163 +# CONFIG_USB_APPLETOUCH is not set
1166 +# USB Imaging devices
1168 +# CONFIG_USB_MDC800 is not set
1171 +# USB Multimedia devices
1173 +# CONFIG_USB_DABUSB is not set
1176 +# Video4Linux support is needed for USB Multimedia device support
1180 +# USB Network Adapters
1182 +# CONFIG_USB_CATC is not set
1183 +# CONFIG_USB_KAWETH is not set
1184 +# CONFIG_USB_PEGASUS is not set
1185 +# CONFIG_USB_RTL8150 is not set
1186 +CONFIG_USB_USBNET=y
1187 +CONFIG_USB_NET_AX8817X=y
1188 +CONFIG_USB_NET_CDCETHER=y
1189 +# CONFIG_USB_NET_GL620A is not set
1190 +CONFIG_USB_NET_NET1080=y
1191 +# CONFIG_USB_NET_PLUSB is not set
1192 +# CONFIG_USB_NET_RNDIS_HOST is not set
1193 +# CONFIG_USB_NET_CDC_SUBSET is not set
1194 +CONFIG_USB_NET_ZAURUS=y
1195 +# CONFIG_USB_ZD1201 is not set
1203 +# USB Serial Converter support
1205 +CONFIG_USB_SERIAL=y
1206 +CONFIG_USB_SERIAL_CONSOLE=y
1207 +CONFIG_USB_SERIAL_GENERIC=y
1208 +# CONFIG_USB_SERIAL_AIRPRIME is not set
1209 +# CONFIG_USB_SERIAL_BELKIN is not set
1210 +# CONFIG_USB_SERIAL_WHITEHEAT is not set
1211 +# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
1212 +# CONFIG_USB_SERIAL_CP2101 is not set
1213 +# CONFIG_USB_SERIAL_CYPRESS_M8 is not set
1214 +# CONFIG_USB_SERIAL_EMPEG is not set
1215 +# CONFIG_USB_SERIAL_FTDI_SIO is not set
1216 +CONFIG_USB_SERIAL_VISOR=y
1217 +CONFIG_USB_SERIAL_IPAQ=y
1218 +# CONFIG_USB_SERIAL_IR is not set
1219 +# CONFIG_USB_SERIAL_EDGEPORT is not set
1220 +# CONFIG_USB_SERIAL_EDGEPORT_TI is not set
1221 +# CONFIG_USB_SERIAL_GARMIN is not set
1222 +# CONFIG_USB_SERIAL_IPW is not set
1223 +# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
1224 +# CONFIG_USB_SERIAL_KEYSPAN is not set
1225 +# CONFIG_USB_SERIAL_KLSI is not set
1226 +# CONFIG_USB_SERIAL_KOBIL_SCT is not set
1227 +# CONFIG_USB_SERIAL_MCT_U232 is not set
1228 +# CONFIG_USB_SERIAL_PL2303 is not set
1229 +# CONFIG_USB_SERIAL_HP4X is not set
1230 +# CONFIG_USB_SERIAL_SAFE is not set
1231 +# CONFIG_USB_SERIAL_TI is not set
1232 +# CONFIG_USB_SERIAL_CYBERJACK is not set
1233 +# CONFIG_USB_SERIAL_XIRCOM is not set
1234 +# CONFIG_USB_SERIAL_OPTION is not set
1235 +# CONFIG_USB_SERIAL_OMNINET is not set
1238 +# USB Miscellaneous drivers
1240 +# CONFIG_USB_EMI62 is not set
1241 +# CONFIG_USB_EMI26 is not set
1242 +# CONFIG_USB_AUERSWALD is not set
1243 +# CONFIG_USB_RIO500 is not set
1244 +# CONFIG_USB_LEGOTOWER is not set
1245 +# CONFIG_USB_LCD is not set
1246 +# CONFIG_USB_LED is not set
1247 +# CONFIG_USB_CYTHERM is not set
1248 +# CONFIG_USB_PHIDGETKIT is not set
1249 +# CONFIG_USB_PHIDGETSERVO is not set
1250 +# CONFIG_USB_IDMOUSE is not set
1251 +# CONFIG_USB_LD is not set
1252 +# CONFIG_USB_TEST is not set
1255 +# USB DSL modem support
1259 +# USB Gadget Support
1261 +CONFIG_USB_GADGET=y
1262 +CONFIG_USB_GADGET_DEBUG_FILES=y
1263 +CONFIG_USB_GADGET_SELECTED=y
1264 +# CONFIG_USB_GADGET_NET2280 is not set
1265 +# CONFIG_USB_GADGET_PXA2XX is not set
1266 +# CONFIG_USB_GADGET_GOKU is not set
1267 +# CONFIG_USB_GADGET_LH7A40X is not set
1268 +CONFIG_USB_GADGET_OMAP=y
1270 +# CONFIG_USB_GADGET_DUMMY_HCD is not set
1271 +# CONFIG_USB_GADGET_DUALSPEED is not set
1272 +# CONFIG_USB_ZERO is not set
1274 +# CONFIG_USB_ETH_RNDIS is not set
1275 +# CONFIG_USB_GADGETFS is not set
1276 +# CONFIG_USB_FILE_STORAGE is not set
1277 +# CONFIG_USB_G_SERIAL is not set
1280 +# MMC/SD Card support
1283 +# CONFIG_MMC_DEBUG is not set
1285 +CONFIG_MMC_BLOCK_BROKEN_RFD=y
1286 +CONFIG_MMC_BULKTRANSFER=y
1288 +# CONFIG_MMC_WBSD is not set
1291 +# Synchronous Serial Interfaces (SSI)
1293 +CONFIG_OMAP_UWIRE=y
1294 +CONFIG_OMAP_TSC2101=y
1300 +CONFIG_EXT2_FS_XATTR=y
1301 +CONFIG_EXT2_FS_POSIX_ACL=y
1302 +CONFIG_EXT2_FS_SECURITY=y
1303 +# CONFIG_EXT2_FS_XIP is not set
1304 +# CONFIG_EXT3_FS is not set
1305 +# CONFIG_JBD is not set
1306 +CONFIG_FS_MBCACHE=y
1307 +# CONFIG_REISERFS_FS is not set
1308 +# CONFIG_JFS_FS is not set
1309 +CONFIG_FS_POSIX_ACL=y
1310 +# CONFIG_XFS_FS is not set
1311 +# CONFIG_MINIX_FS is not set
1314 +# CONFIG_QUOTA is not set
1315 +# CONFIG_DNOTIFY is not set
1316 +# CONFIG_AUTOFS_FS is not set
1317 +CONFIG_AUTOFS4_FS=y
1318 +# CONFIG_FUSE_FS is not set
1321 +# CD-ROM/DVD Filesystems
1323 +# CONFIG_ISO9660_FS is not set
1324 +# CONFIG_UDF_FS is not set
1327 +# DOS/FAT/NT Filesystems
1332 +CONFIG_FAT_DEFAULT_CODEPAGE=437
1333 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
1334 +# CONFIG_NTFS_FS is not set
1337 +# Pseudo filesystems
1342 +# CONFIG_HUGETLBFS is not set
1343 +# CONFIG_HUGETLB_PAGE is not set
1345 +# CONFIG_RELAYFS_FS is not set
1348 +# Miscellaneous filesystems
1350 +# CONFIG_ADFS_FS is not set
1351 +# CONFIG_AFFS_FS is not set
1352 +# CONFIG_HFS_FS is not set
1353 +# CONFIG_HFSPLUS_FS is not set
1354 +# CONFIG_BEFS_FS is not set
1355 +# CONFIG_BFS_FS is not set
1356 +# CONFIG_EFS_FS is not set
1358 +CONFIG_JFFS_FS_VERBOSE=0
1359 +CONFIG_JFFS_PROC_FS=y
1361 +CONFIG_JFFS2_FS_DEBUG=4
1362 +CONFIG_JFFS2_FS_WRITEBUFFER=y
1363 +CONFIG_JFFS2_COMPRESSION_OPTIONS=y
1364 +CONFIG_JFFS2_ZLIB=y
1365 +CONFIG_JFFS2_RTIME=y
1366 +CONFIG_JFFS2_RUBIN=y
1367 +# CONFIG_JFFS2_CMODE_NONE is not set
1368 +CONFIG_JFFS2_CMODE_PRIORITY=y
1369 +# CONFIG_JFFS2_CMODE_SIZE is not set
1371 +# CONFIG_VXFS_FS is not set
1372 +# CONFIG_HPFS_FS is not set
1373 +# CONFIG_QNX4FS_FS is not set
1374 +# CONFIG_SYSV_FS is not set
1375 +# CONFIG_UFS_FS is not set
1378 +# Network File Systems
1382 +# CONFIG_NFS_V3_ACL is not set
1384 +# CONFIG_NFS_DIRECTIO is not set
1385 +# CONFIG_NFSD is not set
1389 +CONFIG_NFS_COMMON=y
1391 +CONFIG_SUNRPC_GSS=y
1392 +CONFIG_RPCSEC_GSS_KRB5=y
1393 +# CONFIG_RPCSEC_GSS_SPKM3 is not set
1394 +# CONFIG_SMB_FS is not set
1395 +# CONFIG_CIFS is not set
1396 +# CONFIG_NCP_FS is not set
1397 +# CONFIG_CODA_FS is not set
1398 +# CONFIG_AFS_FS is not set
1399 +# CONFIG_9P_FS is not set
1404 +CONFIG_PARTITION_ADVANCED=y
1405 +# CONFIG_ACORN_PARTITION is not set
1406 +# CONFIG_OSF_PARTITION is not set
1407 +# CONFIG_AMIGA_PARTITION is not set
1408 +# CONFIG_ATARI_PARTITION is not set
1409 +# CONFIG_MAC_PARTITION is not set
1410 +CONFIG_MSDOS_PARTITION=y
1411 +# CONFIG_BSD_DISKLABEL is not set
1412 +# CONFIG_MINIX_SUBPARTITION is not set
1413 +# CONFIG_SOLARIS_X86_PARTITION is not set
1414 +# CONFIG_UNIXWARE_DISKLABEL is not set
1415 +# CONFIG_LDM_PARTITION is not set
1416 +# CONFIG_SGI_PARTITION is not set
1417 +# CONFIG_ULTRIX_PARTITION is not set
1418 +# CONFIG_SUN_PARTITION is not set
1419 +# CONFIG_EFI_PARTITION is not set
1422 +# Native Language Support
1425 +CONFIG_NLS_DEFAULT="utf8"
1426 +CONFIG_NLS_CODEPAGE_437=y
1427 +# CONFIG_NLS_CODEPAGE_737 is not set
1428 +# CONFIG_NLS_CODEPAGE_775 is not set
1429 +# CONFIG_NLS_CODEPAGE_850 is not set
1430 +# CONFIG_NLS_CODEPAGE_852 is not set
1431 +# CONFIG_NLS_CODEPAGE_855 is not set
1432 +# CONFIG_NLS_CODEPAGE_857 is not set
1433 +# CONFIG_NLS_CODEPAGE_860 is not set
1434 +# CONFIG_NLS_CODEPAGE_861 is not set
1435 +# CONFIG_NLS_CODEPAGE_862 is not set
1436 +# CONFIG_NLS_CODEPAGE_863 is not set
1437 +# CONFIG_NLS_CODEPAGE_864 is not set
1438 +# CONFIG_NLS_CODEPAGE_865 is not set
1439 +# CONFIG_NLS_CODEPAGE_866 is not set
1440 +# CONFIG_NLS_CODEPAGE_869 is not set
1441 +# CONFIG_NLS_CODEPAGE_936 is not set
1442 +# CONFIG_NLS_CODEPAGE_950 is not set
1443 +# CONFIG_NLS_CODEPAGE_932 is not set
1444 +# CONFIG_NLS_CODEPAGE_949 is not set
1445 +# CONFIG_NLS_CODEPAGE_874 is not set
1446 +# CONFIG_NLS_ISO8859_8 is not set
1447 +# CONFIG_NLS_CODEPAGE_1250 is not set
1448 +# CONFIG_NLS_CODEPAGE_1251 is not set
1449 +# CONFIG_NLS_ASCII is not set
1450 +CONFIG_NLS_ISO8859_1=y
1451 +# CONFIG_NLS_ISO8859_2 is not set
1452 +# CONFIG_NLS_ISO8859_3 is not set
1453 +# CONFIG_NLS_ISO8859_4 is not set
1454 +# CONFIG_NLS_ISO8859_5 is not set
1455 +# CONFIG_NLS_ISO8859_6 is not set
1456 +# CONFIG_NLS_ISO8859_7 is not set
1457 +# CONFIG_NLS_ISO8859_9 is not set
1458 +# CONFIG_NLS_ISO8859_13 is not set
1459 +# CONFIG_NLS_ISO8859_14 is not set
1460 +# CONFIG_NLS_ISO8859_15 is not set
1461 +# CONFIG_NLS_KOI8_R is not set
1462 +# CONFIG_NLS_KOI8_U is not set
1466 +# Profiling support
1468 +# CONFIG_PROFILING is not set
1473 +# CONFIG_PRINTK_TIME is not set
1474 +CONFIG_DEBUG_KERNEL=y
1475 +CONFIG_MAGIC_SYSRQ=y
1476 +CONFIG_LOG_BUF_SHIFT=17
1477 +CONFIG_DETECT_SOFTLOCKUP=y
1478 +# CONFIG_SCHEDSTATS is not set
1479 +# CONFIG_DEBUG_SLAB is not set
1480 +# CONFIG_DEBUG_SPINLOCK is not set
1481 +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
1482 +# CONFIG_DEBUG_KOBJECT is not set
1483 +# CONFIG_DEBUG_BUGVERBOSE is not set
1484 +# CONFIG_DEBUG_INFO is not set
1485 +# CONFIG_DEBUG_FS is not set
1486 +CONFIG_FRAME_POINTER=y
1487 +# CONFIG_DEBUG_USER is not set
1488 +# CONFIG_DEBUG_WAITQ is not set
1489 +CONFIG_DEBUG_ERRORS=y
1491 +# CONFIG_DEBUG_ICEDCC is not set
1496 +# CONFIG_KEYS is not set
1497 +# CONFIG_SECURITY is not set
1500 +# Cryptographic options
1503 +CONFIG_CRYPTO_HMAC=y
1504 +# CONFIG_CRYPTO_NULL is not set
1505 +# CONFIG_CRYPTO_MD4 is not set
1506 +CONFIG_CRYPTO_MD5=y
1507 +CONFIG_CRYPTO_SHA1=y
1508 +# CONFIG_CRYPTO_SHA256 is not set
1509 +# CONFIG_CRYPTO_SHA512 is not set
1510 +# CONFIG_CRYPTO_WP512 is not set
1511 +# CONFIG_CRYPTO_TGR192 is not set
1512 +CONFIG_CRYPTO_DES=y
1513 +# CONFIG_CRYPTO_BLOWFISH is not set
1514 +# CONFIG_CRYPTO_TWOFISH is not set
1515 +# CONFIG_CRYPTO_SERPENT is not set
1516 +# CONFIG_CRYPTO_AES is not set
1517 +# CONFIG_CRYPTO_CAST5 is not set
1518 +# CONFIG_CRYPTO_CAST6 is not set
1519 +# CONFIG_CRYPTO_TEA is not set
1520 +# CONFIG_CRYPTO_ARC4 is not set
1521 +# CONFIG_CRYPTO_KHAZAD is not set
1522 +# CONFIG_CRYPTO_ANUBIS is not set
1523 +CONFIG_CRYPTO_DEFLATE=m
1524 +# CONFIG_CRYPTO_MICHAEL_MIC is not set
1525 +# CONFIG_CRYPTO_CRC32C is not set
1526 +# CONFIG_CRYPTO_TEST is not set
1529 +# Hardware crypto devices
1536 +# CONFIG_CRC16 is not set
1539 +CONFIG_ZLIB_INFLATE=y
1540 +CONFIG_ZLIB_DEFLATE=y
1541 +CONFIG_REED_SOLOMON=m
1542 +CONFIG_REED_SOLOMON_DEC16=y
1543 diff -Naur linux-2.6.14-omap2/arch/arm/Kconfig linux-h6300-omap2-2.6.14.3/arch/arm/Kconfig
1544 --- linux-2.6.14-omap2/arch/arm/Kconfig 2005-12-02 01:53:31.000000000 +0200
1545 +++ linux-h6300-omap2-2.6.14.3/arch/arm/Kconfig 2005-10-14 18:55:31.000000000 +0300
1548 source "drivers/video/Kconfig"
1550 +source "drivers/telephony/Kconfig"
1552 source "sound/Kconfig"
1554 source "drivers/usb/Kconfig"
1555 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
1556 --- linux-2.6.14-omap2/arch/arm/mach-omap1/board-h6300.c 1970-01-01 02:00:00.000000000 +0200
1557 +++ linux-h6300-omap2-2.6.14.3/arch/arm/mach-omap1/board-h6300.c 2005-10-22 03:52:45.000000000 +0300
1560 + * Modified from board-h6300.c
1562 + * Code for generic OMAP board. Should work on many OMAP systems where
1563 + * the device drivers take care of all the necessary hardware initialization.
1564 + * Do not put any board specific code to this file; create a new machine
1565 + * type if you need custom low-level initializations.
1567 + * This program is free software; you can redistribute it and/or modify
1568 + * it under the terms of the GNU General Public License version 2 as
1569 + * published by the Free Software Foundation.
1572 +#include <linux/kernel.h>
1573 +#include <linux/init.h>
1574 +#include <linux/device.h>
1575 +#include <linux/delay.h>
1576 +#include <linux/mtd/mtd.h>
1577 +#include <linux/mtd/partitions.h>
1579 +#include <asm/hardware.h>
1580 +#include <asm/mach-types.h>
1581 +#include <asm/mach/arch.h>
1582 +#include <asm/mach/flash.h>
1583 +#include <asm/mach/map.h>
1585 +#include <asm/arch/gpio.h>
1587 +#include <asm/arch/tc.h>
1588 +#include <asm/arch/usb.h>
1590 +#include <asm/arch/common.h>
1592 +#include <asm/arch/h6300_uart_info.h>
1595 + * Bluetooth - Relies on h6300_bt module,
1596 + * so make the calls indirectly through pointers. Requires that the
1597 + * h6300_bt bluetooth module be loaded before any attempt to use
1598 + * bluetooth (obviously).
1601 +static struct h6300_uart_funcs bt_funcs;
1602 +static struct h6300_uart_funcs gsm_funcs;
1605 +h6300_bt_configure(struct uart_omap_port *up, int enable)
1607 + printk(KERN_NOTICE "board-h6300.c, h6300_bt_configure() started\n");
1608 + if (bt_funcs.configure != NULL)
1609 + bt_funcs.configure(up, enable);
1610 + printk(KERN_NOTICE "board-h6300.c, h6300_bt_configure() done\n");
1614 +h6300_bt_set_txrx(struct uart_omap_port *up, int txrx)
1616 + printk(KERN_NOTICE "board-h6300.c, h6300_bt_set_txrx() started\n");
1617 + if (bt_funcs.set_txrx != NULL)
1619 + printk(KERN_NOTICE "board-h6300.c, h6300_bt_set_txrx(), bt_funcs.set_txrx != NULL\n");
1620 + bt_funcs.set_txrx(up, txrx);
1622 + printk(KERN_NOTICE "board-h6300.c, h6300_bt_set_txrx() done\n");
1626 +h6300_bt_get_txrx(struct uart_omap_port *up)
1630 + printk(KERN_NOTICE "board-h6300.c, h6300_bt_get_txrx() started\n");
1631 + if (bt_funcs.get_txrx != NULL)
1633 + retVal = bt_funcs.get_txrx(up);
1634 + printk(KERN_NOTICE "board-h6300.c, h6300_bt_get_txrx(), bt_funcs.get_trx != null, done, retVal %d\n", retVal);
1639 + printk(KERN_NOTICE "board-h6300.c, h6300_bt_get_txrx() done, returning 0\n");
1644 +static struct platform_omap_serial_funcs h6300_omap_bt_funcs = {
1645 + .configure = h6300_bt_configure,
1646 + .set_txrx = h6300_bt_set_txrx,
1647 + .get_txrx = h6300_bt_get_txrx,
1650 +struct platform_device btuart_device = {
1651 + .name = "h6300_bt",
1654 +EXPORT_SYMBOL(btuart_device);
1657 +h6300_gsm_configure(struct uart_omap_port *up, int enable)
1659 + printk(KERN_NOTICE "board-h6300.c, h6300_gsm_configure() started\n");
1660 + if (gsm_funcs.configure != NULL)
1661 + gsm_funcs.configure(up, enable);
1662 + printk(KERN_NOTICE "board-h6300.c, h6300_gsm_configure() done\n");
1666 +h6300_gsm_set_txrx(struct uart_omap_port *up, int txrx)
1668 + printk(KERN_NOTICE "board-h6300.c, h6300_gsm_set_txrx() started\n");
1669 + if (bt_funcs.set_txrx != NULL)
1671 + printk(KERN_NOTICE "board-h6300.c, h6300_gsm_set_txrx(), bt_funcs.set_txrx != NULL\n");
1672 + gsm_funcs.set_txrx(up, txrx);
1674 + printk(KERN_NOTICE "board-h6300.c, h6300_gsm_set_txrx() done\n");
1678 +h6300_gsm_get_txrx(struct uart_omap_port *up)
1682 + printk(KERN_NOTICE "board-h6300.c, h6300_gsm_get_txrx() started\n");
1683 + if (bt_funcs.get_txrx != NULL)
1685 + retVal = gsm_funcs.get_txrx(up);
1686 + printk(KERN_NOTICE "board-h6300.c, h6300_gsm_get_txrx(), bt_funcs.get_trx != null, done, retVal %d\n", retVal);
1691 + printk(KERN_NOTICE "board-h6300.c, h6300_gsm_get_txrx() done, returning 0\n");
1696 +static struct platform_omap_serial_funcs h6300_omap_gsm_funcs = {
1697 + .configure = h6300_gsm_configure,
1698 + .set_txrx = h6300_gsm_set_txrx,
1699 + .get_txrx = h6300_gsm_get_txrx,
1702 +struct platform_device gsmuart_device = {
1703 + .name = "h6300_gsm",
1706 +EXPORT_SYMBOL(gsmuart_device);
1709 +static struct mtd_partition h6300_partitions[] = {
1710 + /* bootloader (U-Boot, etc) in first sector */
1712 + .name = "bootloader",
1715 + .mask_flags = MTD_WRITEABLE, /* force read-only */
1717 + /* bootloader params in the next sector */
1720 + .offset = MTDPART_OFS_APPEND,
1727 + .offset = MTDPART_OFS_APPEND,
1731 + /* rest of flash1 is a file system */
1734 + .offset = MTDPART_OFS_APPEND,
1735 + .size = SZ_16M - SZ_2M - 2 * SZ_128K,
1740 + .name = "filesystem",
1741 + .offset = MTDPART_OFS_APPEND,
1742 + .size = MTDPART_SIZ_FULL,
1747 +static struct flash_platform_data h6300_flash_data = {
1748 + .map_name = "cfi_probe",
1750 + .parts = h6300_partitions,
1751 + .nr_parts = ARRAY_SIZE(h6300_partitions),
1754 +static struct resource h6300_flash_resource = {
1755 + .start = OMAP_CS0_PHYS,
1756 + .end = OMAP_CS0_PHYS + SZ_32M - 1,
1757 + .flags = IORESOURCE_MEM,
1760 +static struct platform_device h6300_flash_device = {
1761 + .name = "omapflash",
1764 + .platform_data = &h6300_flash_data,
1766 + .num_resources = 1,
1767 + .resource = &h6300_flash_resource,
1771 +static struct resource h6300_wlan_resource[] = {
1773 + .start = OMAP_CS1_PHYS,
1774 + .end = OMAP_CS1_PHYS + SZ_32M -1,
1775 + .flags = IORESOURCE_MEM,
1779 + .start = OMAP_GPIO_IRQ(11),
1780 + .end = OMAP_GPIO_IRQ(11),
1781 + .flags = IORESOURCE_IRQ,
1785 +static struct platform_device h6300_wlan_device = {
1786 + .name = "tnetw1100b",
1788 + .num_resources = 2,
1789 + .resource = h6300_wlan_resource,
1792 +static struct platform_device *h6300_devices[] __initdata = {
1795 + &h6300_wlan_device,
1796 + //&h6300_flash_device,
1799 +static void __init h6300_init_irq(void)
1804 + omap_request_gpio (2);
1805 + omap_set_gpio_direction (2, 0);
1806 + omap_set_gpio_dataout (2, 1);
1809 +/* assume no Mini-AB port */
1811 +static struct omap_usb_config h6300_usb_config __initdata = {
1813 + .register_dev = 1,
1817 +static struct omap_lcd_config h6300_lcd_config __initdata = {
1818 + .panel_name = "h6300",
1819 + .ctrl_name = "internal",
1822 +static struct omap_mmc_config h6300_mmc_config __initdata = {
1826 + .wp_pin = OMAP_GPIO_IRQ(13),
1827 + .power_pin = -1, /* FPGA F3 UIO42 */
1828 + .switch_pin = -1, /* FPGA F4 UIO43 */
1832 +static struct omap_uart_config h6300_uart_config __initdata = {
1833 + .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)),
1836 +static struct omap_board_config_kernel h6300_config[] = {
1837 + { OMAP_TAG_USB, &h6300_usb_config },
1838 + { OMAP_TAG_MMC, &h6300_mmc_config },
1839 + { OMAP_TAG_UART, &h6300_uart_config },
1840 + { OMAP_TAG_LCD, &h6300_lcd_config },
1843 +static void __init h6300_init(void)
1847 + ret = platform_add_devices(h6300_devices, ARRAY_SIZE(h6300_devices));
1850 + printk(KERN_WARNING "Unable to add h6300 platform devices like bluetooth");
1852 + omap_board_config = h6300_config;
1853 + omap_board_config_size = ARRAY_SIZE(h6300_config);
1854 + omap_serial_init();
1857 +static void __init h6300_map_io(void)
1859 + omap_map_common_io();
1861 + btuart_device.dev.platform_data = &h6300_omap_bt_funcs;
1862 + gsmuart_device.dev.platform_data = &h6300_omap_gsm_funcs;
1865 +MACHINE_START(H6300, "HP iPAQ H6300")
1866 + /* MAINTAINER("Everett Coleman II <gcc80x86@fuzzyneural.net>") */
1867 + .phys_ram = 0x10000000,
1868 + .phys_io = 0xfff00000,
1869 + .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc,
1870 + .boot_params = 0x10000100,
1871 + .map_io = h6300_map_io,
1872 + .init_irq = h6300_init_irq,
1873 + .init_machine = h6300_init,
1874 + .timer = &omap_timer,
1876 diff -Naur linux-2.6.14-omap2/arch/arm/mach-omap1/Kconfig linux-h6300-omap2-2.6.14.3/arch/arm/mach-omap1/Kconfig
1877 --- linux-2.6.14-omap2/arch/arm/mach-omap1/Kconfig 2005-12-02 01:53:31.000000000 +0200
1878 +++ linux-h6300-omap2-2.6.14.3/arch/arm/mach-omap1/Kconfig 2005-10-22 03:52:45.000000000 +0300
1880 TI OMAP 1510 or 1610 Innovator board support. Say Y here if you
1883 +config MACH_OMAP_H6300
1884 + bool "HP IPaq H6300"
1885 + depends on ARCH_OMAP1 && ARCH_OMAP15XX
1887 + HP IPaq H6300 series.
1890 bool "TI H2 Support"
1891 depends on ARCH_OMAP1 && ARCH_OMAP16XX
1892 diff -Naur linux-2.6.14-omap2/arch/arm/mach-omap1/Makefile linux-h6300-omap2-2.6.14.3/arch/arm/mach-omap1/Makefile
1893 --- linux-2.6.14-omap2/arch/arm/mach-omap1/Makefile 2005-12-02 01:53:31.000000000 +0200
1894 +++ linux-h6300-omap2-2.6.14.3/arch/arm/mach-omap1/Makefile 2005-10-22 03:52:45.000000000 +0300
1896 obj-$(CONFIG_MACH_OMAP_H3) += board-h3.o
1897 obj-$(CONFIG_MACH_VOICEBLUE) += board-voiceblue.o
1898 obj-$(CONFIG_MACH_NETSTAR) += board-netstar.o
1899 -obj-$(CONFIG_MACH_OMAP_PALMTE) += board-palmte.o
1900 +obj-$(CONFIG_MACH_OMAP_PALMTE) += board-palmte.o
1901 +obj-$(CONFIG_MACH_OMAP_H6300) += board-h6300.o
1903 ifeq ($(CONFIG_ARCH_OMAP15XX),y)
1904 # Innovator-1510 FPGA
1905 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
1906 --- linux-2.6.14-omap2/arch/arm/mach-omap1/mux.c 2005-12-02 01:53:32.000000000 +0200
1907 +++ linux-h6300-omap2-2.6.14.3/arch/arm/mach-omap1/mux.c 2005-11-11 04:13:42.000000000 +0200
1908 @@ -196,6 +196,13 @@
1909 MUX_CFG("P15_1610_UWIRE_CS3", 8, 12, 1, 1, 22, 0, 1, 1, 1)
1910 MUX_CFG("N15_1610_UWIRE_CS1", 7, 18, 2, 1, 14, 0, NA, 0, 1)
1912 +/* OMAP-1510 uWire */
1913 +MUX_CFG("P15_1510_UWIRE_CS3", 8, 12, 1, NA, 0, 0, NA, 0, 1)
1914 +MUX_CFG("N14_1510_UWIRE_CS0", 8, 9, 1, NA, 0, 0, NA, 0, 1)
1915 +MUX_CFG("V19_1510_UWIRE_SCLK", 8, 6, 0, NA, 0, 0, NA, 0, 1)
1916 +MUX_CFG("W21_1510_UWIRE_SDO", 8, 3, 0, NA, 0, 0, NA, 0, 1)
1917 +MUX_CFG("U18_1510_UWIRE_SDI", 8, 0, 0, 1, 18, 0, NA, 0, 1)
1919 /* OMAP-1610 Flash */
1920 MUX_CFG("L3_1610_FLASH_CS2B_OE",10, 6, 1, NA, 0, 0, NA, 0, 1)
1921 MUX_CFG("M8_1610_FLASH_CS2B_WE",10, 3, 1, NA, 0, 0, NA, 0, 1)
1923 MUX_CFG("T20_1610_LOW_PWR", 7, 12, 1, NA, 0, 0, NA, 0, 0)
1926 +MUX_CFG("R10_1510_MCLK_ON", B, 18, 0, 2, 22, 1, NA, 1, 1)
1927 MUX_CFG("V5_1710_MCLK_ON", B, 15, 0, NA, 0, 0, NA, 0, 0)
1928 MUX_CFG("V5_1710_MCLK_OFF", B, 15, 6, NA, 0, 0, NA, 0, 0)
1929 MUX_CFG("R10_1610_MCLK_ON", B, 18, 0, NA, 22, 0, NA, 1, 0)
1930 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
1931 --- linux-2.6.14-omap2/arch/arm/plat-omap/dma.c 2005-12-02 01:53:32.000000000 +0200
1932 +++ linux-h6300-omap2-2.6.14.3/arch/arm/plat-omap/dma.c 2005-11-11 04:13:42.000000000 +0200
1934 #include <asm/hardware.h>
1935 #include <asm/dma.h>
1937 +#include <asm/mach-types.h>
1939 #include <asm/arch/tc.h>
1941 @@ -1086,6 +1087,10 @@
1944 if (omap_dma_in_1510_mode()) {
1945 + u16 l = omap_readw(OMAP1510_DMA_LCD_CTRL);
1947 + omap_writew (l, OMAP1510_DMA_LCD_CTRL);
1949 omap_writew(top >> 16, OMAP1510_DMA_LCD_TOP_F1_U);
1950 omap_writew(top, OMAP1510_DMA_LCD_TOP_F1_L);
1951 omap_writew(bottom >> 16, OMAP1510_DMA_LCD_BOT_F1_U);
1952 diff -Naur linux-2.6.14-omap2/arch/arm/tools/mach-types linux-h6300-omap2-2.6.14.3/arch/arm/tools/mach-types
1953 --- linux-2.6.14-omap2/arch/arm/tools/mach-types 2005-10-28 03:02:08.000000000 +0300
1954 +++ linux-h6300-omap2-2.6.14.3/arch/arm/tools/mach-types 2005-10-22 03:52:45.000000000 +0300
1956 s3c2460 MACH_S3C2460 S3C2460 560
1957 pdm MACH_PDM PDM 561
1958 h4700 MACH_H4700 H4700 562
1959 -h6300 MACH_H6300 H6300 563
1960 +h6300 MACH_OMAP_H6300 H6300 563
1961 rz1700 MACH_RZ1700 RZ1700 564
1962 a716 MACH_A716 A716 565
1963 estk2440a MACH_ESTK2440A ESTK2440A 566
1964 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
1965 --- linux-2.6.14-omap2/arch/i386/kernel/cpu/mtrr/main.c 2005-10-28 03:02:08.000000000 +0300
1966 +++ linux-h6300-omap2-2.6.14.3/arch/i386/kernel/cpu/mtrr/main.c 2005-12-02 01:34:34.000000000 +0200
1967 @@ -626,6 +626,14 @@
1968 if (cpuid_eax(0x80000000) >= 0x80000008) {
1970 phys_addr = cpuid_eax(0x80000008) & 0xff;
1971 + /* CPUID workaround for Intel 0F33/0F34 CPU */
1972 + if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
1973 + boot_cpu_data.x86 == 0xF &&
1974 + boot_cpu_data.x86_model == 0x3 &&
1975 + (boot_cpu_data.x86_mask == 0x3 ||
1976 + boot_cpu_data.x86_mask == 0x4))
1979 size_or_mask = ~((1 << (phys_addr - PAGE_SHIFT)) - 1);
1980 size_and_mask = ~size_or_mask & 0xfff00000;
1981 } else if (boot_cpu_data.x86_vendor == X86_VENDOR_CENTAUR &&
1982 diff -Naur linux-2.6.14-omap2/arch/ppc64/Kconfig linux-h6300-omap2-2.6.14.3/arch/ppc64/Kconfig
1983 --- linux-2.6.14-omap2/arch/ppc64/Kconfig 2005-10-28 03:02:08.000000000 +0300
1984 +++ linux-h6300-omap2-2.6.14.3/arch/ppc64/Kconfig 2005-12-02 01:34:35.000000000 +0200
1985 @@ -234,6 +234,10 @@
1986 This option enables hardware multithreading on RS64 cpus.
1987 pSeries systems p620 and p660 have such a cpu type.
1990 + bool "NUMA support"
1991 + default y if DISCONTIGMEM || SPARSEMEM
1993 config ARCH_SELECT_MEMORY_MODEL
1998 depends on ARCH_DISCONTIGMEM_ENABLE
2000 -config ARCH_FLATMEM_ENABLE
2003 config ARCH_SPARSEMEM_ENABLE
2005 depends on ARCH_DISCONTIGMEM_ENABLE
2006 @@ -274,10 +275,6 @@
2008 depends on NEED_MULTIPLE_NODES
2011 - bool "NUMA support"
2012 - default y if DISCONTIGMEM || SPARSEMEM
2015 bool "SMT (Hyperthreading) scheduler support"
2017 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
2018 --- linux-2.6.14-omap2/arch/s390/appldata/appldata_base.c 2005-10-28 03:02:08.000000000 +0300
2019 +++ linux-h6300-omap2-2.6.14.3/arch/s390/appldata/appldata_base.c 2005-11-23 01:44:02.000000000 +0200
2020 @@ -592,12 +592,15 @@
2022 void appldata_unregister_ops(struct appldata_ops *ops)
2025 spin_lock(&appldata_ops_lock);
2026 - unregister_sysctl_table(ops->sysctl_header);
2027 list_del(&ops->list);
2028 - kfree(ops->ctl_table);
2029 + /* at that point any incoming access will fail */
2030 + table = ops->ctl_table;
2031 ops->ctl_table = NULL;
2032 spin_unlock(&appldata_ops_lock);
2033 + unregister_sysctl_table(ops->sysctl_header);
2035 P_INFO("%s-ops unregistered!\n", ops->name);
2037 /********************** module-ops management <END> **************************/
2038 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
2039 --- linux-2.6.14-omap2/arch/x86_64/kernel/setup.c 2005-10-28 03:02:08.000000000 +0300
2040 +++ linux-h6300-omap2-2.6.14.3/arch/x86_64/kernel/setup.c 2005-12-02 01:34:35.000000000 +0200
2041 @@ -993,6 +993,11 @@
2042 unsigned eax = cpuid_eax(0x80000008);
2043 c->x86_virt_bits = (eax >> 8) & 0xff;
2044 c->x86_phys_bits = eax & 0xff;
2045 + /* CPUID workaround for Intel 0F34 CPU */
2046 + if (c->x86_vendor == X86_VENDOR_INTEL &&
2047 + c->x86 == 0xF && c->x86_model == 0x3 &&
2048 + c->x86_mask == 0x4)
2049 + c->x86_phys_bits = 36;
2053 diff -Naur linux-2.6.14-omap2/drivers/block/cfq-iosched.c linux-h6300-omap2-2.6.14.3/drivers/block/cfq-iosched.c
2054 --- linux-2.6.14-omap2/drivers/block/cfq-iosched.c 2005-10-28 03:02:08.000000000 +0300
2055 +++ linux-h6300-omap2-2.6.14.3/drivers/block/cfq-iosched.c 2005-11-23 01:44:02.000000000 +0200
2056 @@ -2260,10 +2260,8 @@
2057 if (!atomic_dec_and_test(&cfqd->ref))
2062 cfq_shutdown_timer_wq(cfqd);
2063 - q->elevator->elevator_data = NULL;
2066 mempool_destroy(cfqd->crq_pool);
2067 kfree(cfqd->crq_hash);
2068 diff -Naur linux-2.6.14-omap2/drivers/block/pktcdvd.c linux-h6300-omap2-2.6.14.3/drivers/block/pktcdvd.c
2069 --- linux-2.6.14-omap2/drivers/block/pktcdvd.c 2005-10-28 03:02:08.000000000 +0300
2070 +++ linux-h6300-omap2-2.6.14.3/drivers/block/pktcdvd.c 2005-12-02 01:34:35.000000000 +0200
2071 @@ -1191,7 +1191,7 @@
2072 struct packet_data *pkt;
2075 - for (i = 0; i <= PACKET_NUM_STATES; i++)
2076 + for (i = 0; i < PACKET_NUM_STATES; i++)
2079 spin_lock(&pd->cdrw.active_list_lock);
2080 diff -Naur linux-2.6.14-omap2/drivers/bluetooth/Kconfig linux-h6300-omap2-2.6.14.3/drivers/bluetooth/Kconfig
2081 --- linux-2.6.14-omap2/drivers/bluetooth/Kconfig 2005-10-28 03:02:08.000000000 +0300
2082 +++ linux-h6300-omap2-2.6.14.3/drivers/bluetooth/Kconfig 2005-10-04 00:58:34.000000000 +0300
2083 @@ -163,6 +163,16 @@
2085 Say Y here to compile support for virtual HCI devices into the
2086 kernel or say M to compile it as module (hci_vhci).
2089 + tristate "H6300 BRF6100 BT DRIVER"
2091 + Bluetooth H6300 BRF6100 driver.
2092 + This driver provides the firmware loading mechanism for the BRF6100
2093 + bt hardware in iPAQ h6300.
2095 + Say Y here to compile support for BRF6100 BT devices into the
2096 + kernel or say M to compile it as module (h6300_BT).
2100 diff -Naur linux-2.6.14-omap2/drivers/bluetooth/Makefile linux-h6300-omap2-2.6.14.3/drivers/bluetooth/Makefile
2101 --- linux-2.6.14-omap2/drivers/bluetooth/Makefile 2005-10-28 03:02:08.000000000 +0300
2102 +++ linux-h6300-omap2-2.6.14.3/drivers/bluetooth/Makefile 2005-09-28 01:04:13.000000000 +0300
2104 obj-$(CONFIG_BT_HCIBFUSB) += bfusb.o
2105 obj-$(CONFIG_BT_HCIDTL1) += dtl1_cs.o
2106 obj-$(CONFIG_BT_HCIBT3C) += bt3c_cs.o
2107 -obj-$(CONFIG_BT_HCIBLUECARD) += bluecard_cs.o
2108 +obj-$(CONFIG_BT_HCIBLUECARD)+= bluecard_cs.o
2109 obj-$(CONFIG_BT_HCIBTUART) += btuart_cs.o
2110 +obj-$(CONFIG_BT_H6300) += omap/
2112 -hci_uart-y := hci_ldisc.o
2113 +hci_uart-y := hci_ldisc.o
2114 hci_uart-$(CONFIG_BT_HCIUART_H4) += hci_h4.o
2115 hci_uart-$(CONFIG_BT_HCIUART_BCSP) += hci_bcsp.o
2116 -hci_uart-objs := $(hci_uart-y)
2117 +hci_uart-objs := $(hci_uart-y)
2118 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
2119 --- linux-2.6.14-omap2/drivers/bluetooth/omap/h6300_bt_brf6100.c 1970-01-01 02:00:00.000000000 +0200
2120 +++ linux-h6300-omap2-2.6.14.3/drivers/bluetooth/omap/h6300_bt_brf6100.c 2005-12-02 00:45:30.000000000 +0200
2123 + * Bluetooth interface driver for TI BRF6100 on h6300
2125 + * Copyright (C) 2005 Mika Laitio <lamikr@cc.jyu.fi>
2126 + * Ideas taken from the brf6150 bt driver made by Todd Blumer for the pxa hx4700.
2128 + * This program is free software; you can redistribute it and/or modify
2129 + * it under the terms of the GNU General Public License version 2 as
2130 + * published by the Free Software Foundation.
2133 +#include <linux/module.h>
2134 +#include <linux/kernel.h>
2135 +#include <linux/delay.h>
2136 +#include <linux/device.h>
2138 +#include <asm/hardware.h>
2139 +#include <asm/arch/gpio.h>
2141 +#include <asm/arch/h6300_uart_info.h>
2142 +#include "h6300_bt_led.h"
2145 +h6300_bt_configure(struct uart_omap_port *up, int enable)
2147 + printk(KERN_NOTICE "h6300_bt_brf6100.c h6300_bt_configure() started, enable = %d\n", enable);
2149 + // printk( KERN_NOTICE "h6300 configure bluetooth: %d\n", enable );
2150 + if (enable == 0) {
2151 + omap_set_gpio_dataout(GPIO_N_BT_RST, 1); // turn off gpio, note 1 == off for negative gpios
2153 + h6300_clear_led(INDEX_BT_LED);
2155 + else if (enable == 1) {
2156 + omap_set_gpio_dataout(GPIO_N_BT_RST, 1); // turn on gpio, note 0 == on for negative gpios
2159 + else if (enable == 2) {
2161 + * BRF6150's RTS goes low when firmware is ready
2162 + * so check for CTS=1 (nCTS=0 -> CTS=1). Typical 150ms
2170 + while ((BTMSR & MSR_CTS) == 0 && tries++ < 50);
2172 + h6300_set_led(INDEX_BT_LED, 16, 16);
2174 + printk(KERN_NOTICE "h6300_bt_brf6100.c h6300_bt_configure() done\n");
2178 +h6300_bt_set_txrx(struct uart_omap_port *up, int txrx)
2180 + printk(KERN_NOTICE "h6300_bt_brf6100.c h6300_bt_set_txrx(), txrx = %d done\n", txrx);
2185 +h6300_bt_get_txrx(struct uart_omap_port *up)
2187 + printk(KERN_NOTICE "h6300_bt_brf6100.c h6300_bt_get_txrx() done\n");
2193 +h6300_bt_probe(struct device *dev)
2195 + struct h6300_uart_funcs *funcs = (struct h6300_uart_funcs *)dev->platform_data;
2197 + omap_request_gpio(GPIO_BT_PWR_EN); // ask bt_power_en gpio, remember to release in remove_function
2198 + omap_set_gpio_direction(GPIO_BT_PWR_EN, 1); // set gpio direction to be output
2199 + omap_set_gpio_dataout(GPIO_BT_PWR_EN, 1); // turn on gpio
2203 + omap_request_gpio(GPIO_N_BT_RST); // ask bt_reset gpio, remember to release in remove_function
2204 + omap_set_gpio_direction(GPIO_N_BT_RST, 1); // set gpio direction to be output
2205 + omap_set_gpio_dataout(GPIO_N_BT_RST, 0); // turn on gpio, note 0 == on for negative gpios
2207 + /* configure bluetooth UART */
2208 + //h6300_gpio_mode(GPIO_NR_H6300_BT_RXD_MD);
2209 + //h6300_gpio_mode(GPIO_NR_H6300_BT_TXD_MD);
2210 + //h6300_gpio_mode(GPIO_NR_H6300_BT_UART_CTS_MD);
2211 + //h6300_gpio_mode(GPIO_NR_H6300_BT_UART_RTS_MD);
2213 + funcs->configure = h6300_bt_configure;
2214 + funcs->set_txrx = h6300_bt_set_txrx;
2215 + funcs->get_txrx = h6300_bt_get_txrx;
2217 + /* Make sure the LED is off */
2218 + h6300_clear_led(INDEX_BT_LED);
2220 + printk(KERN_NOTICE "h6300_bt_brf6100.c h6300_bt_probe() done\n");
2226 +h6300_bt_remove(struct device *dev)
2228 + struct h6300_uart_funcs *funcs = (struct h6300_uart_funcs *)dev->platform_data;
2230 + printk(KERN_NOTICE "h6300_bt_brf6100.c h6300_bt_remove() started\n");
2232 + omap_free_gpio(GPIO_BT_PWR_EN);
2233 + omap_free_gpio(GPIO_N_BT_RST);
2235 + funcs->configure = NULL;
2236 + funcs->set_txrx = NULL;
2237 + funcs->get_txrx = NULL;
2239 + /* Make sure the LED is off */
2240 + h6300_clear_led(INDEX_BT_LED);
2242 + printk(KERN_NOTICE "h6300_bt_brf6100.c, h6300_bt_remove() done\n");
2247 +static struct device_driver bt_driver = {
2248 + .name = "h6300_bt",
2249 + .bus = &platform_bus_type,
2250 + .probe = h6300_bt_probe,
2251 + .remove = h6300_bt_remove,
2255 +h6300_bt_init(void)
2257 + printk(KERN_NOTICE "h6300 Bluetooth Driver init()\n");
2258 + return driver_register(&bt_driver);
2262 +h6300_bt_exit(void)
2264 + printk(KERN_NOTICE "h6300 Bluetooth Driver exit()\n");
2265 + driver_unregister(&bt_driver);
2268 +module_init(h6300_bt_init);
2269 +module_exit(h6300_bt_exit);
2271 +MODULE_AUTHOR("Mika Laitio, <lamikr@cc.jyu.fi>");
2272 +MODULE_DESCRIPTION("iPAQ h6300 BRF6100 Bluetooth driver.");
2273 +MODULE_LICENSE("GPL");
2275 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
2276 --- linux-2.6.14-omap2/drivers/bluetooth/omap/h6300_bt_led.c 1970-01-01 02:00:00.000000000 +0200
2277 +++ linux-h6300-omap2-2.6.14.3/drivers/bluetooth/omap/h6300_bt_led.c 2005-10-06 02:34:39.000000000 +0300
2280 + * Bluetooth interface driver helper for controlling bluetooth leds available in iPAQ h6300.
2282 + * Copyright (C) 2005 Mika Laitio <lamikr@cc.jyu.fi>
2283 + * Ideas from the brf6150 bt driver made by Todd Blumer for the pxa hx4700.
2285 + * This program is free software; you can redistribute it and/or modify
2286 + * it under the terms of the GNU General Public License version 2 as
2287 + * published by the Free Software Foundation.
2290 +#include <linux/module.h>
2291 +#include <linux/kernel.h>
2292 +#include <linux/delay.h>
2293 +#include <linux/device.h>
2295 +#include <asm/hardware.h>
2296 +#include <asm/arch/gpio.h>
2299 + * Low level access for disabling h6300 bt led.
2301 + * TODO: implement for h6300
2303 +void h6300_clear_led(int led_num)
2305 + printk(KERN_NOTICE "h6300_bt_led.c h6300_clear_led() done\n");
2306 + //hx4700_set_led(led_num, 0, 16);
2308 +EXPORT_SYMBOL(h6300_clear_led);
2311 + * Low level access for setting up the bt led.
2313 + * TODO: implement for h6300
2315 +void h6300_set_led(int led_num, int duty_time, int cycle_time)
2317 + printk(KERN_NOTICE "h6300_bt_led.c h6300_set_led() done\n");
2319 +EXPORT_SYMBOL(h6300_set_led);
2320 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
2321 --- linux-2.6.14-omap2/drivers/bluetooth/omap/h6300_bt_led.h 1970-01-01 02:00:00.000000000 +0200
2322 +++ linux-h6300-omap2-2.6.14.3/drivers/bluetooth/omap/h6300_bt_led.h 2005-10-06 02:34:39.000000000 +0300
2324 +#ifndef H6300_BT_LED_H_
2325 +#define H6300_BT_LED_H_
2327 +#define INDEX_BT_LED 2
2329 +void h6300_clear_led(int led_num);
2330 +void h6300_set_led(int led_num, int duty_time, int cycle_time);
2332 +#endif /*H6300_BT_LED_H_*/
2333 diff -Naur linux-2.6.14-omap2/drivers/bluetooth/omap/Makefile linux-h6300-omap2-2.6.14.3/drivers/bluetooth/omap/Makefile
2334 --- linux-2.6.14-omap2/drivers/bluetooth/omap/Makefile 1970-01-01 02:00:00.000000000 +0200
2335 +++ linux-h6300-omap2-2.6.14.3/drivers/bluetooth/omap/Makefile 2005-10-06 02:34:39.000000000 +0300
2338 +# Makefile for the Linux iPAQ H6300 BRF6100 Bluetooth device drivers.
2341 +h6300_bt-objs := h6300_bt_led.o h6300_bt_brf6100.o
2342 +obj-$(CONFIG_BT_H6300) += h6300_bt.o
2343 diff -Naur linux-2.6.14-omap2/drivers/char/rtc.c linux-h6300-omap2-2.6.14.3/drivers/char/rtc.c
2344 --- linux-2.6.14-omap2/drivers/char/rtc.c 2005-10-28 03:02:08.000000000 +0300
2345 +++ linux-h6300-omap2-2.6.14.3/drivers/char/rtc.c 2005-12-02 01:34:35.000000000 +0200
2346 @@ -149,8 +149,22 @@
2348 static void rtc_dropped_irq(unsigned long data);
2350 -static void set_rtc_irq_bit(unsigned char bit);
2351 -static void mask_rtc_irq_bit(unsigned char bit);
2352 +static void set_rtc_irq_bit_locked(unsigned char bit);
2353 +static void mask_rtc_irq_bit_locked(unsigned char bit);
2355 +static inline void set_rtc_irq_bit(unsigned char bit)
2357 + spin_lock_irq(&rtc_lock);
2358 + set_rtc_irq_bit_locked(bit);
2359 + spin_unlock_irq(&rtc_lock);
2362 +static void mask_rtc_irq_bit(unsigned char bit)
2364 + spin_lock_irq(&rtc_lock);
2365 + mask_rtc_irq_bit_locked(bit);
2366 + spin_unlock_irq(&rtc_lock);
2370 static int rtc_proc_open(struct inode *inode, struct file *file);
2371 @@ -401,18 +415,19 @@
2373 case RTC_PIE_OFF: /* Mask periodic int. enab. bit */
2375 - mask_rtc_irq_bit(RTC_PIE);
2376 + unsigned long flags; /* can be called from isr via rtc_control() */
2377 + spin_lock_irqsave (&rtc_lock, flags);
2378 + mask_rtc_irq_bit_locked(RTC_PIE);
2379 if (rtc_status & RTC_TIMER_ON) {
2380 - spin_lock_irq (&rtc_lock);
2381 rtc_status &= ~RTC_TIMER_ON;
2382 del_timer(&rtc_irq_timer);
2383 - spin_unlock_irq (&rtc_lock);
2385 + spin_unlock_irqrestore (&rtc_lock, flags);
2388 case RTC_PIE_ON: /* Allow periodic ints */
2391 + unsigned long flags; /* can be called from isr via rtc_control() */
2393 * We don't really want Joe User enabling more
2394 * than 64Hz of interrupts on a multi-user machine.
2395 @@ -421,14 +436,14 @@
2396 (!capable(CAP_SYS_RESOURCE)))
2399 + spin_lock_irqsave (&rtc_lock, flags);
2400 if (!(rtc_status & RTC_TIMER_ON)) {
2401 - spin_lock_irq (&rtc_lock);
2402 rtc_irq_timer.expires = jiffies + HZ/rtc_freq + 2*HZ/100;
2403 add_timer(&rtc_irq_timer);
2404 rtc_status |= RTC_TIMER_ON;
2405 - spin_unlock_irq (&rtc_lock);
2407 - set_rtc_irq_bit(RTC_PIE);
2408 + set_rtc_irq_bit_locked(RTC_PIE);
2409 + spin_unlock_irqrestore (&rtc_lock, flags);
2412 case RTC_UIE_OFF: /* Mask ints from RTC updates. */
2417 + unsigned long flags; /* can be called from isr via rtc_control() */
2420 * The max we can do is 8192Hz.
2422 if (arg != (1<<tmp))
2425 - spin_lock_irq(&rtc_lock);
2426 + spin_lock_irqsave(&rtc_lock, flags);
2427 if (hpet_set_periodic_freq(arg)) {
2428 - spin_unlock_irq(&rtc_lock);
2429 + spin_unlock_irqrestore(&rtc_lock, flags);
2434 val = CMOS_READ(RTC_FREQ_SELECT) & 0xf0;
2436 CMOS_WRITE(val, RTC_FREQ_SELECT);
2437 - spin_unlock_irq(&rtc_lock);
2438 + spin_unlock_irqrestore(&rtc_lock, flags);
2442 @@ -844,12 +860,15 @@
2446 - spin_lock_irq(&rtc_task_lock);
2447 + unsigned long flags;
2448 + if (cmd != RTC_PIE_ON && cmd != RTC_PIE_OFF && cmd != RTC_IRQP_SET)
2450 + spin_lock_irqsave(&rtc_task_lock, flags);
2451 if (rtc_callback != task) {
2452 - spin_unlock_irq(&rtc_task_lock);
2453 + spin_unlock_irqrestore(&rtc_task_lock, flags);
2456 - spin_unlock_irq(&rtc_task_lock);
2457 + spin_unlock_irqrestore(&rtc_task_lock, flags);
2458 return rtc_do_ioctl(cmd, arg, 1);
2461 @@ -1306,40 +1325,32 @@
2462 * meddles with the interrupt enable/disable bits.
2465 -static void mask_rtc_irq_bit(unsigned char bit)
2466 +static void mask_rtc_irq_bit_locked(unsigned char bit)
2470 - spin_lock_irq(&rtc_lock);
2471 - if (hpet_mask_rtc_irq_bit(bit)) {
2472 - spin_unlock_irq(&rtc_lock);
2473 + if (hpet_mask_rtc_irq_bit(bit))
2476 val = CMOS_READ(RTC_CONTROL);
2478 CMOS_WRITE(val, RTC_CONTROL);
2479 CMOS_READ(RTC_INTR_FLAGS);
2482 - spin_unlock_irq(&rtc_lock);
2485 -static void set_rtc_irq_bit(unsigned char bit)
2486 +static void set_rtc_irq_bit_locked(unsigned char bit)
2490 - spin_lock_irq(&rtc_lock);
2491 - if (hpet_set_rtc_irq_bit(bit)) {
2492 - spin_unlock_irq(&rtc_lock);
2493 + if (hpet_set_rtc_irq_bit(bit))
2496 val = CMOS_READ(RTC_CONTROL);
2498 CMOS_WRITE(val, RTC_CONTROL);
2499 CMOS_READ(RTC_INTR_FLAGS);
2502 - spin_unlock_irq(&rtc_lock);
2506 diff -Naur linux-2.6.14-omap2/drivers/hwmon/it87.c linux-h6300-omap2-2.6.14.3/drivers/hwmon/it87.c
2507 --- linux-2.6.14-omap2/drivers/hwmon/it87.c 2005-10-28 03:02:08.000000000 +0300
2508 +++ linux-h6300-omap2-2.6.14.3/drivers/hwmon/it87.c 2005-12-02 01:34:35.000000000 +0200
2509 @@ -522,8 +522,15 @@
2510 struct i2c_client *client = to_i2c_client(dev);
2511 struct it87_data *data = i2c_get_clientdata(client);
2512 int val = simple_strtol(buf, NULL, 10);
2513 + u8 reg = it87_read_value(client, IT87_REG_FAN_DIV);
2515 down(&data->update_lock);
2517 + case 0: data->fan_div[nr] = reg & 0x07; break;
2518 + case 1: data->fan_div[nr] = (reg >> 3) & 0x07; break;
2519 + case 2: data->fan_div[nr] = (reg & 0x40) ? 3 : 1; break;
2522 data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
2523 it87_write_value(client, IT87_REG_FAN_MIN(nr), data->fan_min[nr]);
2524 up(&data->update_lock);
2525 diff -Naur linux-2.6.14-omap2/drivers/hwmon/lm78.c linux-h6300-omap2-2.6.14.3/drivers/hwmon/lm78.c
2526 --- linux-2.6.14-omap2/drivers/hwmon/lm78.c 2005-10-28 03:02:08.000000000 +0300
2527 +++ linux-h6300-omap2-2.6.14.3/drivers/hwmon/lm78.c 2005-12-02 01:34:35.000000000 +0200
2529 static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf)
2531 struct lm78_data *data = lm78_update_device(dev);
2532 - return sprintf(buf, "%d\n", vid_from_reg(82, data->vid));
2533 + return sprintf(buf, "%d\n", vid_from_reg(data->vid, 82));
2535 static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
2537 diff -Naur linux-2.6.14-omap2/drivers/hwmon/w83627hf.c linux-h6300-omap2-2.6.14.3/drivers/hwmon/w83627hf.c
2538 --- linux-2.6.14-omap2/drivers/hwmon/w83627hf.c 2005-10-28 03:02:08.000000000 +0300
2539 +++ linux-h6300-omap2-2.6.14.3/drivers/hwmon/w83627hf.c 2005-12-02 01:34:35.000000000 +0200
2541 (w83627thf == data->type || w83637hf == data->type))
2543 /* use VRM9 calculation */
2544 - data->in_min[0] = (u8)(((val * 100) - 70000 + 244) / 488);
2546 + SENSORS_LIMIT(((val * 100) - 70000 + 244) / 488, 0,
2549 /* use VRM8 (standard) calculation */
2550 data->in_min[0] = IN_TO_REG(val);
2552 (w83627thf == data->type || w83637hf == data->type))
2554 /* use VRM9 calculation */
2555 - data->in_max[0] = (u8)(((val * 100) - 70000 + 244) / 488);
2557 + SENSORS_LIMIT(((val * 100) - 70000 + 244) / 488, 0,
2560 /* use VRM8 (standard) calculation */
2561 data->in_max[0] = IN_TO_REG(val);
2562 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
2563 --- linux-2.6.14-omap2/drivers/i2c/busses/i2c-omap.c 2005-12-02 01:53:32.000000000 +0200
2564 +++ linux-h6300-omap2-2.6.14.3/drivers/i2c/busses/i2c-omap.c 2005-10-20 20:53:33.000000000 +0300
2565 @@ -124,10 +124,10 @@
2566 /* I2C System Configuration Register (OMAP_I2C_SYSC): */
2567 #define OMAP_I2C_SYSC_SRST (1 << 1) /* Soft Reset */
2569 +#undef I2C_OMAP_DEBUG
2570 /* ------- debugging ---------------------------------------------------*/
2572 -#define I2C_OMAP_DEBUG
2573 -#ifdef I2c_OMAP_DEBUG
2574 +#ifdef I2C_OMAP_DEBUG
2575 static int i2c_debug;
2577 module_param(i2c_debug, int, 0);
2578 diff -Naur linux-2.6.14-omap2/drivers/i2c/chips/Kconfig linux-h6300-omap2-2.6.14.3/drivers/i2c/chips/Kconfig
2579 --- linux-2.6.14-omap2/drivers/i2c/chips/Kconfig 2005-12-02 01:53:32.000000000 +0200
2580 +++ linux-h6300-omap2-2.6.14.3/drivers/i2c/chips/Kconfig 2005-10-14 18:55:31.000000000 +0300
2582 This driver can also be built as a module. If so, the module
2583 will be called pca9539.
2586 + tristate "Philips PCA9535 16-bit I/O port"
2589 + If you say yes here you get support for the Philips PCA9535
2592 + This driver can also be built as a module. If so, the module
2593 + will be called pca9539.
2595 config SENSORS_PCF8591
2596 tristate "Philips PCF8591"
2597 depends on I2C && EXPERIMENTAL
2598 diff -Naur linux-2.6.14-omap2/drivers/i2c/chips/Makefile linux-h6300-omap2-2.6.14.3/drivers/i2c/chips/Makefile
2599 --- linux-2.6.14-omap2/drivers/i2c/chips/Makefile 2005-12-02 01:53:32.000000000 +0200
2600 +++ linux-h6300-omap2-2.6.14.3/drivers/i2c/chips/Makefile 2005-10-14 18:55:31.000000000 +0300
2602 obj-$(CONFIG_SENSORS_TLV320AIC23) += tlv320aic23.o
2603 obj-$(CONFIG_GPIOEXPANDER_OMAP) += gpio_expander_omap.o
2604 obj-$(CONFIG_MENELAUS) += menelaus.o
2605 +obj-$(CONFIG_PCA9535) += pca9535.o
2607 ifeq ($(CONFIG_I2C_DEBUG_CHIP),y)
2608 EXTRA_CFLAGS += -DDEBUG
2609 diff -Naur linux-2.6.14-omap2/drivers/i2c/chips/pca9535.c linux-h6300-omap2-2.6.14.3/drivers/i2c/chips/pca9535.c
2610 --- linux-2.6.14-omap2/drivers/i2c/chips/pca9535.c 1970-01-01 02:00:00.000000000 +0200
2611 +++ linux-h6300-omap2-2.6.14.3/drivers/i2c/chips/pca9535.c 2005-10-25 22:23:21.000000000 +0300
2614 + Driver for Philips PCA9535 16-bit low power I/O port with interrupt
2616 + This program is free software; you can redistribute it and/or modify
2617 + it under the terms of the GNU General Public License as published by
2618 + the Free Software Foundation; either version 2 of the License, or
2619 + (at your option) any later version.
2621 + This program is distributed in the hope that it will be useful,
2622 + but WITHOUT ANY WARRANTY; without even the implied warranty of
2623 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2624 + GNU General Public License for more details.
2626 + You should have received a copy of the GNU General Public License
2627 + along with this program; if not, write to the Free Software
2628 + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
2630 + Copyright (C) 2005 Husam Senussi
2631 + Framework based on Pawel Kolodziejski's pca9535 driver in
2632 + handheld.org's 2.6.13 kernel. Driver updated by Mika Laitio.
2635 +#include <linux/module.h>
2636 +#include <linux/init.h>
2637 +#include <linux/slab.h>
2638 +#include <linux/i2c.h>
2639 +#include <linux/hwmon-sysfs.h>
2640 +#include <linux/hwmon.h>
2641 +#include <linux/err.h>
2643 +#include <asm/arch/pca9535.h>
2644 +#include <linux/delay.h>
2646 +#include <linux/interrupt.h>
2647 +#include <asm/mach-types.h>
2648 +#include <asm/irq.h>
2649 +#include <asm/mach/arch.h>
2650 +#include <asm/hardware.h>
2652 +EXPORT_SYMBOL(pca9535_gpio_read);
2653 +EXPORT_SYMBOL(pca9535_gpio_write);
2654 +EXPORT_SYMBOL(pca9535_gpio_direction);
2656 +static int pca9535_attach_adapter(struct i2c_adapter *adapter);
2657 +static int pca9535_detach_client(struct i2c_client *client);
2658 +static int pca9535_attach(struct i2c_adapter *adapter, int address, int zero_or_minus_one);
2659 +static u32 pca9535_read_reg(struct i2c_client *client, u8 regaddr);
2660 +static void pca9535_write_reg(struct i2c_client *client, u8 regaddr, u16 param);
2664 + PCA9535_INPUT_0 = 0,
2665 + PCA9535_INPUT_1 = 1,
2666 + PCA9535_OUTPUT_0 = 2,
2667 + PCA9535_OUTPUT_1 = 3,
2668 + PCA9535_INVERT_0 = 4,
2669 + PCA9535_INVERT_1 = 5,
2670 + PCA9535_DIRECTION_0 = 6,
2671 + PCA9535_DIRECTION_1 = 7,
2674 +struct pca9535_data {
2675 + struct semaphore lock;
2676 + struct i2c_client client;
2679 +static struct i2c_driver pca9535_driver = {
2680 + .owner = THIS_MODULE,
2681 + .name = "pca9535",
2682 + .flags = I2C_DF_NOTIFY,
2683 + .attach_adapter = pca9535_attach_adapter,
2684 + .detach_client = pca9535_detach_client,
2687 +static struct i2c_client *pca9535_i2c_client = NULL;
2688 +static struct pca9535_data pca9535_inited;
2690 +static unsigned short normal_i2c[] = { 0x20, I2C_CLIENT_END };
2692 +#define DRIVER_VERSION "20 OCT 2005"
2693 +#define DRIVER_NAME "PCA9535"
2696 + * sysfs callback function.
2698 +static ssize_t pca9535_show(struct device *dev, struct device_attribute *attr,
2701 + struct sensor_device_attribute *psa = to_sensor_dev_attr(attr);
2702 + struct i2c_client *client = to_i2c_client(dev);
2703 + return sprintf(buf, "%02X\n", (pca9535_read_reg(client, psa->index) >> 8));
2707 + * sysfs callback function.
2709 +static ssize_t pca9535_store(struct device *dev, struct device_attribute *attr,
2710 + const char *buf, size_t count)
2712 + struct sensor_device_attribute *psa = to_sensor_dev_attr(attr);
2713 + struct i2c_client *client = to_i2c_client(dev);
2714 + unsigned long val = simple_strtoul(buf, NULL, 0);
2715 + unsigned long old = pca9535_read_reg(client, psa->index);
2720 + val = (old & 0xff) | (val << 8);
2721 + pca9535_write_reg(client, psa->index, val);
2725 +#define PCA9535_ENTRY_RO(name, cmd_idx) \
2726 + static SENSOR_DEVICE_ATTR(name, S_IRUGO, pca9535_show, NULL, cmd_idx)
2728 +#define PCA9535_ENTRY_RW(name, cmd_idx) \
2729 + static SENSOR_DEVICE_ATTR(name, S_IRUGO | S_IWUSR, pca9535_show, \
2730 + pca9535_store, cmd_idx)
2732 +PCA9535_ENTRY_RO(input0, PCA9535_INPUT_0);
2733 +PCA9535_ENTRY_RO(input1, PCA9535_INPUT_1);
2734 +PCA9535_ENTRY_RW(output0, PCA9535_OUTPUT_0);
2735 +PCA9535_ENTRY_RW(output1, PCA9535_OUTPUT_1);
2736 +PCA9535_ENTRY_RW(invert0, PCA9535_INVERT_0);
2737 +PCA9535_ENTRY_RW(invert1, PCA9535_INVERT_1);
2738 +PCA9535_ENTRY_RW(direction0, PCA9535_DIRECTION_0);
2739 +PCA9535_ENTRY_RW(direction1, PCA9535_DIRECTION_1);
2741 +static struct attribute *pca9535_attributes[] = {
2742 + &sensor_dev_attr_input0.dev_attr.attr,
2743 + &sensor_dev_attr_input1.dev_attr.attr,
2744 + &sensor_dev_attr_output0.dev_attr.attr,
2745 + &sensor_dev_attr_output1.dev_attr.attr,
2746 + &sensor_dev_attr_invert0.dev_attr.attr,
2747 + &sensor_dev_attr_invert1.dev_attr.attr,
2748 + &sensor_dev_attr_direction0.dev_attr.attr,
2749 + &sensor_dev_attr_direction1.dev_attr.attr,
2753 +static struct attribute_group pca9535_defattr_group = {
2754 + .attrs = pca9535_attributes,
2756 +//End of sysfs management code.
2760 +u32 pca9535_read_input(void)
2762 + return pca9535_read_reg(pca9535_i2c_client, 0);
2764 +EXPORT_SYMBOL(pca9535_read_input);
2766 +void pca9535_write_output(u16 param)
2768 + pca9535_write_reg(pca9535_i2c_client, 2, param);
2770 +EXPORT_SYMBOL(pca9535_write_output);
2772 +void pca9535_set_dir(u16 param)
2774 + pca9535_write_reg(pca9535_i2c_client, 6, param);
2776 +EXPORT_SYMBOL(pca9535_set_dir);
2778 +static int pca9535_attach_adapter(struct i2c_adapter *adapter)
2780 + return i2c_probe(adapter, &addr_data, pca9535_attach);
2783 +static int pca9535_attach(struct i2c_adapter *adapter, int address, int zero_or_minus_one)
2785 + struct i2c_client *new_client;
2788 + printk("pca9535_attach() started\n");
2789 + new_client = &(pca9535_inited.client);
2790 + i2c_set_clientdata(new_client, 0);
2791 + new_client->addr = address;
2792 + new_client->adapter = adapter;
2793 + new_client->driver = &pca9535_driver;
2794 + new_client->flags = I2C_CLIENT_ALLOW_USE;
2795 + strcpy(new_client->name, DRIVER_NAME);
2797 + if ((err = i2c_attach_client(new_client)))
2800 + pca9535_i2c_client = new_client;
2802 + init_MUTEX(&pca9535_inited.lock);
2803 + i2c_set_clientdata(pca9535_i2c_client, &pca9535_inited);
2805 + sysfs_create_group(&pca9535_i2c_client->dev.kobj, &pca9535_defattr_group);
2807 + printk("pca9535_attach() ok\n");
2811 + printk("pca9535_attach() failed, error code = %d\n", err);
2815 +static int pca9535_detach_client(struct i2c_client *client)
2819 + if ((err = i2c_detach_client(client))) {
2820 + dev_err(&client->dev, "Client deregistration failed, client not detached.\n");
2823 + pca9535_i2c_client = NULL;
2828 +static int __init pca9535_init(void)
2830 + return i2c_add_driver(&pca9535_driver);
2833 +static void __exit pca9535_exit(void)
2835 + i2c_del_driver(&pca9535_driver);
2839 + * Reads the value of GPIO available via I2C.
2841 +int pca9535_gpio_read(int gpio){
2842 + unsigned char reg = 0;
2843 + unsigned long val = 0;
2845 + printk("9535_gpio_read() called\n");
2846 + if(!pca9535_i2c_client)
2849 + if(gpio < GPIO0 || gpio > GPIO17)
2852 + if(gpio >= GPIO0 && gpio <= GPIO7){
2853 + reg = PCA9535_INPUT_0;
2855 + }else if(gpio >= GPIO8 && gpio <= GPIO17){
2856 + reg = PCA9535_INPUT_1;
2860 + down(&pca9535_inited.lock);
2862 + // Read the existing values first
2863 + val = pca9535_read_reg(pca9535_i2c_client, reg) >> 8;
2864 + val = (val >> gpio) & 0x01;
2866 + up(&pca9535_inited.lock);
2872 + * Set the value of I2C GPIO.
2874 +int pca9535_gpio_write(int gpio, unsigned char value){
2875 + unsigned char in_reg = 0;
2876 + unsigned char out_reg = 0;
2877 + unsigned long val = 0;
2878 + unsigned long old = 0;
2881 + if(!pca9535_i2c_client)
2884 + if(gpio < GPIO0 || gpio > GPIO17)
2887 + if(gpio >= GPIO0 && gpio <= GPIO7){
2888 + in_reg = PCA9535_INPUT_0;
2889 + out_reg = PCA9535_OUTPUT_0;
2891 + }else if(gpio >= GPIO8 && gpio <= GPIO17){
2892 + in_reg = PCA9535_INPUT_1;
2893 + out_reg = PCA9535_OUTPUT_1;
2897 + down(&pca9535_inited.lock);
2899 + // Read the existing values first
2900 + val = pca9535_read_reg(pca9535_i2c_client, in_reg);
2905 + old |= (1 << gpio);
2908 + old &= ~(1 << gpio);
2915 + val = (val & 0xff) | (old << 8);
2917 + // write the values back to the register
2918 + pca9535_write_reg(pca9535_i2c_client, out_reg, val);
2921 + up(&pca9535_inited.lock);
2926 + * Set the direction of I2C GPIO.
2928 +int pca9535_gpio_direction(int gpio, unsigned char direction){
2929 + unsigned char reg = 0;
2930 + unsigned long val = 0;
2931 + unsigned long old = 0;
2934 + if(!pca9535_i2c_client)
2937 + if(gpio < GPIO0 || gpio > GPIO17)
2940 + if(gpio >= GPIO0 && gpio <= GPIO7){
2941 + reg = PCA9535_DIRECTION_0;
2943 + }else if(gpio >= GPIO8 && gpio <= GPIO17){
2944 + reg = PCA9535_DIRECTION_1;
2948 + down(&pca9535_inited.lock);
2950 + // Read the existing values first
2951 + old = pca9535_read_reg(pca9535_i2c_client, reg);
2954 + switch(direction){
2956 + val |= (1 << gpio);
2959 + val &= ~(1 << gpio);
2966 + val = (old & 0xff) | (val << 8);
2968 + // write the values back to the register
2969 + pca9535_write_reg(pca9535_i2c_client, reg, val);
2972 + up(&pca9535_inited.lock);
2976 +static u32 pca9535_read_reg(struct i2c_client *client, u8 regaddr)
2982 + buffer[0] = regaddr;
2986 + r = i2c_master_send(client, buffer, 1);
2988 + printk(KERN_ERR "pca9535: read failed, status %d\n", r);
2989 + return 0xffffffff;
2992 + r = i2c_master_recv(client, buffer, 3);
2994 + printk(KERN_ERR "pca9535: read failed, status %d\n", r);
2995 + return 0xffffffff;
2999 + data |= buffer[2] << 8;
3000 + //printk(KERN_ERR "%s: reading %x in %x\n", __FUNCTION__, data, regaddr);
3005 +static void pca9535_write_reg(struct i2c_client *client, u8 regaddr, u16 data)
3010 + //printk(KERN_ERR "%s: writing %x in %x\n", __FUNCTION__, data, regaddr);
3011 + buffer[0] = regaddr;
3012 + buffer[1] = data >> 8;
3013 + buffer[2] = data & 0xff;
3015 + r = i2c_master_send(client, buffer, 3);
3017 + printk(KERN_ERR "pca9535: write failed, status %d\n", r);
3021 +MODULE_AUTHOR("Husam Senussi <husamsenussi@gmail.com>");
3022 +MODULE_DESCRIPTION("PCA9535 driver");
3023 +MODULE_LICENSE("GPL");
3025 +module_init(pca9535_init);
3026 +module_exit(pca9535_exit);
3027 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
3028 --- linux-2.6.14-omap2/drivers/input/keyboard/omap-keypad.c 2005-12-02 01:53:33.000000000 +0200
3029 +++ linux-h6300-omap2-2.6.14.3/drivers/input/keyboard/omap-keypad.c 2005-11-04 03:06:04.000000000 +0200
3032 * Copyright (C) 2003 Nokia Corporation
3033 * Written by Timo Teräs <ext-timo.teras@nokia.com>
3034 + * iPAQ h6300 key and joypad support added by Mika Laitio. (2005)
3036 * Added support for H2 & H3 Keypad
3037 * Copyright (C) 2004 Texas Instruments
3040 * This program is free software; you can redistribute it and/or modify
3041 * it under the terms of the GNU General Public License as published by
3042 * the Free Software Foundation; either version 2 of the License, or
3044 #include <asm/arch/mux.h>
3046 #undef NEW_BOARD_LEARNING_MODE
3047 +//#define NEW_BOARD_LEARNING_MODE 1
3049 static void omap_kp_tasklet(unsigned long);
3050 static void omap_kp_timer(unsigned long);
3052 static unsigned char keypad_state[8];
3053 static unsigned int keypad_irq = INT_KEYBOARD;
3055 +static int prevJoypadKeycodePressEmulated;
3057 static struct timer_list kp_timer;
3058 DECLARE_TASKLET_DISABLED(kp_tasklet, omap_kp_tasklet, 0);
3060 @@ -165,6 +169,47 @@
3064 +#define _h6300_KEY_CALENDAR 67 // xmodmap 75 aka F9
3065 +#define _H6300_KEY_TELEPHONE 68 // xmodmap 76 aka F10
3066 +#define _H6300_KEY_HOMEPAGE 87 // xmodmap 87 aka Num_Lock
3067 +#define _H6300_KEY_MAIL 88 // xmodmap 88 aka Scroll_Lock
3070 + * Following 5 keypad events are not really sent to userspace.
3071 + * Instead if the good combination of them is sent, then that is send.
3072 + * (up, right, down, left, enter)
3074 +#define _H6300_JOYPAD_UP_RIGHT 1 // 00001
3075 +#define _H6300_JOYPAD_DOWN_RIGHT 2 // 00010
3076 +#define _h6300_JOYPAD_DOWN_LEFT 4 // 00100
3077 +#define _h6300_JOYPAD_UP_LEFT 8 // 01000
3078 +#define _H6300_JOYPAD_KEY_OK 16 // 10000
3080 +static int h6300_keymap[] = {
3081 + KEY(2, 0, _h6300_KEY_CALENDAR), // address button in the bottom left
3082 + KEY(2, 3, _H6300_KEY_TELEPHONE), // start call button in the bottom
3083 + KEY(3, 1, _H6300_KEY_HOMEPAGE), // stop call button in the bottom
3084 + KEY(3, 4, _H6300_KEY_MAIL), // messaging button in the bottom right
3086 + KEY(0, 0, KEY_VOLUMEUP), // volume up button in the right side
3087 + KEY(0, 1, KEY_VOLUMEDOWN), // volume down button in the right side
3088 + KEY(3, 2, KEY_RECORD), // record button in the left side
3090 + KEY(1, 0, _h6300_JOYPAD_UP_LEFT),
3091 + KEY(1, 1, _h6300_JOYPAD_DOWN_LEFT),
3092 + KEY(1, 2, _H6300_JOYPAD_KEY_OK),
3093 + KEY(1, 3, _H6300_JOYPAD_DOWN_RIGHT),
3094 + KEY(1, 4, _H6300_JOYPAD_UP_RIGHT),
3096 + KEY(5, 0, KEY_RIGHT),
3097 + KEY(5, 1, KEY_DOWN),
3098 + KEY(5, 2, KEY_LEFT),
3099 + KEY(5, 3, KEY_UP),
3100 + KEY(5, 4, KEY_ENTER),
3107 static irqreturn_t omap_kp_interrupt(int irq, void *dev_id,
3109 for (col = 0; col < 8; col++) {
3110 omap_writew(~(1 << col) & 0xff, OMAP_MPUIO_BASE + OMAP_MPUIO_KBC);
3112 - if (machine_is_omap_osk() || machine_is_omap_h2() || machine_is_omap_h3()) {
3113 + if (machine_is_omap_osk() || machine_is_omap_h2() || machine_is_omap_h3() || machine_is_h6300()) {
3114 + // makes keyboard act a little bit slower
3118 @@ -214,26 +260,34 @@
3122 +int is_key_down(unsigned char new_state[],
3126 + return (new_state[col] & (1 << row)) ? 1 : 0;
3129 static void omap_kp_tasklet(unsigned long data)
3131 unsigned char new_state[8], changed, key_down = 0;
3134 + int report_key, report_col, report_row, joypad_checked; // joypad specific variables
3136 /* check for any changes */
3137 omap_kp_scan_keypad(new_state);
3139 /* check for changes and print those */
3140 + joypad_checked = 0;
3141 for (col = 0; col < 8; col++) {
3142 changed = new_state[col] ^ keypad_state[col];
3143 key_down |= new_state[col];
3148 for (row = 0; row < 8; row++) {
3150 if (!(changed & (1 << row)))
3153 #ifdef NEW_BOARD_LEARNING_MODE
3154 printk(KERN_INFO "omap-keypad: key %d-%d %s\n", col, row, (new_state[col] & (1 << row)) ? "pressed" : "released");
3156 @@ -245,9 +299,173 @@
3161 - input_report_key(&omap_kp_dev, key,
3162 - new_state[col] & (1 << row));
3163 + if (machine_is_h6300() &&
3164 + ((col == 1) || (col == 5)))
3170 + if ((joypad_checked == 0) &&
3171 + ((key == _H6300_JOYPAD_KEY_OK) ||
3172 + (key == _h6300_JOYPAD_UP_LEFT) ||
3173 + (key == _H6300_JOYPAD_UP_RIGHT) ||
3174 + (key == _H6300_JOYPAD_DOWN_RIGHT) ||
3175 + (key == _h6300_JOYPAD_DOWN_LEFT)))
3177 + if (is_key_down(new_state, col, row))
3180 + * only enter pressed
3181 + * 1 0 0 _H6300_JOYPAD_KEY_OK 0 0
3182 + * --> 100100 == 36
3184 + if (new_state[1] == 36)
3186 + joypad_checked = 1;
3187 + prevJoypadKeycodePressEmulated = KEY_ENTER;
3188 + new_state[5] = 48; //110000
3189 + report_key = prevJoypadKeycodePressEmulated;
3192 + input_report_key(&omap_kp_dev,
3194 + new_state[report_col] & (1 << report_row));
3197 + * enter, up_left and up_right sensors pressed.
3198 + * 1 _H6300_JOYPAD_UP_RIGHT 0 _H6300_JOYPAD_KEY_OK 0 _h6300_JOYPAD_UP_LEFT
3199 + * --> 110101 == 53
3201 + * 1 KEY_UP_RIGHT 0 0 0 _h6300_JOYPAD_UP_LEFT
3202 + * --> 110001 == 42
3205 + else if ((new_state[1] == 53) ||
3206 + (new_state[1] == 49))
3208 + joypad_checked = 1;
3209 + prevJoypadKeycodePressEmulated = KEY_UP;
3210 + new_state[5] = 40; //101000
3211 + report_key = prevJoypadKeycodePressEmulated;
3214 + input_report_key(&omap_kp_dev,
3216 + new_state[report_col] & (1 << report_row));
3219 + * enter, down_left and down_right sensors pressed
3220 + * --> 101110 == 46
3222 + * down_left and down_right
3224 + * --> move to down
3226 + else if ((new_state[1] == 46) ||
3227 + (new_state[1] == 42))
3229 + joypad_checked = 1;
3230 + prevJoypadKeycodePressEmulated = KEY_DOWN;
3231 + new_state[5] = 34; //100010
3232 + report_key = prevJoypadKeycodePressEmulated;
3235 + input_report_key(&omap_kp_dev,
3237 + new_state[report_col] & (1 << report_row));
3240 + * enter, up_right and down_right sensors pressed
3241 + * --> 111100 == 60
3243 + * down_right and up_right
3244 + * --> 111000 == 56
3245 + * --> move to right
3247 + else if ((new_state[1] == 60) ||
3248 + (new_state[1] == 56))
3250 + joypad_checked = 1;
3251 + prevJoypadKeycodePressEmulated = KEY_RIGHT;
3252 + new_state[5] = 33; //100001
3253 + report_key = prevJoypadKeycodePressEmulated;
3256 + input_report_key(&omap_kp_dev,
3258 + new_state[report_col] & (1 << report_row));
3261 + * enter, up_left and down_left sensors pressed
3262 + * --> 100111 == 39
3263 + * or up_left and down_left
3264 + * --> 100011 == 35
3265 + * --> move to left
3267 + else if ((new_state[1] == 39) ||
3268 + (new_state[1] == 35))
3270 + joypad_checked = 1;
3271 + prevJoypadKeycodePressEmulated = KEY_LEFT;
3272 + new_state[5] = 36; //100100
3273 + report_key = prevJoypadKeycodePressEmulated;
3276 + input_report_key(&omap_kp_dev,
3278 + new_state[report_col] & (1 << report_row));
3282 + //printk("missed new_state = %d\n", new_state[1]);
3287 + if (prevJoypadKeycodePressEmulated != 0)
3289 + // report key up event
3290 + joypad_checked = 1;
3291 + new_state[5] = 32; //100000
3292 + report_key = prevJoypadKeycodePressEmulated;
3294 + switch(prevJoypadKeycodePressEmulated)
3312 + printk(KERN_WARNING "Unknown iPAQ h6300 column 1 key = %d released. This should newer happen!\n",
3316 + input_report_key(&omap_kp_dev,
3318 + new_state[report_col] & (1 << report_row));
3319 + prevJoypadKeycodePressEmulated = 0;
3326 + input_report_key(&omap_kp_dev,
3328 + new_state[col] & (1 << row));
3333 @@ -285,7 +503,12 @@
3334 } else if (machine_is_omap_perseus2()) {
3336 keypad_irq = INT_730_MPUIO_KEYPAD;
3337 + } else if (machine_is_h6300()) {
3338 + keymap = h6300_keymap;
3339 + // set keyboard to send repeated key events if key is hold down
3340 + set_bit(EV_REP, omap_kp_dev.evbit);
3342 + printk("omap_keypad.c, keyMap = test_keymap\n");
3343 keymap = test_keymap;
3347 omap_kp_dev.name = "omap-keypad";
3348 input_register_device(&omap_kp_dev);
3350 - if (machine_is_omap_h2() || machine_is_omap_h3()) {
3351 + if (machine_is_omap_h2() || machine_is_omap_h3() || machine_is_h6300()) {
3352 omap_cfg_reg(F18_1610_KBC0);
3353 omap_cfg_reg(D20_1610_KBC1);
3354 omap_cfg_reg(D19_1610_KBC2);
3357 omap_writew(0xff, OMAP_MPUIO_BASE + OMAP_MPUIO_GPIO_DEBOUNCING);
3359 + prevJoypadKeycodePressEmulated = 0;
3361 /* scan current status and enable interrupt */
3362 omap_kp_scan_keypad(keypad_state);
3363 diff -Naur linux-2.6.14-omap2/drivers/input/touchscreen/omap/Makefile linux-h6300-omap2-2.6.14.3/drivers/input/touchscreen/omap/Makefile
3364 --- linux-2.6.14-omap2/drivers/input/touchscreen/omap/Makefile 2005-12-02 01:53:33.000000000 +0200
3365 +++ linux-h6300-omap2-2.6.14.3/drivers/input/touchscreen/omap/Makefile 2005-10-22 03:52:45.000000000 +0300
3367 objs-$(CONFIG_ARCH_OMAP16XX)$(CONFIG_MACH_OMAP_H3) += ts_hx.o
3368 objs-$(CONFIG_ARCH_OMAP15XX)$(CONFIG_MACH_OMAP_INNOVATOR) += ts_inn1510.o
3369 objs-$(CONFIG_ARCH_OMAP16XX)$(CONFIG_MACH_OMAP_OSK) += ts_osk.o
3370 +objs-$(CONFIG_ARCH_OMAP15XX)$(CONFIG_MACH_OMAP_H6300) += ts_hx.o
3372 omapts-objs := omap_ts.o $(objs-yy)
3373 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
3374 --- linux-2.6.14-omap2/drivers/input/touchscreen/omap/omap_ts.c 2005-12-02 01:53:33.000000000 +0200
3375 +++ linux-h6300-omap2-2.6.14.3/drivers/input/touchscreen/omap/omap_ts.c 2005-10-22 03:52:45.000000000 +0300
3377 #define OMAP_TS_NAME "omap_ts"
3379 static struct ts_device *__initdata ts_devs[] = {
3380 -#if defined(CONFIG_MACH_OMAP_H2) || defined(CONFIG_MACH_OMAP_H3)
3381 +#if defined(CONFIG_MACH_OMAP_H2) || defined(CONFIG_MACH_OMAP_H3) || defined(CONFIG_MACH_OMAP_H6300)
3384 #ifdef CONFIG_MACH_OMAP_OSK
3385 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
3386 --- linux-2.6.14-omap2/drivers/input/touchscreen/omap/ts_hx.c 2005-12-02 01:53:33.000000000 +0200
3387 +++ linux-h6300-omap2-2.6.14.3/drivers/input/touchscreen/omap/ts_hx.c 2005-09-28 02:45:59.000000000 +0300
3389 #include <asm/arch/mux.h>
3390 #include <asm/arch/hardware.h>
3391 #include <asm/hardware/tsc2101.h>
3392 +#include <linux/delay.h>
3394 #include "../drivers/ssi/omap-tsc2101.h"
3395 #include "omap_ts.h"
3397 } else if (machine_is_omap_h3()) {
3399 omap_cfg_reg(W19_1610_GPIO48);
3400 + } else if (machine_is_h6300 ()) {
3402 + omap_cfg_reg(M14_1510_GPIO2);
3406 ts->irq = OMAP_GPIO_IRQ(gpio);
3407 - if (omap_request_gpio(gpio) != 0) {
3408 - printk(KERN_ERR "hX_ts_init.c: Could not reserve GPIO!\n");
3411 + if (!machine_is_h6300 ()){
3412 + if (omap_request_gpio(gpio) != 0) {
3413 + printk(KERN_ERR "hX_ts_init.c: Could not reserve GPIO!\n");
3418 omap_set_gpio_direction(gpio, 1);
3419 set_irq_type(ts->irq, IRQT_FALLING);
3421 omap_free_gpio(H2_GPIO_NUM);
3422 else if (machine_is_omap_h3())
3423 omap_free_gpio(H3_GPIO_NUM);
3424 + else if (machine_is_h6300())
3425 + omap_free_gpio(2);
3428 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
3429 --- linux-2.6.14-omap2/drivers/isdn/hardware/eicon/os_4bri.c 2005-10-28 03:02:08.000000000 +0300
3430 +++ linux-h6300-omap2-2.6.14.3/drivers/isdn/hardware/eicon/os_4bri.c 2005-12-02 01:34:35.000000000 +0200
3432 #include "diva_pci.h"
3434 #include "dsrv4bri.h"
3435 +#include "helpers.h"
3437 static void *diva_xdiLoadFileFile = NULL;
3438 static dword diva_xdiLoadFileLength = 0;
3443 -void *xdiLoadFile(char *FileName, unsigned long *FileLength,
3444 +void *xdiLoadFile(char *FileName, dword *FileLength,
3447 void *ret = diva_xdiLoadFileFile;
3448 diff -Naur linux-2.6.14-omap2/drivers/mmc/mmc.c linux-h6300-omap2-2.6.14.3/drivers/mmc/mmc.c
3449 --- linux-2.6.14-omap2/drivers/mmc/mmc.c 2005-12-02 01:53:33.000000000 +0200
3450 +++ linux-h6300-omap2-2.6.14.3/drivers/mmc/mmc.c 2005-11-05 00:46:08.000000000 +0200
3453 case 2: /* MMC v2.0 - v2.2 */
3454 case 3: /* MMC v3.1 - v3.3 */
3455 + case 4: /* MMC v4 */
3456 card->cid.manfid = UNSTUFF_BITS(resp, 120, 8);
3457 card->cid.oemid = UNSTUFF_BITS(resp, 104, 16);
3458 card->cid.prod_name[0] = UNSTUFF_BITS(resp, 96, 8);
3459 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
3460 --- linux-2.6.14-omap2/drivers/net/wan/hdlc_cisco.c 2005-10-28 03:02:08.000000000 +0300
3461 +++ linux-h6300-omap2-2.6.14.3/drivers/net/wan/hdlc_cisco.c 2005-12-02 01:34:35.000000000 +0200
3463 "uptime %ud%uh%um%us)\n",
3464 dev->name, days, hrs,
3467 netif_carrier_on(dev);
3469 hdlc->state.cisco.up = 1;
3473 hdlc->state.cisco.settings.timeout * HZ)) {
3474 hdlc->state.cisco.up = 0;
3475 printk(KERN_INFO "%s: Link down\n", dev->name);
3477 netif_carrier_off(dev);
3481 cisco_keepalive_send(dev, CISCO_KEEPALIVE_REQ,
3482 @@ -261,8 +265,10 @@
3484 hdlc_device *hdlc = dev_to_hdlc(dev);
3485 del_timer_sync(&hdlc->state.cisco.timer);
3487 if (netif_carrier_ok(dev))
3488 netif_carrier_off(dev);
3490 hdlc->state.cisco.up = 0;
3491 hdlc->state.cisco.request_sent = 0;
3493 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
3494 --- linux-2.6.14-omap2/drivers/net/wan/hdlc_fr.c 2005-10-28 03:02:08.000000000 +0300
3495 +++ linux-h6300-omap2-2.6.14.3/drivers/net/wan/hdlc_fr.c 2005-12-02 01:34:35.000000000 +0200
3496 @@ -545,8 +545,10 @@
3498 hdlc->state.fr.reliable = reliable;
3501 if (!netif_carrier_ok(dev))
3502 netif_carrier_on(dev);
3505 hdlc->state.fr.n391cnt = 0; /* Request full status */
3506 hdlc->state.fr.dce_changed = 1;
3507 @@ -560,8 +562,10 @@
3512 if (netif_carrier_ok(dev))
3513 netif_carrier_off(dev);
3516 while (pvc) { /* Deactivate all PVCs */
3517 pvc_carrier(0, pvc);
3518 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
3519 --- linux-2.6.14-omap2/drivers/net/wan/hdlc_generic.c 2005-10-28 03:02:08.000000000 +0300
3520 +++ linux-h6300-omap2-2.6.14.3/drivers/net/wan/hdlc_generic.c 2005-12-02 01:34:35.000000000 +0200
3522 hdlc_device *hdlc = dev_to_hdlc(dev);
3523 if (hdlc->proto.start)
3524 return hdlc->proto.start(dev);
3527 if (netif_carrier_ok(dev))
3528 printk(KERN_ERR "hdlc_set_carrier_on(): already on\n");
3530 netif_carrier_on(dev);
3536 if (hdlc->proto.stop)
3537 return hdlc->proto.stop(dev);
3541 if (!netif_carrier_ok(dev))
3542 printk(KERN_ERR "hdlc_set_carrier_off(): already off\n");
3544 netif_carrier_off(dev);
3549 @@ -294,8 +298,10 @@
3554 if (netif_carrier_ok(dev))
3555 netif_carrier_off(dev); /* no carrier until DCD goes up */
3560 diff -Naur linux-2.6.14-omap2/drivers/net/wireless/airo.c linux-h6300-omap2-2.6.14.3/drivers/net/wireless/airo.c
3561 --- linux-2.6.14-omap2/drivers/net/wireless/airo.c 2005-10-28 03:02:08.000000000 +0300
3562 +++ linux-h6300-omap2-2.6.14.3/drivers/net/wireless/airo.c 2005-11-23 01:44:02.000000000 +0200
3564 #include <linux/pci.h>
3565 #include <asm/uaccess.h>
3570 static struct pci_device_id card_ids[] = {
3571 { 0x14b9, 1, PCI_ANY_ID, PCI_ANY_ID, },
3572 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
3573 --- linux-2.6.14-omap2/drivers/net/wireless/airo_cs.c 2005-10-28 03:02:08.000000000 +0300
3574 +++ linux-h6300-omap2-2.6.14.3/drivers/net/wireless/airo_cs.c 2005-11-23 01:44:02.000000000 +0200
3577 #include <asm/system.h>
3582 All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If
3583 you do not define PCMCIA_DEBUG at all, all the debug code will be
3588 -struct net_device *init_airo_card( int, int, int, struct device * );
3589 -void stop_airo_card( struct net_device *, int );
3590 -int reset_airo_card( struct net_device * );
3592 static void airo_config(dev_link_t *link);
3593 static void airo_release(dev_link_t *link);
3594 static int airo_event(event_t event, int priority,
3595 diff -Naur linux-2.6.14-omap2/drivers/net/wireless/airo.h linux-h6300-omap2-2.6.14.3/drivers/net/wireless/airo.h
3596 --- linux-2.6.14-omap2/drivers/net/wireless/airo.h 1970-01-01 02:00:00.000000000 +0200
3597 +++ linux-h6300-omap2-2.6.14.3/drivers/net/wireless/airo.h 2005-11-23 01:44:02.000000000 +0200
3602 +struct net_device *init_airo_card(unsigned short irq, int port, int is_pcmcia,
3603 + struct device *dmdev);
3604 +int reset_airo_card(struct net_device *dev);
3605 +void stop_airo_card(struct net_device *dev, int freeres);
3607 +#endif /* _AIRO_H_ */
3608 diff -Naur linux-2.6.14-omap2/drivers/net/wireless/Kconfig linux-h6300-omap2-2.6.14.3/drivers/net/wireless/Kconfig
3609 --- linux-2.6.14-omap2/drivers/net/wireless/Kconfig 2005-10-28 03:02:08.000000000 +0300
3610 +++ linux-h6300-omap2-2.6.14.3/drivers/net/wireless/Kconfig 2005-10-22 03:52:45.000000000 +0300
3612 depends on NET_RADIO && (ISA || PCI || PPC_PMAC || PCMCIA)
3615 +source "drivers/net/wireless/tiacx/Kconfig"
3619 diff -Naur linux-2.6.14-omap2/drivers/net/wireless/Makefile linux-h6300-omap2-2.6.14.3/drivers/net/wireless/Makefile
3620 --- linux-2.6.14-omap2/drivers/net/wireless/Makefile 2005-10-28 03:02:08.000000000 +0300
3621 +++ linux-h6300-omap2-2.6.14.3/drivers/net/wireless/Makefile 2005-10-14 18:55:31.000000000 +0300
3623 # 16-bit wireless PCMCIA client drivers
3624 obj-$(CONFIG_PCMCIA_RAYCS) += ray_cs.o
3625 obj-$(CONFIG_PCMCIA_WL3501) += wl3501_cs.o
3626 +obj-$(CONFIG_ACX) += tiacx/
3627 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
3628 --- linux-2.6.14-omap2/drivers/net/wireless/prism54/islpci_eth.c 2005-10-28 03:02:08.000000000 +0300
3629 +++ linux-h6300-omap2-2.6.14.3/drivers/net/wireless/prism54/islpci_eth.c 2005-11-23 01:44:02.000000000 +0200
3631 /* lock the driver code */
3632 spin_lock_irqsave(&priv->slock, flags);
3634 - /* determine the amount of fragments needed to store the frame */
3636 - frame_size = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;
3640 /* check whether the destination queue has enough fragments for the frame */
3641 curr_frag = le32_to_cpu(cb->driver_curr_frag[ISL38XX_CB_TX_DATA_LQ]);
3642 if (unlikely(curr_frag - priv->free_data_tx >= ISL38XX_CB_TX_QSIZE)) {
3644 /* store the skb address for future freeing */
3645 priv->data_low_tx[index] = skb;
3646 /* set the proper fragment start address and size information */
3647 + frame_size = skb->len;
3648 fragment->size = cpu_to_le16(frame_size);
3649 fragment->flags = cpu_to_le16(0); /* set to 1 if more fragments */
3650 fragment->address = cpu_to_le32(pci_map_address);
3651 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
3652 --- linux-2.6.14-omap2/drivers/net/wireless/tiacx/acx_config.h 1970-01-01 02:00:00.000000000 +0200
3653 +++ linux-h6300-omap2-2.6.14.3/drivers/net/wireless/tiacx/acx_config.h 2005-09-28 23:54:23.000000000 +0300
3655 +/* temporary hack until proper Kconfig integration */
3656 +#define CONFIG_ACX_PCI 1
3657 +#define CONFIG_ACX_USB 1
3659 +#define WLAN_RELEASE "v0.3.10"
3661 +/* set to 0 if you don't want any debugging code to be compiled in */
3662 +/* set to 1 if you want some debugging */
3663 +/* set to 2 if you want extensive debug log */
3664 +#define ACX_DEBUG 2
3666 +/* assume 32bit I/O width
3667 + * (16bit is also compatible with Compact Flash) */
3668 +#define ACX_IO_WIDTH 16
3670 +/* Set this to 1 if you want monitor mode to use
3671 + * phy header. Currently it is not useful anyway since we
3672 + * don't know what useful info (if any) is in phy header.
3673 + * If you want faster/smaller code, say 0 here */
3674 +#define WANT_PHY_HDR 0
3676 +/* whether to do Tx descriptor cleanup in softirq (i.e. not in IRQ
3677 + * handler) or not. Note that doing it later does slightly increase
3678 + * system load, so still do that stuff in the IRQ handler for now,
3679 + * even if that probably means worse latency */
3680 +#define TX_CLEANUP_IN_SOFTIRQ 0
3682 +/* set to 1 if you want to have 1 driver per card instead of 1 single driver
3683 + * managing all cards (of a particular bus type) in your system
3684 + * Useful e.g. if you need to reinitialize single cards from time to time
3685 + * LINUX 2.4.X ONLY!! (pci_for_each_dev()) Feel free to implement 2.6.x
3686 + * compatibility... */
3687 +#define SEPARATE_DRIVER_INSTANCES 0
3690 +/* very talkative */
3691 +#define PARANOID_LOCKING 1
3692 +/* normal (use when bug-free) */
3693 +/* #define DO_LOCKING 1 */
3694 +/* else locking is disabled! */
3696 +/* 0 - normal mode */
3697 +/* 1 - development/debug: probe for IEs on modprobe */
3698 +#define CMD_DISCOVERY 0
3699 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
3700 --- linux-2.6.14-omap2/drivers/net/wireless/tiacx/acx_func.h 1970-01-01 02:00:00.000000000 +0200
3701 +++ linux-h6300-omap2-2.6.14.3/drivers/net/wireless/tiacx/acx_func.h 2005-09-28 23:54:23.000000000 +0300
3703 +/***********************************************************************
3704 +** Copyright (C) 2003 ACX100 Open Source Project
3706 +** The contents of this file are subject to the Mozilla Public
3707 +** License Version 1.1 (the "License"); you may not use this file
3708 +** except in compliance with the License. You may obtain a copy of
3709 +** the License at http://www.mozilla.org/MPL/
3711 +** Software distributed under the License is distributed on an "AS
3712 +** IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
3713 +** implied. See the License for the specific language governing
3714 +** rights and limitations under the License.
3716 +** Alternatively, the contents of this file may be used under the
3717 +** terms of the GNU Public License version 2 (the "GPL"), in which
3718 +** case the provisions of the GPL are applicable instead of the
3719 +** above. If you wish to allow the use of your version of this file
3720 +** only under the terms of the GPL and not to allow others to use
3721 +** your version of this file under the MPL, indicate your decision
3722 +** by deleting the provisions above and replace them with the notice
3723 +** and other provisions required by the GPL. If you do not delete
3724 +** the provisions above, a recipient may use your version of this
3725 +** file under either the MPL or the GPL.
3726 +** ---------------------------------------------------------------------
3727 +** Inquiries regarding the ACX100 Open Source Project can be
3728 +** made directly to:
3730 +** acx100-users@lists.sf.net
3731 +** http://acx100.sf.net
3732 +** ---------------------------------------------------------------------
3736 +/***********************************************************************
3739 +** - Avoid SHOUTING needlessly. Avoid excessive verbosity.
3740 +** Gradually remove messages which are old debugging aids.
3742 +** - Use printk() for messages which are to be always logged.
3743 +** Supply either 'acx:' or '<devname>:' prefix so that user
3744 +** can figure out who's speaking among other kernel chatter.
3745 +** acx: is for general issues (e.g. "acx: no firmware image!")
3746 +** while <devname>: is related to a particular device
3747 +** (think about multi-card setup). Double check that message
3748 +** is not confusing to the average user.
3750 +** - use printk KERN_xxx level only if message is not a WARNING
3751 +** but is INFO, ERR etc.
3753 +** - Use printk_ratelimited() for messages which may flood
3754 +** (e.g. "rx DUP pkt!").
3756 +** - Use acxlog() for messages which may be omitted (and they
3757 +** _will_ be omitted in non-debug builds). Note that
3758 +** message levels may be disabled at compile-time selectively,
3759 +** thus select them wisely. Example: L_DEBUG is the lowest
3760 +** (most likely to be compiled out) -> use for less important stuff.
3762 +** - Do not print important stuff with acxlog(), or else people
3763 +** will never build non-debug driver.
3766 +** hex: capital letters, zero filled (e.g. 0x02AC)
3767 +** str: dont start from capitals, no trailing periods ("tx: queue is stopped")
3771 +void log_fn_enter(const char *funcname);
3772 +void log_fn_exit(const char *funcname);
3773 +void log_fn_exit_v(const char *funcname, int v);
3777 + if (unlikely(acx_debug & L_FUNC)) { \
3778 + log_fn_enter(__func__); \
3782 +#define FN_EXIT1(v) \
3784 + if (unlikely(acx_debug & L_FUNC)) { \
3785 + log_fn_exit_v(__func__, v); \
3790 + if (unlikely(acx_debug & L_FUNC)) { \
3791 + log_fn_exit(__func__); \
3798 +#define FN_EXIT1(v)
3801 +#endif /* ACX_DEBUG > 1 */
3806 +#define acxlog(chan, args...) \
3808 + if (acx_debug & (chan)) \
3811 +#define printk_ratelimited(args...) printk(args)
3813 +#else /* Non-debug build: */
3815 +#define acxlog(chan, args...)
3816 +/* Standard way of log flood prevention */
3817 +#define printk_ratelimited(args...) \
3819 + if (printk_ratelimit()) \
3823 +#endif /* ACX_DEBUG */
3825 +void acx_print_mac(const char *head, const u8 *mac, const char *tail);
3827 +/* Optimized out to nothing in non-debug build */
3829 +acxlog_mac(int level, const char *head, const u8 *mac, const char *tail)
3831 + if (acx_debug & level) {
3832 + acx_print_mac(head, mac, tail);
3837 +/***********************************************************************
3838 +** MAC address helpers
3841 +MAC_COPY(u8 *mac, const u8 *src)
3843 + *(u32*)mac = *(u32*)src;
3844 + ((u16*)mac)[2] = ((u16*)src)[2];
3845 + /* kernel's memcpy will do the same: memcpy(dst, src, ETH_ALEN); */
3849 +MAC_FILL(u8 *mac, u8 val)
3851 + memset(mac, val, ETH_ALEN);
3857 + ((u16*)mac)[2] = *(u32*)mac = -1;
3863 + ((u16*)mac)[2] = *(u32*)mac = 0;
3867 +mac_is_equal(const u8 *a, const u8 *b)
3869 + /* can't beat this */
3870 + return memcmp(a, b, ETH_ALEN) == 0;
3874 +mac_is_bcast(const u8 *mac)
3876 + /* AND together 4 first bytes with sign-entended 2 last bytes
3877 + ** Only bcast address gives 0xffffffff. +1 gives 0 */
3878 + return ( *(s32*)mac & ((s16*)mac)[2] ) + 1 == 0;
3882 +mac_is_zero(const u8 *mac)
3884 + return ( *(u32*)mac | ((u16*)mac)[2] ) == 0;
3888 +mac_is_directed(const u8 *mac)
3890 + return (mac[0] & 1)==0;
3894 +mac_is_mcast(const u8 *mac)
3896 + return (mac[0] & 1) && !mac_is_bcast(mac);
3899 +#define MACSTR "%02X:%02X:%02X:%02X:%02X:%02X"
3900 +#define MAC(bytevector) \
3901 + ((unsigned char *)bytevector)[0], \
3902 + ((unsigned char *)bytevector)[1], \
3903 + ((unsigned char *)bytevector)[2], \
3904 + ((unsigned char *)bytevector)[3], \
3905 + ((unsigned char *)bytevector)[4], \
3906 + ((unsigned char *)bytevector)[5]
3909 +/***********************************************************************
3912 +#define TO_STRING(x) #x
3913 +#define STRING(x) TO_STRING(x)
3915 +#define CLEAR_BIT(val, mask) ((val) &= ~(mask))
3916 +#define SET_BIT(val, mask) ((val) |= (mask))
3918 +/* undefined if v==0 */
3919 +static inline unsigned int
3922 + unsigned int n = 0;
3923 + while (!(v & 0xf)) { v>>=4; n+=4; }
3924 + while (!(v & 1)) { v>>=1; n++; }
3928 +/* undefined if v==0 */
3929 +static inline unsigned int
3932 + unsigned int n = 0;
3933 + while (v>0xf) { v>>=4; n+=4; }
3934 + while (v>1) { v>>=1; n++; }
3938 +/* undefined if v==0 */
3940 +has_only_one_bit(u16 v)
3942 + return ((v-1) ^ v) >= v;
3946 +/***********************************************************************
3948 +** We have priv->sem and priv->lock.
3950 +** We employ following naming convention in order to get locking right:
3952 +** acx_e_xxxx - external entry points called from process context.
3953 +** It is okay to sleep. priv->sem is to be taken on entry.
3954 +** acx_i_xxxx - external entry points possibly called from atomic context.
3955 +** Sleeping is not allowed (and thus down(sem) is not legal!)
3956 +** acx_s_xxxx - potentially sleeping functions. Do not ever call under lock!
3957 +** acx_l_xxxx - functions which expect lock to be already taken.
3958 +** rest - non-sleeping functions which do not require locking
3959 +** but may be run inder lock
3961 +** Theory of operation:
3963 +** All process-context entry points (_e_ functions) take sem
3964 +** immediately. IRQ handler and other 'atomic-context' entry points
3965 +** (_i_ functions) take lock immediately on entry, but dont take sem
3966 +** because that might sleep.
3968 +** Thus *all* code is either protected by sem or lock, or both.
3970 +** Code which must not run concurrently with IRQ takes lock.
3971 +** Such code is marked with _l_.
3973 +** This results in the following rules of thumb useful in code review:
3975 +** + If a function calls _s_ fn, it must be an _s_ itself.
3976 +** + You can call _l_ fn only (a) from another _l_ fn
3977 +** or (b) from _s_, _e_ or _i_ fn by taking lock, calling _l_,
3978 +** and dropping lock.
3979 +** + All IRQ code runs under lock.
3980 +** + Any _s_ fn is running under sem.
3981 +** + Code under sem can race only with IRQ code.
3982 +** + Code under sem+lock cannot race with anything.
3985 +/* These functions *must* be inline or they will break horribly on SPARC, due
3986 + * to its weird semantics for save/restore flags */
3988 +#if defined(PARANOID_LOCKING) /* Lock debugging */
3990 +void acx_lock_debug(wlandevice_t *priv, const char* where);
3991 +void acx_unlock_debug(wlandevice_t *priv, const char* where);
3992 +void acx_down_debug(wlandevice_t *priv, const char* where);
3993 +void acx_up_debug(wlandevice_t *priv, const char* where);
3994 +void acx_lock_unhold(void);
3995 +void acx_sem_unhold(void);
3998 +acx_lock_helper(wlandevice_t *priv, unsigned long *fp, const char* where)
4000 + acx_lock_debug(priv, where);
4001 + spin_lock_irqsave(&priv->lock, *fp);
4004 +acx_unlock_helper(wlandevice_t *priv, unsigned long *fp, const char* where)
4006 + acx_unlock_debug(priv, where);
4007 + spin_unlock_irqrestore(&priv->lock, *fp);
4010 +acx_down_helper(wlandevice_t *priv, const char* where)
4012 + acx_down_debug(priv, where);
4015 +acx_up_helper(wlandevice_t *priv, const char* where)
4017 + acx_up_debug(priv, where);
4019 +#define acx_lock(priv, flags) acx_lock_helper(priv, &(flags), __FILE__ ":" STRING(__LINE__))
4020 +#define acx_unlock(priv, flags) acx_unlock_helper(priv, &(flags), __FILE__ ":" STRING(__LINE__))
4021 +#define acx_sem_lock(priv) acx_down_helper(priv, __FILE__ ":" STRING(__LINE__))
4022 +#define acx_sem_unlock(priv) acx_up_helper(priv, __FILE__ ":" STRING(__LINE__))
4024 +#elif defined(DO_LOCKING)
4026 +#define acx_lock(priv, flags) spin_lock_irqsave(&priv->lock, flags)
4027 +#define acx_unlock(priv, flags) spin_unlock_irqrestore(&priv->lock, flags)
4028 +#define acx_sem_lock(priv) down(&priv->sem)
4029 +#define acx_sem_unlock(priv) up(&priv->sem)
4030 +#define acx_lock_unhold() ((void)0)
4031 +#define acx_sem_unhold() ((void)0)
4033 +#else /* no locking! :( */
4035 +#define acx_lock(priv, flags) ((void)0)
4036 +#define acx_unlock(priv, flags) ((void)0)
4037 +#define acx_sem_lock(priv) ((void)0)
4038 +#define acx_sem_unlock(priv) ((void)0)
4039 +#define acx_lock_unhold() ((void)0)
4040 +#define acx_sem_unhold() ((void)0)
4045 +/***********************************************************************
4048 +/* Can race with rx path (which is not protected by sem):
4049 +** rx -> process_[re]assocresp() -> set_status(ASSOCIATED) -> wake_queue()
4050 +** Can race with tx_complete IRQ:
4051 +** IRQ -> acx_l_clean_tx_desc -> acx_wake_queue
4052 +** Review carefully all callsites */
4054 +acx_stop_queue(netdevice_t *dev, const char *msg)
4056 + if(netif_queue_stopped(dev))
4059 + netif_stop_queue(dev);
4061 + acxlog(L_BUFT, "tx: stop queue %s\n", msg);
4065 +acx_queue_stopped(netdevice_t *dev)
4067 + return netif_queue_stopped(dev);
4071 +acx_start_queue(netdevice_t *dev, const char *msg)
4073 + netif_start_queue(dev);
4075 + acxlog(L_BUFT, "tx: start queue %s\n", msg);
4079 +acx_wake_queue(netdevice_t *dev, const char *msg)
4081 + netif_wake_queue(dev);
4083 + acxlog(L_BUFT, "tx: wake queue %s\n", msg);
4087 +acx_carrier_off(netdevice_t *dev, const char *msg)
4089 + netif_carrier_off(dev);
4091 + acxlog(L_BUFT, "tx: carrier off %s\n", msg);
4095 +acx_carrier_on(netdevice_t *dev, const char *msg)
4097 + netif_carrier_on(dev);
4099 + acxlog(L_BUFT, "tx: carrier on %s\n", msg);
4102 +/* This function does not need locking UNLESS you call it
4103 +** as acx_set_status(ACX_STATUS_4_ASSOCIATED), bacause this can
4104 +** wake queue. This can race with stop_queue elsewhere. */
4105 +void acx_set_status(wlandevice_t *priv, u16 status);
4108 +/***********************************************************************
4109 +** Communication with firmware
4111 +#define CMD_TIMEOUT_MS(n) (n)
4112 +#define ACX_CMD_TIMEOUT_DEFAULT CMD_TIMEOUT_MS(50)
4116 +/* We want to log cmd names */
4117 +int acxpci_s_issue_cmd_timeo_debug(wlandevice_t *priv, unsigned cmd, void *param, unsigned len, unsigned timeout, const char* cmdstr);
4118 +int acxusb_s_issue_cmd_timeo_debug(wlandevice_t *priv, unsigned cmd, void *param, unsigned len, unsigned timeout, const char* cmdstr);
4120 +acx_s_issue_cmd_timeo_debug(wlandevice_t *priv, unsigned cmd, void *param, unsigned len, unsigned timeout, const char* cmdstr)
4122 +#if defined(CONFIG_ACX_CFI)
4123 + return acxpci_s_issue_cmd_timeo_debug(priv, cmd, param, len, timeout, cmdstr);
4126 + return acxpci_s_issue_cmd_timeo_debug(priv, cmd, param, len, timeout, cmdstr);
4127 + return acxusb_s_issue_cmd_timeo_debug(priv, cmd, param, len, timeout, cmdstr);
4130 +#define acx_s_issue_cmd(priv,cmd,param,len) \
4131 + acx_s_issue_cmd_timeo_debug(priv,cmd,param,len,ACX_CMD_TIMEOUT_DEFAULT,#cmd)
4132 +#define acx_s_issue_cmd_timeo(priv,cmd,param,len,timeo) \
4133 + acx_s_issue_cmd_timeo_debug(priv,cmd,param,len,timeo,#cmd)
4134 +int acx_s_configure_debug(wlandevice_t *priv, void *pdr, int type, const char* str);
4135 +#define acx_s_configure(priv,pdr,type) \
4136 + acx_s_configure_debug(priv,pdr,type,#type)
4137 +int acx_s_interrogate_debug(wlandevice_t *priv, void *pdr, int type, const char* str);
4138 +#define acx_s_interrogate(priv,pdr,type) \
4139 + acx_s_interrogate_debug(priv,pdr,type,#type)
4143 +int acxpci_s_issue_cmd_timeo(wlandevice_t *priv, unsigned cmd, void *param, unsigned len, unsigned timeout);
4144 +int acxusb_s_issue_cmd_timeo(wlandevice_t *priv, unsigned cmd, void *param, unsigned len, unsigned timeout);
4146 +acx_s_issue_cmd_timeo(wlandevice_t *priv, unsigned cmd, void *param, unsigned len, unsigned timeout)
4149 + return acxpci_s_issue_cmd_timeo(priv, cmd, param, len, timeout);
4150 + return acxusb_s_issue_cmd_timeo(priv, cmd, param, len, timeout);
4153 +acx_s_issue_cmd(wlandevice_t *priv, unsigned cmd, void *param, unsigned len)
4156 + return acxpci_s_issue_cmd_timeo(priv, cmd, param, len, ACX_CMD_TIMEOUT_DEFAULT);
4157 + return acxusb_s_issue_cmd_timeo(priv, cmd, param, len, ACX_CMD_TIMEOUT_DEFAULT);
4159 +int acx_s_configure(wlandevice_t *priv, void *pdr, int type);
4160 +int acx_s_interrogate(wlandevice_t *priv, void *pdr, int type);
4164 +void acx_s_cmd_start_scan(wlandevice_t *priv);
4167 +/***********************************************************************
4171 +acx111pci_ioctl_info(
4172 + struct net_device *dev,
4173 + struct iw_request_info *info,
4174 + struct iw_param *vwrq,
4177 +acx100pci_ioctl_set_phy_amp_bias(
4178 + struct net_device *dev,
4179 + struct iw_request_info *info,
4180 + struct iw_param *vwrq,
4184 +/***********************************************************************
4187 +int acxpci_s_read_phy_reg(wlandevice_t *priv, u32 reg, u8 *charbuf);
4188 +int acxusb_s_read_phy_reg(wlandevice_t *priv, u32 reg, u8 *charbuf);
4190 +acx_s_read_phy_reg(wlandevice_t *priv, u32 reg, u8 *charbuf)
4192 +#if defined(CONFIG_ACX_CFI)
4193 + return acxpci_s_read_phy_reg(priv, reg, charbuf);
4196 + return acxpci_s_read_phy_reg(priv, reg, charbuf);
4197 + return acxusb_s_read_phy_reg(priv, reg, charbuf);
4201 +int acxpci_s_write_phy_reg(wlandevice_t *priv, u32 reg, u8 value);
4202 +int acxusb_s_write_phy_reg(wlandevice_t *priv, u32 reg, u8 value);
4204 +acx_s_write_phy_reg(wlandevice_t *priv, u32 reg, u8 value)
4206 +#if defined(CONFIG_ACX_CFI)
4207 + return acxpci_s_write_phy_reg(priv, reg, value);
4210 + return acxpci_s_write_phy_reg(priv, reg, value);
4211 + return acxusb_s_write_phy_reg(priv, reg, value);
4215 +void acx_s_msleep(int ms);
4216 +int acx_s_init_mac(netdevice_t *dev);
4217 +void acx_set_reg_domain(wlandevice_t *priv, unsigned char reg_dom_id);
4218 +void acx_set_timer(wlandevice_t *priv, int timeout_us);
4219 +void acx_update_capabilities(wlandevice_t *priv);
4220 +int acx_read_eeprom_offset(wlandevice_t *priv, u32 addr, u8 *charbuf);
4221 +void acx_s_start(wlandevice_t *priv);
4222 +#if USE_FW_LOADER_26
4223 +firmware_image_t *acx_s_read_fw(struct device *dev, const char *file, u32 *size);
4225 +firmware_image_t *acx_s_read_fw(const char *file, u32 *size);
4226 +#define acx_s_read_fw(dev, file, size) acx_s_read_fw(file, size)
4228 +void acx_s_initialize_rx_config(wlandevice_t *priv);
4229 +void acx_s_update_card_settings(wlandevice_t *priv, int get_all, int set_all);
4230 +void acx_init_task_scheduler(wlandevice_t *priv);
4231 +void acx_schedule_after_interrupt_task(wlandevice_t *priv, unsigned int set_flag);
4232 +int acx_s_upload_radio(wlandevice_t *priv);
4233 +void acx_read_configoption(wlandevice_t *priv);
4234 +int acx_proc_register_entries(const struct net_device *dev);
4235 +int acx_proc_unregister_entries(const struct net_device *dev);
4236 +void acx_l_update_ratevector(wlandevice_t *priv);
4238 +int acx_e_ioctl_old(netdevice_t *dev, struct ifreq *ifr, int cmd);
4240 +client_t *acx_l_sta_list_get(wlandevice_t *priv, const u8 *address);
4241 +void acx_l_sta_list_del(wlandevice_t *priv, client_t *clt);
4243 +int acx_l_transmit_disassoc(wlandevice_t *priv, client_t *clt);
4244 +void acx_i_timer(unsigned long a);
4245 +int acx_s_complete_scan(wlandevice_t *priv);
4247 +static inline wlan_hdr_t*
4248 +acx_get_wlan_hdr(wlandevice_t *priv, const rxbuffer_t *rxbuf)
4250 + if (!(priv->rx_config_1 & RX_CFG1_INCLUDE_PHY_HDR))
4251 + return (wlan_hdr_t*)&rxbuf->hdr_a3;
4253 + /* take into account phy header in front of packet */
4254 + if (IS_ACX111(priv))
4255 + return (wlan_hdr_t*)((u8*)&rxbuf->hdr_a3 + 8);
4257 + return (wlan_hdr_t*)((u8*)&rxbuf->hdr_a3 + 4);
4260 +struct sk_buff *acx_rxbuf_to_ether(struct wlandevice *priv, rxbuffer_t *rxbuf);
4262 +void acx_l_power_led(wlandevice_t *priv, int enable);
4264 +unsigned int acx_l_clean_tx_desc(wlandevice_t *priv);
4265 +void acx_l_clean_tx_desc_emergency(wlandevice_t *priv);
4267 +u8 acx_signal_determine_quality(u8 signal, u8 noise);
4269 +void acx_l_process_rxbuf(wlandevice_t *priv, rxbuffer_t *rxbuf);
4270 +void acx_l_process_rx_desc(wlandevice_t *priv);
4272 +tx_t* acxpci_l_alloc_tx(wlandevice_t *priv);
4273 +tx_t* acxusb_l_alloc_tx(wlandevice_t *priv);
4274 +static inline tx_t*
4275 +acx_l_alloc_tx(wlandevice_t *priv)
4277 +#if defined(CONFIG_ACX_CFI)
4278 + return acxpci_l_alloc_tx(priv);
4281 + return acxpci_l_alloc_tx(priv);
4282 + return acxusb_l_alloc_tx(priv);
4286 +void* acxpci_l_get_txbuf(wlandevice_t *priv, tx_t *tx_opaque);
4287 +void* acxusb_l_get_txbuf(wlandevice_t *priv, tx_t *tx_opaque);
4288 +static inline void*
4289 +acx_l_get_txbuf(wlandevice_t *priv, tx_t *tx_opaque)
4291 +#if defined(CONFIG_ACX_CFI)
4292 + return acxpci_l_get_txbuf(priv, tx_opaque);
4295 + return acxpci_l_get_txbuf(priv, tx_opaque);
4296 + return acxusb_l_get_txbuf(priv, tx_opaque);
4300 +void acxpci_l_tx_data(wlandevice_t *priv, tx_t *tx_opaque, int len);
4301 +void acxusb_l_tx_data(wlandevice_t *priv, tx_t *tx_opaque, int len);
4303 +acx_l_tx_data(wlandevice_t *priv, tx_t *tx_opaque, int len)
4305 +#if defined(CONFIG_ACX_CFI)
4306 + acxpci_l_tx_data(priv, tx_opaque, len);
4309 + acxpci_l_tx_data(priv, tx_opaque, len);
4311 + acxusb_l_tx_data(priv, tx_opaque, len);
4315 +void acx_dump_bytes(const void *, int);
4316 +void acx_log_bad_eid(wlan_hdr_t* hdr, int len, wlan_ie_t* ie_ptr);
4318 +u8 acx_rate111to100(u16);
4320 +void acx100usb_l_tx_data(wlandevice_t *priv, struct txdesc *desc);
4321 +int acx_s_set_defaults(wlandevice_t *priv);
4322 +void acx_init_mboxes(wlandevice_t *priv);
4324 +int acx_l_ether_to_txbuf(wlandevice_t *priv, void *txbuf, const struct sk_buff *skb);
4327 +static inline const char* acx_get_packet_type_string(u16 fc) { return ""; }
4329 +const char* acx_get_packet_type_string(u16 fc);
4331 +const char* acx_cmd_status_str(unsigned int state);
4333 +int acx_i_start_xmit(struct sk_buff *skb, netdevice_t *dev);
4334 +void acx_free_desc_queues(wlandevice_t *priv);
4336 +int acx_s_create_hostdesc_queues(wlandevice_t *priv);
4337 +void acx_create_desc_queues(wlandevice_t *priv, u32 tx_queue_start, u32 rx_queue_start);
4339 +int acx100_s_init_wep(wlandevice_t *priv);
4340 +int acx100_s_init_packet_templates(wlandevice_t *priv);
4341 +int acx111_s_init_packet_templates(wlandevice_t *priv);
4343 +void great_inquisitor(wlandevice_t *priv);
4345 +char* acxpci_s_proc_diag_output(char *p, wlandevice_t *priv);
4346 +int acx_proc_eeprom_output(char *p, wlandevice_t *priv);
4347 +void acx_set_interrupt_mask(wlandevice_t *priv);
4348 +int acx100_s_set_tx_level(wlandevice_t *priv, u8 level_dbm);
4350 +#if defined(CONFIG_ACX_CFI)
4351 +int __init acxcfi_e_init_module(void);
4353 +int __init acxpci_e_init_module(void);
4354 +int __init acxusb_e_init_module(void);
4357 +#if defined(CONFIG_ACX_CFI)
4358 +void __exit acxcfi_e_cleanup_module(void);
4360 +void __exit acxpci_e_cleanup_module(void);
4361 +void __exit acxusb_e_cleanup_module(void);
4363 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
4364 --- linux-2.6.14-omap2/drivers/net/wireless/tiacx/acx.h 1970-01-01 02:00:00.000000000 +0200
4365 +++ linux-h6300-omap2-2.6.14.3/drivers/net/wireless/tiacx/acx.h 2005-09-28 23:54:23.000000000 +0300
4367 +#include "acx_config.h"
4368 +#include "wlan_compat.h"
4369 +#include "wlan_hdr.h"
4370 +#include "wlan_mgmt.h"
4371 +#include "acx_struct.h"
4372 +#include "acx_func.h"
4373 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
4374 --- linux-2.6.14-omap2/drivers/net/wireless/tiacx/acx_struct.h 1970-01-01 02:00:00.000000000 +0200
4375 +++ linux-h6300-omap2-2.6.14.3/drivers/net/wireless/tiacx/acx_struct.h 2005-10-29 22:02:44.000000000 +0300
4377 +/***********************************************************************
4378 +** Copyright (C) 2003 ACX100 Open Source Project
4380 +** The contents of this file are subject to the Mozilla Public
4381 +** License Version 1.1 (the "License"); you may not use this file
4382 +** except in compliance with the License. You may obtain a copy of
4383 +** the License at http://www.mozilla.org/MPL/
4385 +** Software distributed under the License is distributed on an "AS
4386 +** IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
4387 +** implied. See the License for the specific language governing
4388 +** rights and limitations under the License.
4390 +** Alternatively, the contents of this file may be used under the
4391 +** terms of the GNU Public License version 2 (the "GPL"), in which
4392 +** case the provisions of the GPL are applicable instead of the
4393 +** above. If you wish to allow the use of your version of this file
4394 +** only under the terms of the GPL and not to allow others to use
4395 +** your version of this file under the MPL, indicate your decision
4396 +** by deleting the provisions above and replace them with the notice
4397 +** and other provisions required by the GPL. If you do not delete
4398 +** the provisions above, a recipient may use your version of this
4399 +** file under either the MPL or the GPL.
4400 +** ---------------------------------------------------------------------
4401 +** Inquiries regarding the ACX100 Open Source Project can be
4402 +** made directly to:
4404 +** acx100-users@lists.sf.net
4405 +** http://acx100.sf.net
4406 +** ---------------------------------------------------------------------
4409 +/***********************************************************************
4410 +** Forward declarations of types
4412 +typedef struct tx tx_t;
4413 +typedef struct wlandevice wlandevice_t;
4414 +typedef struct client client_t;
4415 +typedef struct rxdesc rxdesc_t;
4416 +typedef struct txdesc txdesc_t;
4417 +typedef struct rxhostdesc rxhostdesc_t;
4418 +typedef struct txhostdesc txhostdesc_t;
4421 +/***********************************************************************
4422 +** Debug / log functionality
4425 + L_LOCK = (ACX_DEBUG>1)*0x0001, /* locking debug log */
4426 + L_INIT = (ACX_DEBUG>0)*0x0002, /* special card initialization logging */
4427 + L_IRQ = (ACX_DEBUG>0)*0x0004, /* interrupt stuff */
4428 + L_ASSOC = (ACX_DEBUG>0)*0x0008, /* assocation (network join) and station log */
4429 + L_FUNC = (ACX_DEBUG>1)*0x0020, /* logging of function enter / leave */
4430 + L_XFER = (ACX_DEBUG>1)*0x0080, /* logging of transfers and mgmt */
4431 + L_DATA = (ACX_DEBUG>1)*0x0100, /* logging of transfer data */
4432 + L_DEBUG = (ACX_DEBUG>1)*0x0200, /* log of debug info */
4433 + L_IOCTL = (ACX_DEBUG>0)*0x0400, /* log ioctl calls */
4434 + L_CTL = (ACX_DEBUG>1)*0x0800, /* log of low-level ctl commands */
4435 + L_BUFR = (ACX_DEBUG>1)*0x1000, /* debug rx buffer mgmt (ring buffer etc.) */
4436 + L_XFER_BEACON = (ACX_DEBUG>1)*0x2000, /* also log beacon packets */
4437 + L_BUFT = (ACX_DEBUG>1)*0x4000, /* debug tx buffer mgmt (ring buffer etc.) */
4438 + L_USBRXTX = (ACX_DEBUG>0)*0x8000, /* debug USB rx/tx operations */
4439 + L_BUF = L_BUFR + L_BUFT,
4444 +extern unsigned int acx_debug;
4446 +enum { acx_debug = 0 };
4450 +/*============================================================================*
4451 + * Random helpers *
4452 + *============================================================================*/
4453 +#define ACX_PACKED __WLAN_ATTRIB_PACK__
4455 +#define VEC_SIZE(a) (sizeof(a)/sizeof(a[0]))
4457 +/* Use worker_queues for 2.5/2.6 Kernels and queue tasks for 2.4 Kernels
4458 + (used for the 'bottom half' of the interrupt routine) */
4460 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,41)
4461 +#include <linux/workqueue.h>
4462 +/* #define NEWER_KERNELS_ONLY 1 */
4463 +#define USE_WORKER_TASKS
4464 +#define WORK_STRUCT struct work_struct
4465 +#define SCHEDULE_WORK schedule_work
4466 +#define FLUSH_SCHEDULED_WORK flush_scheduled_work
4469 +#include <linux/tqueue.h>
4470 +#define USE_QUEUE_TASKS
4471 +#define WORK_STRUCT struct tq_struct
4472 +#define SCHEDULE_WORK schedule_task
4473 +#define INIT_WORK(work, func, ndev) \
4475 + (work)->routine = (func); \
4476 + (work)->data = (ndev); \
4478 +#define FLUSH_SCHEDULED_WORK flush_scheduled_tasks
4483 +/*============================================================================*
4485 + *============================================================================*/
4489 +/* The supported chip models */
4490 +#define CHIPTYPE_ACX100 1
4491 +#define CHIPTYPE_ACX111 2
4493 +#define IS_ACX100(priv) ((priv)->chip_type == CHIPTYPE_ACX100)
4494 +#define IS_ACX111(priv) ((priv)->chip_type == CHIPTYPE_ACX111)
4496 +/* Supported interfaces */
4497 +#define DEVTYPE_PCI 0
4498 +#define DEVTYPE_USB 1
4500 +#if defined(CONFIG_ACX_PCI)
4501 + #if !defined(CONFIG_ACX_USB)
4502 + #define IS_PCI(priv) 1
4504 + #define IS_PCI(priv) ((priv)->dev_type == DEVTYPE_PCI)
4507 + #define IS_PCI(priv) 0
4510 +#if defined(CONFIG_ACX_USB)
4511 + #if !defined(CONFIG_ACX_PCI)
4512 + #define IS_USB(priv) 1
4514 + #define IS_USB(priv) ((priv)->dev_type == DEVTYPE_USB)
4517 + #define IS_USB(priv) 0
4520 +/* Driver defaults */
4521 +#define DEFAULT_DTIM_INTERVAL 10
4522 +/* used to be 2048, but FreeBSD driver changed it to 4096 to work properly
4523 +** in noisy wlans */
4524 +#define DEFAULT_MSDU_LIFETIME 4096
4525 +#define DEFAULT_RTS_THRESHOLD 2312 /* max. size: disable RTS mechanism */
4526 +#define DEFAULT_BEACON_INTERVAL 100
4528 +#define ACX100_BAP_DATALEN_MAX 4096
4529 +#define ACX100_RID_GUESSING_MAXLEN 2048 /* I'm not really sure */
4530 +#define ACX100_RIDDATA_MAXLEN ACX100_RID_GUESSING_MAXLEN
4532 +/* Support Constants */
4533 +/* Radio type names, found in Win98 driver's TIACXLN.INF */
4534 +#define RADIO_MAXIM_0D 0x0d
4535 +#define RADIO_RFMD_11 0x11
4536 +#define RADIO_RALINK_15 0x15
4537 +/* used in ACX111 cards (WG311v2, WL-121, ...): */
4538 +#define RADIO_RADIA_16 0x16
4539 +/* most likely *sometimes* used in ACX111 cards: */
4540 +#define RADIO_UNKNOWN_17 0x17
4541 +/* FwRad19.bin was found in a Safecom driver; must be an ACX111 radio: */
4542 +#define RADIO_UNKNOWN_19 0x19
4544 +/* Controller Commands */
4545 +/* can be found in table cmdTable in firmware "Rev. 1.5.0" (FW150) */
4546 +#define ACX1xx_CMD_RESET 0x00
4547 +#define ACX1xx_CMD_INTERROGATE 0x01
4548 +#define ACX1xx_CMD_CONFIGURE 0x02
4549 +#define ACX1xx_CMD_ENABLE_RX 0x03
4550 +#define ACX1xx_CMD_ENABLE_TX 0x04
4551 +#define ACX1xx_CMD_DISABLE_RX 0x05
4552 +#define ACX1xx_CMD_DISABLE_TX 0x06
4553 +#define ACX1xx_CMD_FLUSH_QUEUE 0x07
4554 +#define ACX1xx_CMD_SCAN 0x08
4555 +#define ACX1xx_CMD_STOP_SCAN 0x09
4556 +#define ACX1xx_CMD_CONFIG_TIM 0x0a
4557 +#define ACX1xx_CMD_JOIN 0x0b
4558 +#define ACX1xx_CMD_WEP_MGMT 0x0c
4559 +#ifdef OLD_FIRMWARE_VERSIONS
4560 +#define ACX100_CMD_HALT 0x0e /* mapped to unknownCMD in FW150 */
4562 +#define ACX1xx_CMD_MEM_READ 0x0d
4563 +#define ACX1xx_CMD_MEM_WRITE 0x0e
4565 +#define ACX1xx_CMD_SLEEP 0x0f
4566 +#define ACX1xx_CMD_WAKE 0x10
4567 +#define ACX1xx_CMD_UNKNOWN_11 0x11 /* mapped to unknownCMD in FW150 */
4568 +#define ACX100_CMD_INIT_MEMORY 0x12
4569 +#define ACX1xx_CMD_CONFIG_BEACON 0x13
4570 +#define ACX1xx_CMD_CONFIG_PROBE_RESPONSE 0x14
4571 +#define ACX1xx_CMD_CONFIG_NULL_DATA 0x15
4572 +#define ACX1xx_CMD_CONFIG_PROBE_REQUEST 0x16
4573 +#define ACX1xx_CMD_TEST 0x17
4574 +#define ACX1xx_CMD_RADIOINIT 0x18
4575 +#define ACX111_CMD_RADIOCALIB 0x19
4577 +/* 'After Interrupt' Commands */
4578 +#define ACX_AFTER_IRQ_CMD_STOP_SCAN 0x01
4579 +#define ACX_AFTER_IRQ_CMD_ASSOCIATE 0x02
4580 +#define ACX_AFTER_IRQ_CMD_RADIO_RECALIB 0x04
4581 +#define ACX_AFTER_IRQ_UPDATE_CARD_CFG 0x08
4582 +#define ACX_AFTER_IRQ_TX_CLEANUP 0x10
4583 +#define ACX_AFTER_IRQ_COMPLETE_SCAN 0x20
4584 +#define ACX_AFTER_IRQ_RESTART_SCAN 0x40
4586 +/***********************************************************************
4587 +** Tx/Rx buffer sizes and watermarks
4589 +/* BTW, this will alloc and use DMAable buffers of
4590 +** WLAN_A4FR_MAXLEN_WEP_FCS * (RX_CNT + TX_CNT) bytes
4591 +** RX/TX_CNT=32 -> ~150k DMA buffers
4592 +** RX/TX_CNT=16 -> ~75k DMA buffers
4597 +/* we clean up txdescs when we have N free txdesc: */
4598 +#define TX_START_CLEAN (TX_CNT - (TX_CNT/4))
4599 +#define TX_EMERG_CLEAN 2
4600 +/* we stop queue if we have less than N free txbufs: */
4601 +#define TX_STOP_QUEUE 3
4602 +/* we start queue if we have more than N free txbufs: */
4603 +#define TX_START_QUEUE 6
4605 +/***********************************************************************
4606 +** Interrogate/Configure cmd constants
4608 +** NB: length includes JUST the data part of the IE
4609 +** (does not include size of the (type,len) pair)
4611 +** TODO: seems that acx100, acx100usb, acx111 have some differences,
4612 +** fix code with regard to this!
4615 +#define DEF_IE(name, val, len) enum { ACX##name=val, ACX##name##_LEN=len }
4617 +/* Information Elements: Network Parameters, Static Configuration Entities */
4618 +/* these are handled by real_cfgtable in firmware "Rev 1.5.0" (FW150) */
4619 +DEF_IE(1xx_IE_UNKNOWN_00 ,0x0000, -1); /* mapped to cfgInvalid in FW150 */
4620 +DEF_IE(100_IE_ACX_TIMER ,0x0001, 0x10);
4621 +DEF_IE(1xx_IE_POWER_MGMT ,0x0002, 0x06);
4622 +DEF_IE(1xx_IE_QUEUE_CONFIG ,0x0003, 0x1c);
4623 +DEF_IE(100_IE_BLOCK_SIZE ,0x0004, 0x02);
4624 +DEF_IE(1xx_IE_MEMORY_CONFIG_OPTIONS ,0x0005, 0x14);
4625 +DEF_IE(1xx_IE_RATE_FALLBACK ,0x0006, 0x01);
4626 +DEF_IE(100_IE_WEP_OPTIONS ,0x0007, 0x03);
4627 +DEF_IE(111_IE_RADIO_BAND ,0x0007, -1);
4628 +DEF_IE(1xx_IE_MEMORY_MAP ,0x0008, 0x28); /* huh? */
4629 +DEF_IE(100_IE_SSID ,0x0008, 0x20); /* huh? */
4630 +DEF_IE(1xx_IE_SCAN_STATUS ,0x0009, 0x04); /* mapped to cfgInvalid in FW150 */
4631 +DEF_IE(1xx_IE_ASSOC_ID ,0x000a, 0x02);
4632 +DEF_IE(1xx_IE_UNKNOWN_0B ,0x000b, -1); /* mapped to cfgInvalid in FW150 */
4633 +DEF_IE(100_IE_UNKNOWN_0C ,0x000c, -1); /* very small implementation in FW150! */
4634 +DEF_IE(111_IE_CONFIG_OPTIONS ,0x000c, 0x14c);
4635 +DEF_IE(1xx_IE_FWREV ,0x000d, 0x18);
4636 +DEF_IE(1xx_IE_FCS_ERROR_COUNT ,0x000e, 0x04);
4637 +DEF_IE(1xx_IE_MEDIUM_USAGE ,0x000f, 0x08);
4638 +DEF_IE(1xx_IE_RXCONFIG ,0x0010, 0x04);
4639 +DEF_IE(100_IE_UNKNOWN_11 ,0x0011, -1); /* NONBINARY: large implementation in FW150! link quality readings or so? */
4640 +DEF_IE(111_IE_QUEUE_THRESH ,0x0011, -1);
4641 +DEF_IE(100_IE_UNKNOWN_12 ,0x0012, -1); /* NONBINARY: VERY large implementation in FW150!! */
4642 +DEF_IE(111_IE_BSS_POWER_SAVE ,0x0012, -1);
4643 +DEF_IE(1xx_IE_FIRMWARE_STATISTICS ,0x0013, 0x9c);
4644 +DEF_IE(1xx_IE_FEATURE_CONFIG ,0x0015, 0x08);
4645 +DEF_IE(111_IE_KEY_CHOOSE ,0x0016, 0x04); /* for rekeying. really len=4?? */
4646 +DEF_IE(1xx_IE_DOT11_STATION_ID ,0x1001, 0x06);
4647 +DEF_IE(100_IE_DOT11_UNKNOWN_1002 ,0x1002, -1); /* mapped to cfgInvalid in FW150 */
4648 +DEF_IE(111_IE_DOT11_FRAG_THRESH ,0x1002, -1); /* mapped to cfgInvalid in FW150 */
4649 +DEF_IE(100_IE_DOT11_BEACON_PERIOD ,0x1003, 0x02); /* mapped to cfgInvalid in FW150 */
4650 +DEF_IE(1xx_IE_DOT11_DTIM_PERIOD ,0x1004, -1); /* mapped to cfgInvalid in FW150 */
4651 +DEF_IE(1xx_IE_DOT11_SHORT_RETRY_LIMIT ,0x1005, 0x01);
4652 +DEF_IE(1xx_IE_DOT11_LONG_RETRY_LIMIT ,0x1006, 0x01);
4653 +DEF_IE(100_IE_DOT11_WEP_DEFAULT_KEY_WRITE ,0x1007, 0x20); /* configure default keys */
4654 +DEF_IE(1xx_IE_DOT11_MAX_XMIT_MSDU_LIFETIME ,0x1008, 0x04);
4655 +DEF_IE(1xx_IE_DOT11_GROUP_ADDR ,0x1009, -1);
4656 +DEF_IE(1xx_IE_DOT11_CURRENT_REG_DOMAIN ,0x100a, 0x02);
4657 +//It's harmless to have larger struct. Use USB case always.
4659 +////DEF_IE(1xx_IE_DOT11_CURRENT_ANTENNA ,0x100b, 0x01);
4661 +DEF_IE(1xx_IE_DOT11_CURRENT_ANTENNA ,0x100b, 0x02);
4663 +DEF_IE(1xx_IE_DOT11_UNKNOWN_100C ,0x100c, -1); /* mapped to cfgInvalid in FW150 */
4664 +DEF_IE(1xx_IE_DOT11_TX_POWER_LEVEL ,0x100d, 0x01);
4666 +////DEF_IE(1xx_IE_DOT11_CURRENT_CCA_MODE ,0x100e, 0x01);
4668 +DEF_IE(1xx_IE_DOT11_CURRENT_CCA_MODE ,0x100e, 0x02);
4670 +//USB doesn't return anything - len==0?!
4671 +DEF_IE(100_IE_DOT11_ED_THRESHOLD ,0x100f, 0x04);
4672 +DEF_IE(1xx_IE_DOT11_WEP_DEFAULT_KEY_SET ,0x1010, 0x01); /* set default key ID */
4673 +DEF_IE(100_IE_DOT11_UNKNOWN_1011 ,0x1011, -1); /* mapped to cfgInvalid in FW150 */
4674 +DEF_IE(100_IE_DOT11_UNKNOWN_1012 ,0x1012, -1); /* mapped to cfgInvalid in FW150 */
4675 +DEF_IE(100_IE_DOT11_UNKNOWN_1013 ,0x1013, -1); /* mapped to cfgInvalid in FW150 */
4678 +/* Experimentally obtained on acx100, fw 1.9.8.b
4679 +** -1 means that fw returned 'invalid IE'
4680 +** 0200 FC00 nnnn... are test read contents: u16 type, u16 len, data
4681 +** (AA are poison bytes marking bytes not written by fw)
4683 +** Looks like acx100 fw does not update len field (thus len=256-4=FC here)
4684 +** A number of IEs seem to trash type,len fields
4685 +** IEs marked 'huge' return gobs of data (no poison bytes remain)
4687 +DEF_IE(100_IE_INVAL_00, 0x0000, -1);
4688 +DEF_IE(100_IE_INVAL_01, 0x0001, -1); /* IE_ACX_TIMER, len=16 on older fw */
4689 +DEF_IE(100_IE_POWER_MGMT, 0x0002, 4); /* 0200FC00 00040000 AAAAAAAA */
4690 +DEF_IE(100_IE_QUEUE_CONFIG, 0x0003, 28); /* 0300FC00 48060000 9CAD0000 0101AAAA DCB00000 E4B00000 9CAA0000 00AAAAAA */
4691 +DEF_IE(100_IE_BLOCK_SIZE, 0x0004, 2); /* 0400FC00 0001AAAA AAAAAAAA AAAAAAAA */
4693 +DEF_IE(100_IE_MEMORY_CONFIG_OPTIONS, 0x0005, 20);
4694 +DEF_IE(100_IE_RATE_FALLBACK, 0x0006, 1); /* 0600FC00 00AAAAAA AAAAAAAA AAAAAAAA */
4696 +DEF_IE(100_IE_WEP_OPTIONS, 0x0007, 3);
4697 +DEF_IE(100_IE_MEMORY_MAP, 0x0008, 40); /* huge: 0800FC00 30000000 6CA20000 70A20000... */
4698 +/* gives INVAL on read: */
4699 +DEF_IE(100_IE_SCAN_STATUS, 0x0009, -1);
4700 +DEF_IE(100_IE_ASSOC_ID, 0x000a, 2); /* huge: 0A00FC00 00000000 01040800 00000000... */
4701 +DEF_IE(100_IE_INVAL_0B, 0x000b, -1);
4702 +/* 'command rejected': */
4703 +DEF_IE(100_IE_CONFIG_OPTIONS, 0x000c, -3);
4704 +DEF_IE(100_IE_FWREV, 0x000d, 24); /* 0D00FC00 52657620 312E392E 382E6200 AAAAAAAA AAAAAAAA 05050201 AAAAAAAA */
4705 +DEF_IE(100_IE_FCS_ERROR_COUNT, 0x000e, 4);
4706 +DEF_IE(100_IE_MEDIUM_USAGE, 0x000f, 8); /* E41F0000 2D780300 FCC91300 AAAAAAAA */
4707 +DEF_IE(100_IE_RXCONFIG, 0x0010, 4); /* 1000FC00 00280000 AAAAAAAA AAAAAAAA */
4708 +DEF_IE(100_IE_QUEUE_THRESH, 0x0011, 12); /* 1100FC00 AAAAAAAA 00000000 00000000 */
4709 +DEF_IE(100_IE_BSS_POWER_SAVE, 0x0012, 1); /* 1200FC00 00AAAAAA AAAAAAAA AAAAAAAA */
4710 +/* read only, variable len */
4711 +DEF_IE(100_IE_FIRMWARE_STATISTICS, 0x0013, 256); /* 0000AC00 00000000 ... */
4712 +DEF_IE(100_IE_INT_CONFIG, 0x0014, 20); /* 00000000 00000000 00000000 00000000 5D74D105 00000000 AAAAAAAA AAAAAAAA */
4713 +DEF_IE(100_IE_FEATURE_CONFIG, 0x0015, 8); /* 1500FC00 16000000 AAAAAAAA AAAAAAAA */
4714 +/* returns 'invalid MAC': */
4715 +DEF_IE(100_IE_KEY_CHOOSE, 0x0016, -4);
4716 +DEF_IE(100_IE_INVAL_17, 0x0017, -1);
4717 +DEF_IE(100_IE_UNKNOWN_18, 0x0018, 0); /* null len?! 1800FC00 AAAAAAAA AAAAAAAA AAAAAAAA */
4718 +DEF_IE(100_IE_UNKNOWN_19, 0x0019, 256); /* huge: 1900FC00 9C1F00EA FEFFFFEA FEFFFFEA... */
4719 +DEF_IE(100_IE_INVAL_1A, 0x001A, -1);
4721 +DEF_IE(100_IE_DOT11_INVAL_1000, 0x1000, -1);
4722 +DEF_IE(100_IE_DOT11_STATION_ID, 0x1001, 6); /* huge: 0110FC00 58B10E2F 03000000 00000000... */
4723 +DEF_IE(100_IE_DOT11_INVAL_1002, 0x1002, -1);
4724 +DEF_IE(100_IE_DOT11_INVAL_1003, 0x1003, -1);
4725 +DEF_IE(100_IE_DOT11_INVAL_1004, 0x1004, -1);
4726 +DEF_IE(100_IE_DOT11_SHORT_RETRY_LIMIT, 0x1005, 1);
4727 +DEF_IE(100_IE_DOT11_LONG_RETRY_LIMIT, 0x1006, 1);
4729 +DEF_IE(100_IE_DOT11_WEP_DEFAULT_KEY_WRITE, 0x1007, 32);
4730 +DEF_IE(100_IE_DOT11_MAX_XMIT_MSDU_LIFETIME, 0x1008, 4); /* huge: 0810FC00 00020000 F4010000 00000000... */
4731 +/* undoc but returns something */
4732 +DEF_IE(100_IE_DOT11_GROUP_ADDR, 0x1009, 12); /* huge: 0910FC00 00000000 00000000 00000000... */
4733 +DEF_IE(100_IE_DOT11_CURRENT_REG_DOMAIN, 0x100a, 1); /* 0A10FC00 30AAAAAA AAAAAAAA AAAAAAAA */
4734 +DEF_IE(100_IE_DOT11_CURRENT_ANTENNA, 0x100b, 1); /* 0B10FC00 8FAAAAAA AAAAAAAA AAAAAAAA */
4735 +DEF_IE(100_IE_DOT11_INVAL_100C, 0x100c, -1);
4736 +DEF_IE(100_IE_DOT11_TX_POWER_LEVEL, 0x100d, 2); /* 00000000 0100AAAA AAAAAAAA AAAAAAAA */
4737 +DEF_IE(100_IE_DOT11_CURRENT_CCA_MODE, 0x100e, 1); /* 0E10FC00 0DAAAAAA AAAAAAAA AAAAAAAA */
4738 +DEF_IE(100_IE_DOT11_ED_THRESHOLD, 0x100f, 4); /* 0F10FC00 70000000 AAAAAAAA AAAAAAAA */
4739 +/* set default key ID */
4740 +DEF_IE(100_IE_DOT11_WEP_DEFAULT_KEY_SET, 0x1010, 1); /* 1010FC00 00AAAAAA AAAAAAAA AAAAAAAA */
4741 +DEF_IE(100_IE_DOT11_INVAL_1011, 0x1011, -1);
4742 +DEF_IE(100_IE_DOT11_INVAL_1012, 0x1012, -1);
4743 +DEF_IE(100_IE_DOT11_INVAL_1013, 0x1013, -1);
4744 +DEF_IE(100_IE_DOT11_UNKNOWN_1014, 0x1014, 256); /* huge */
4745 +DEF_IE(100_IE_DOT11_UNKNOWN_1015, 0x1015, 256); /* huge */
4746 +DEF_IE(100_IE_DOT11_UNKNOWN_1016, 0x1016, 256); /* huge */
4747 +DEF_IE(100_IE_DOT11_UNKNOWN_1017, 0x1017, 256); /* huge */
4748 +DEF_IE(100_IE_DOT11_UNKNOWN_1018, 0x1018, 256); /* huge */
4749 +DEF_IE(100_IE_DOT11_UNKNOWN_1019, 0x1019, 256); /* huge */
4753 +/* Experimentally obtained on PCI acx111 Xterasys XN-2522g, fw 1.2.1.34
4754 +** -1 means that fw returned 'invalid IE'
4755 +** 0400 0800 nnnn... are test read contents: u16 type, u16 len, data
4756 +** (AA are poison bytes marking bytes not written by fw)
4758 +** Looks like acx111 fw reports real len!
4760 +DEF_IE(111_IE_INVAL_00, 0x0000, -1);
4761 +DEF_IE(111_IE_INVAL_01, 0x0001, -1);
4762 +DEF_IE(111_IE_POWER_MGMT, 0x0002, 12);
4763 +/* write only, variable len: 12 + rxqueue_cnt*8 + txqueue_cnt*4: */
4764 +DEF_IE(111_IE_MEMORY_CONFIG, 0x0003, 24);
4765 +DEF_IE(111_IE_BLOCK_SIZE, 0x0004, 8); /* 04000800 AA00AAAA AAAAAAAA */
4766 +/* variable len: 8 + rxqueue_cnt*8 + txqueue_cnt*8: */
4767 +DEF_IE(111_IE_QUEUE_HEAD, 0x0005, 24);
4768 +DEF_IE(111_IE_RATE_FALLBACK, 0x0006, 1);
4769 +/* acx100 name:WEP_OPTIONS */
4770 +/* said to have len:1 (not true, actually returns 12 bytes): */
4771 +DEF_IE(111_IE_RADIO_BAND, 0x0007, 12); /* 07000C00 AAAA1F00 FF03AAAA AAAAAAAA */
4772 +DEF_IE(111_IE_MEMORY_MAP, 0x0008, 48);
4773 +/* said to have len:4, but gives INVAL on read: */
4774 +DEF_IE(111_IE_SCAN_STATUS, 0x0009, -1);
4775 +DEF_IE(111_IE_ASSOC_ID, 0x000a, 2);
4776 +/* write only, len is not known: */
4777 +DEF_IE(111_IE_UNKNOWN_0B, 0x000b, 0);
4778 +/* read only, variable len. I see 67 byte reads: */
4779 +DEF_IE(111_IE_CONFIG_OPTIONS, 0x000c, 67); /* 0C004300 01160500 ... */
4780 +DEF_IE(111_IE_FWREV, 0x000d, 24);
4781 +DEF_IE(111_IE_FCS_ERROR_COUNT, 0x000e, 4);
4782 +DEF_IE(111_IE_MEDIUM_USAGE, 0x000f, 8);
4783 +DEF_IE(111_IE_RXCONFIG, 0x0010, 4);
4784 +DEF_IE(111_IE_QUEUE_THRESH, 0x0011, 12);
4785 +DEF_IE(111_IE_BSS_POWER_SAVE, 0x0012, 1);
4786 +/* read only, variable len. I see 240 byte reads: */
4787 +DEF_IE(111_IE_FIRMWARE_STATISTICS, 0x0013, 240); /* 1300F000 00000000 ... */
4788 +/* said to have len=17. looks like fw pads it to 20: */
4789 +DEF_IE(111_IE_INT_CONFIG, 0x0014, 20); /* 14001400 00000000 00000000 00000000 00000000 00000000 */
4790 +DEF_IE(111_IE_FEATURE_CONFIG, 0x0015, 8);
4791 +/* said to be name:KEY_INDICATOR, len:4, but gives INVAL on read: */
4792 +DEF_IE(111_IE_KEY_CHOOSE, 0x0016, -1);
4793 +/* said to have len:4, but in fact returns 8: */
4794 +DEF_IE(111_IE_MAX_USB_XFR, 0x0017, 8); /* 17000800 00014000 00000000 */
4795 +DEF_IE(111_IE_INVAL_18, 0x0018, -1);
4796 +DEF_IE(111_IE_INVAL_19, 0x0019, -1);
4797 +/* undoc but returns something: */
4798 +/* huh, fw indicates len=20 but uses 4 more bytes in buffer??? */
4799 +DEF_IE(111_IE_UNKNOWN_1A, 0x001A, 20); /* 1A001400 AA00AAAA 0000020F FF030000 00020000 00000007 04000000 */
4801 +DEF_IE(111_IE_DOT11_INVAL_1000, 0x1000, -1);
4802 +DEF_IE(111_IE_DOT11_STATION_ID, 0x1001, 6);
4803 +DEF_IE(111_IE_DOT11_FRAG_THRESH, 0x1002, 2);
4804 +/* acx100 only? gives INVAL on read: */
4805 +DEF_IE(111_IE_DOT11_BEACON_PERIOD, 0x1003, -1);
4806 +/* said to be MAX_RECV_MSDU_LIFETIME: */
4807 +DEF_IE(111_IE_DOT11_DTIM_PERIOD, 0x1004, 4);
4808 +DEF_IE(111_IE_DOT11_SHORT_RETRY_LIMIT, 0x1005, 1);
4809 +DEF_IE(111_IE_DOT11_LONG_RETRY_LIMIT, 0x1006, 1);
4810 +/* acx100 only? gives INVAL on read: */
4811 +DEF_IE(111_IE_DOT11_WEP_DEFAULT_KEY_WRITE, 0x1007, -1);
4812 +DEF_IE(111_IE_DOT11_MAX_XMIT_MSDU_LIFETIME, 0x1008, 4);
4813 +/* undoc but returns something. maybe it's 2 multicast MACs to listen to? */
4814 +DEF_IE(111_IE_DOT11_GROUP_ADDR, 0x1009, 12); /* 09100C00 00000000 00000000 00000000 */
4815 +DEF_IE(111_IE_DOT11_CURRENT_REG_DOMAIN, 0x100a, 1);
4816 +DEF_IE(111_IE_DOT11_CURRENT_ANTENNA, 0x100b, 2);
4817 +DEF_IE(111_IE_DOT11_INVAL_100C, 0x100c, -1);
4818 +DEF_IE(111_IE_DOT11_TX_POWER_LEVEL, 0x100d, 1);
4819 +/* said to have len=1 but gives INVAL on read: */
4820 +DEF_IE(111_IE_DOT11_CURRENT_CCA_MODE, 0x100e, -1);
4821 +/* said to have len=4 but gives INVAL on read: */
4822 +DEF_IE(111_IE_DOT11_ED_THRESHOLD, 0x100f, -1);
4823 +/* set default key ID. write only: */
4824 +DEF_IE(111_IE_DOT11_WEP_DEFAULT_KEY_SET, 0x1010, 1);
4825 +/* undoc but returns something: */
4826 +DEF_IE(111_IE_DOT11_UNKNOWN_1011, 0x1011, 1); /* 11100100 20 */
4827 +DEF_IE(111_IE_DOT11_INVAL_1012, 0x1012, -1);
4828 +DEF_IE(111_IE_DOT11_INVAL_1013, 0x1013, -1);
4832 +/*============================================================================*
4833 + * Information Frames Structures *
4834 + *============================================================================*/
4836 +/* Used in beacon frames and the like */
4837 +#define DOT11RATEBYTE_1 (1*2)
4838 +#define DOT11RATEBYTE_2 (2*2)
4839 +#define DOT11RATEBYTE_5_5 (5*2+1)
4840 +#define DOT11RATEBYTE_11 (11*2)
4841 +#define DOT11RATEBYTE_22 (22*2)
4842 +#define DOT11RATEBYTE_6_G (6*2)
4843 +#define DOT11RATEBYTE_9_G (9*2)
4844 +#define DOT11RATEBYTE_12_G (12*2)
4845 +#define DOT11RATEBYTE_18_G (18*2)
4846 +#define DOT11RATEBYTE_24_G (24*2)
4847 +#define DOT11RATEBYTE_36_G (36*2)
4848 +#define DOT11RATEBYTE_48_G (48*2)
4849 +#define DOT11RATEBYTE_54_G (54*2)
4850 +#define DOT11RATEBYTE_BASIC 0x80 /* flags rates included in basic rate set */
4853 +/***********************************************************************
4856 +** This is the format of rx data returned by acx
4859 +/* I've hoped it's a 802.11 PHY header, but no...
4860 + * so far, I've seen on acx111:
4861 + * 0000 3a00 0000 0000 IBBS Beacons
4862 + * 0000 3c00 0000 0000 ESS Beacons
4863 + * 0000 2700 0000 0000 Probe requests
4866 +typedef struct phy_hdr {
4867 + u8 unknown[4] ACX_PACKED;
4868 + u8 acx111_unknown[4] ACX_PACKED;
4871 +/* seems to be a bit similar to hfa384x_rx_frame.
4872 + * These fields are still not quite obvious, though.
4873 + * Some seem to have different meanings... */
4875 +#define RXBUF_HDRSIZE 12
4876 +#define PHY_HDR(rxbuf) ((phy_hdr_t*)&rxbuf->hdr_a3)
4877 +#define RXBUF_BYTES_RCVD(rxbuf) (le16_to_cpu(rxbuf->mac_cnt_rcvd) & 0xfff)
4878 +#define RXBUF_BYTES_USED(rxbuf) \
4879 + ((le16_to_cpu(rxbuf->mac_cnt_rcvd) & 0xfff) + RXBUF_HDRSIZE)
4882 + 12 bits: length of frame from control field to last byte of FCS
4886 + 6 bits: number of memory block used to store frame in adapter memory
4887 + 1 bit: Traffic Indicator bit in TIM of received Beacon was set
4889 +mac_status: 1 byte (bitmap):
4892 + 5 BDCST Address 1 field is a broadcast
4893 + 4 VBM received beacon frame has more than one set bit (?!)
4894 + 3 TIM Set bit representing this station is set in TIM of received beacon
4895 + 2 GROUP Address 1 is a multicast
4896 + 1 ADDR1 Address 1 matches our MAC
4897 + 0 FCSGD FSC is good
4899 +phy_stat_baseband: 1 byte (bitmap):
4900 + 7 Preamble frame had a long preamble
4901 + 6 PLCP Error CRC16 error in PLCP header
4902 + 5 Unsup_Mod unsupported modulation
4903 + 4 Selected Antenna antenna 1 was used to receive this frame
4904 + 3 PBCC/CCK frame used: 1=PBCC, 0=CCK modulation
4905 + 2 OFDM frame used OFDM modulation
4906 + 1 TI Protection protection frame was detected
4909 +phy_plcp_signal: 1 byte:
4910 + Receive PLCP Signal field from the Baseband Processor
4913 + receive AGC gain level (can be used to measure receive signal strength)
4916 + estimated noise power of equalized receive signal
4917 + at input of FEC decoder (can be used to measure receive signal quality)
4920 + timestamp sampled from either the Access Manager TSF counter
4921 + or free-running microsecond counter when the MAC receives
4922 + first byte of PLCP header.
4925 +typedef struct rxbuffer {
4926 + u16 mac_cnt_rcvd ACX_PACKED; /* only 12 bits are len! (0xfff) */
4927 + u8 mac_cnt_mblks ACX_PACKED;
4928 + u8 mac_status ACX_PACKED;
4929 + u8 phy_stat_baseband ACX_PACKED; /* bit 0x80: used LNA (Low-Noise Amplifier) */
4930 + u8 phy_plcp_signal ACX_PACKED;
4931 + u8 phy_level ACX_PACKED; /* PHY stat */
4932 + u8 phy_snr ACX_PACKED; /* PHY stat */
4933 + u32 time ACX_PACKED; /* timestamp upon MAC rcv first byte */
4934 +/* 4-byte (acx100) or 8-byte (acx111) phy header will be here
4935 +** if RX_CFG1_INCLUDE_PHY_HDR is in effect:
4936 +** phy_hdr_t phy */
4937 + wlan_hdr_a3_t hdr_a3 ACX_PACKED;
4938 + /* maximally sized data part of wlan packet */
4939 + u8 data_a3[WLAN_A4FR_MAXLEN_WEP_FCS - WLAN_HDR_A3_LEN] ACX_PACKED;
4940 + /* can add hdr/data_a4 if needed */
4944 +/*--- Firmware statistics ----------------------------------------------------*/
4945 +typedef struct fw_stats {
4946 + u32 val0x0 ACX_PACKED; /* hdr; */
4947 + u32 tx_desc_of ACX_PACKED;
4948 + u32 rx_oom ACX_PACKED;
4949 + u32 rx_hdr_of ACX_PACKED;
4950 + u32 rx_hdr_use_next ACX_PACKED;
4951 + u32 rx_dropped_frame ACX_PACKED;
4952 + u32 rx_frame_ptr_err ACX_PACKED;
4953 + u32 rx_xfr_hint_trig ACX_PACKED;
4955 + u32 rx_dma_req ACX_PACKED;
4956 + u32 rx_dma_err ACX_PACKED;
4957 + u32 tx_dma_req ACX_PACKED;
4958 + u32 tx_dma_err ACX_PACKED;
4960 + u32 cmd_cplt ACX_PACKED;
4961 + u32 fiq ACX_PACKED;
4962 + u32 rx_hdrs ACX_PACKED;
4963 + u32 rx_cmplt ACX_PACKED;
4964 + u32 rx_mem_of ACX_PACKED;
4965 + u32 rx_rdys ACX_PACKED;
4966 + u32 irqs ACX_PACKED;
4967 + u32 acx_trans_procs ACX_PACKED;
4968 + u32 decrypt_done ACX_PACKED;
4969 + u32 dma_0_done ACX_PACKED;
4970 + u32 dma_1_done ACX_PACKED;
4971 + u32 tx_exch_complet ACX_PACKED;
4972 + u32 commands ACX_PACKED;
4973 + u32 acx_rx_procs ACX_PACKED;
4974 + u32 hw_pm_mode_changes ACX_PACKED;
4975 + u32 host_acks ACX_PACKED;
4976 + u32 pci_pm ACX_PACKED;
4977 + u32 acm_wakeups ACX_PACKED;
4979 + u32 wep_key_count ACX_PACKED;
4980 + u32 wep_default_key_count ACX_PACKED;
4981 + u32 dot11_def_key_mib ACX_PACKED;
4982 + u32 wep_key_not_found ACX_PACKED;
4983 + u32 wep_decrypt_fail ACX_PACKED;
4986 +/* Firmware version struct */
4988 +typedef struct fw_ver {
4989 + u16 cmd ACX_PACKED;
4990 + u16 size ACX_PACKED;
4991 + char fw_id[20] ACX_PACKED;
4992 + u32 hw_id ACX_PACKED;
4995 +#define FW_ID_SIZE 20
4998 +/*--- WEP stuff --------------------------------------------------------------*/
4999 +#define DOT11_MAX_DEFAULT_WEP_KEYS 4
5001 +/* non-firmware struct, no packing necessary */
5002 +typedef struct wep_key {
5003 + size_t size; /* most often used member first */
5006 + u16 strange_filler;
5007 +} wep_key_t; /* size = 264 bytes (33*8) */
5008 +/* FIXME: We don't have size 264! Or is there 2 bytes beyond the key
5009 + * (strange_filler)? */
5011 +/* non-firmware struct, no packing necessary */
5012 +typedef struct key_struct {
5013 + u8 addr[ETH_ALEN]; /* 0x00 */
5014 + u16 filler1; /* 0x06 */
5015 + u32 filler2; /* 0x08 */
5016 + u32 index; /* 0x0c */
5017 + u16 len; /* 0x10 */
5018 + u8 key[29]; /* 0x12; is this long enough??? */
5019 +} key_struct_t; /* size = 276. FIXME: where is the remaining space?? */
5022 +/*--- Client (peer) info -----------------------------------------------------*/
5023 +/* priv->sta_list[] is used for:
5024 +** accumulating and processing of scan results
5025 +** keeping client info in AP mode
5026 +** keeping AP info in STA mode (AP is the only one 'client')
5027 +** keeping peer info in ad-hoc mode
5028 +** non-firmware struct --> no packing necessary */
5030 + CLIENT_EMPTY_SLOT_0 = 0,
5031 + CLIENT_EXIST_1 = 1,
5032 + CLIENT_AUTHENTICATED_2 = 2,
5033 + CLIENT_ASSOCIATED_3 = 3,
5034 + CLIENT_JOIN_CANDIDATE = 4
5037 + struct client* next;
5038 + unsigned long mtime; /* last time we heard it, in jiffies */
5039 + size_t essid_len; /* length of ESSID (without '\0') */
5040 + u32 sir; /* Standard IR */
5041 + u32 snr; /* Signal to Noise Ratio */
5042 + u16 aid; /* association ID */
5043 + u16 seq; /* from client's auth req */
5044 + u16 auth_alg; /* from client's auth req */
5045 + u16 cap_info; /* from client's assoc req */
5046 + u16 rate_cap; /* what client supports (all rates) */
5047 + u16 rate_bas; /* what client supports (basic rates) */
5048 + u16 rate_cfg; /* what is allowed (by iwconfig etc) */
5049 + u16 rate_cur; /* currently used rate mask */
5050 + u8 rate_100; /* currently used rate byte (acx100 only) */
5051 + u8 used; /* misnamed, more like 'status' */
5052 + u8 address[ETH_ALEN];
5053 + u8 bssid[ETH_ALEN]; /* ad-hoc hosts can have bssid != mac */
5057 + u8 fallback_count;
5059 + char essid[IW_ESSID_MAX_SIZE + 1]; /* ESSID and trailing '\0' */
5060 +/* FIXME: this one is too damn big */
5061 + char challenge_text[WLAN_CHALLENGE_LEN];
5065 +/*============================================================================*
5066 + * Hardware structures *
5067 + *============================================================================*/
5069 +/* An opaque typesafe helper type
5071 + * Some hardware fields are actually pointers,
5072 + * but they have to remain u32, since using ptr instead
5073 + * (8 bytes on 64bit systems!) would disrupt the fixed descriptor
5074 + * format the acx firmware expects in the non-user area.
5075 + * Since we cannot cram an 8 byte ptr into 4 bytes, we need to
5076 + * enforce that pointed to data remains in low memory
5077 + * (address value needs to fit in 4 bytes) on 64bit systems.
5079 + * This is easy to get wrong, thus we are using a small struct
5080 + * and special macros to access it. Macros will check for
5081 + * attempts to overflow an acx_ptr with value > 0xffffffff.
5083 + * Attempts to use acx_ptr without macros result in compile-time errors */
5090 +#define CHECK32(n) BUG_ON(sizeof(n)>4 && (long)(n)>0xffffff00)
5092 +#define CHECK32(n) ((void)0)
5095 +/* acx_ptr <-> integer conversion */
5096 +#define cpu2acx(n) ({ CHECK32(n); ((acx_ptr){ .v = cpu_to_le32(n) }); })
5097 +#define acx2cpu(a) (le32_to_cpu(a.v))
5099 +/* acx_ptr <-> pointer conversion */
5100 +#define ptr2acx(p) ({ CHECK32(p); ((acx_ptr){ .v = cpu_to_le32((u32)(long)(p)) }); })
5101 +#define acx2ptr(a) ((void*)le32_to_cpu(a.v))
5103 +/* Values for rate field (acx100 only) */
5104 +#define RATE100_1 10
5105 +#define RATE100_2 20
5106 +#define RATE100_5 55
5107 +#define RATE100_11 110
5108 +#define RATE100_22 220
5109 +/* This bit denotes use of PBCC:
5110 +** (PBCC encoding is usable with 11 and 22 Mbps speeds only) */
5111 +#define RATE100_PBCC511 0x80
5113 +/* Bit values for rate111 field */
5114 +#define RATE111_1 0x0001 /* DBPSK */
5115 +#define RATE111_2 0x0002 /* DQPSK */
5116 +#define RATE111_5 0x0004 /* CCK or PBCC */
5117 +#define RATE111_6 0x0008 /* CCK-OFDM or OFDM */
5118 +#define RATE111_9 0x0010 /* CCK-OFDM or OFDM */
5119 +#define RATE111_11 0x0020 /* CCK or PBCC */
5120 +#define RATE111_12 0x0040 /* CCK-OFDM or OFDM */
5121 +#define RATE111_18 0x0080 /* CCK-OFDM or OFDM */
5122 +#define RATE111_22 0x0100 /* PBCC */
5123 +#define RATE111_24 0x0200 /* CCK-OFDM or OFDM */
5124 +#define RATE111_36 0x0400 /* CCK-OFDM or OFDM */
5125 +#define RATE111_48 0x0800 /* CCK-OFDM or OFDM */
5126 +#define RATE111_54 0x1000 /* CCK-OFDM or OFDM */
5127 +#define RATE111_RESERVED 0x2000
5128 +#define RATE111_PBCC511 0x4000 /* PBCC mod at 5.5 or 11Mbit (else CCK) */
5129 +#define RATE111_SHORTPRE 0x8000 /* short preamble */
5130 +/* Special 'try everything' value */
5131 +#define RATE111_ALL 0x1fff
5132 +/* These bits denote acx100 compatible settings */
5133 +#define RATE111_ACX100_COMPAT 0x0127
5134 +/* These bits denote 802.11b compatible settings */
5135 +#define RATE111_80211B_COMPAT 0x0027
5137 +/* Descriptor Ctl field bits
5138 + * init value is 0x8e, "idle" value is 0x82 (in idle tx descs)
5140 +#define DESC_CTL_SHORT_PREAMBLE 0x01 /* preamble type: 0 = long; 1 = short */
5141 +#define DESC_CTL_FIRSTFRAG 0x02 /* this is the 1st frag of the frame */
5142 +#define DESC_CTL_AUTODMA 0x04
5143 +#define DESC_CTL_RECLAIM 0x08 /* ready to reuse */
5144 +#define DESC_CTL_HOSTDONE 0x20 /* host has finished processing */
5145 +#define DESC_CTL_ACXDONE 0x40 /* acx has finished processing */
5146 +/* host owns the desc [has to be released last, AFTER modifying all other desc fields!] */
5147 +#define DESC_CTL_HOSTOWN 0x80
5149 +#define DESC_CTL_INIT (DESC_CTL_HOSTOWN | DESC_CTL_RECLAIM | \
5150 + DESC_CTL_AUTODMA | DESC_CTL_FIRSTFRAG)
5151 +#define DESC_CTL_DONE (DESC_CTL_ACXDONE | DESC_CTL_HOSTOWN)
5153 +#define DESC_CTL_HOSTOWN_STR "80"
5154 +#define DESC_CTL_DONE_STR "C0"
5155 +/* Descriptor Status field
5157 +#define DESC_STATUS_FULL (1 << 31)
5159 +/* NB: some bits may be interesting for Monitor mode tx (aka Raw tx): */
5160 +#define DESC_CTL2_SEQ 0x01 /* don't increase sequence field */
5161 +#define DESC_CTL2_FCS 0x02 /* don't add the FCS */
5162 +#define DESC_CTL2_MORE_FRAG 0x04
5163 +#define DESC_CTL2_RETRY 0x08 /* don't increase retry field */
5164 +#define DESC_CTL2_POWER 0x10 /* don't increase power mgmt. field */
5165 +#define DESC_CTL2_RTS 0x20 /* do RTS/CTS magic before sending */
5166 +#define DESC_CTL2_WEP 0x40 /* encrypt this frame */
5167 +#define DESC_CTL2_DUR 0x80 /* don't increase duration field */
5169 +/***************************************************************
5173 +** (outside of "#ifdef PCI" because USB (mis)uses HOST_INT_SCAN_COMPLETE) */
5174 +#define HOST_INT_RX_DATA 0x0001
5175 +#define HOST_INT_TX_COMPLETE 0x0002
5176 +#define HOST_INT_TX_XFER 0x0004
5177 +#define HOST_INT_RX_COMPLETE 0x0008
5178 +#define HOST_INT_DTIM 0x0010
5179 +#define HOST_INT_BEACON 0x0020
5180 +#define HOST_INT_TIMER 0x0040
5181 +#define HOST_INT_KEY_NOT_FOUND 0x0080
5182 +#define HOST_INT_IV_ICV_FAILURE 0x0100
5183 +#define HOST_INT_CMD_COMPLETE 0x0200
5184 +#define HOST_INT_INFO 0x0400
5185 +#define HOST_INT_OVERFLOW 0x0800
5186 +#define HOST_INT_PROCESS_ERROR 0x1000
5187 +#define HOST_INT_SCAN_COMPLETE 0x2000
5188 +#define HOST_INT_FCS_THRESHOLD 0x4000
5189 +#define HOST_INT_UNKNOWN 0x8000
5191 +/* Outside of "#ifdef PCI" because USB needs to know sizeof()
5192 +** of txdesc and rxdesc: */
5194 + acx_ptr pNextDesc ACX_PACKED; /* pointer to next txdesc */
5195 + acx_ptr HostMemPtr ACX_PACKED; /* 0x04 */
5196 + acx_ptr AcxMemPtr ACX_PACKED; /* 0x08 */
5197 + u32 tx_time ACX_PACKED; /* 0x0c */
5198 + u16 total_length ACX_PACKED; /* 0x10 */
5199 + u16 Reserved ACX_PACKED; /* 0x12 */
5201 +/* The following 16 bytes do not change when acx100 owns the descriptor */
5202 +/* BUG: fw clears last byte of this area which is supposedly reserved
5203 +** for driver use. amd64 blew up. We dare not use it now */
5204 + u32 dummy[4] ACX_PACKED;
5206 + u8 Ctl_8 ACX_PACKED; /* 0x24, 8bit value */
5207 + u8 Ctl2_8 ACX_PACKED; /* 0x25, 8bit value */
5208 + u8 error ACX_PACKED; /* 0x26 */
5209 + u8 ack_failures ACX_PACKED; /* 0x27 */
5210 + u8 rts_failures ACX_PACKED; /* 0x28 */
5211 + u8 rts_ok ACX_PACKED; /* 0x29 */
5214 + u8 rate ACX_PACKED; /* 0x2a */
5215 + u8 queue_ctrl ACX_PACKED; /* 0x2b */
5218 + u16 rate111 ACX_PACKED; /* 0x2a */
5221 + u32 queue_info ACX_PACKED; /* 0x2c (acx100, reserved on acx111) */
5222 +}; /* size : 48 = 0x30 */
5223 +/* NB: acx111 txdesc structure is 4 byte larger */
5224 +/* All these 4 extra bytes are reserved. tx alloc code takes them into account */
5227 + acx_ptr pNextDesc ACX_PACKED; /* 0x00 */
5228 + acx_ptr HostMemPtr ACX_PACKED; /* 0x04 */
5229 + acx_ptr ACXMemPtr ACX_PACKED; /* 0x08 */
5230 + u32 rx_time ACX_PACKED; /* 0x0c */
5231 + u16 total_length ACX_PACKED; /* 0x10 */
5232 + u16 WEP_length ACX_PACKED; /* 0x12 */
5233 + u32 WEP_ofs ACX_PACKED; /* 0x14 */
5235 +/* the following 16 bytes do not change when acx100 owns the descriptor */
5236 + u8 driverWorkspace[16] ACX_PACKED; /* 0x18 */
5238 + u8 Ctl_8 ACX_PACKED;
5239 + u8 rate ACX_PACKED;
5240 + u8 error ACX_PACKED;
5241 + u8 SNR ACX_PACKED; /* Signal-to-Noise Ratio */
5242 + u8 RxLevel ACX_PACKED;
5243 + u8 queue_ctrl ACX_PACKED;
5244 + u16 unknown ACX_PACKED;
5245 + u32 unknown2 ACX_PACKED;
5246 +}; /* size 52 = 0x34 */
5250 +/* Register I/O offsets */
5251 +#define ACX100_EEPROM_ID_OFFSET 0x380
5253 +/* please add further ACX hardware register definitions only when
5254 + it turns out you need them in the driver, and please try to use
5255 + firmware functionality instead, since using direct I/O access instead
5256 + of letting the firmware do it might confuse the firmware's state
5259 +/* ***** ABSOLUTELY ALWAYS KEEP OFFSETS IN SYNC WITH THE INITIALIZATION
5260 +** OF THE I/O ARRAYS!!!! (grep for '^IO_ACX') ***** */
5262 + IO_ACX_SOFT_RESET = 0,
5264 + IO_ACX_HW_SLAVE_REG_ADDR,
5265 + IO_ACX_HW_SLAVE_REG_DATA,
5266 + IO_ACX_HW_SLAVE_REG_CTRL,
5268 + IO_ACX_SLV_MEM_ADDR,
5269 + IO_ACX_SLV_MEM_DATA,
5270 + IO_ACX_SLV_MEM_CTL,
5271 + IO_ACX_SLV_END_CTL,
5274 + IO_ACX_FEMR, /* Function Event Mask */
5278 + IO_ACX_IRQ_STATUS_NON_DES,
5279 + IO_ACX_IRQ_STATUS_CLEAR, /* CLEAR = clear on read */
5285 + IO_ACX_EEPROM_CTL,
5286 + IO_ACX_EEPROM_ADDR,
5287 + IO_ACX_EEPROM_DATA,
5288 + IO_ACX_EEPROM_CFG,
5301 + IO_ACX_CMD_MAILBOX_OFFS,
5302 + IO_ACX_INFO_MAILBOX_OFFS,
5303 + IO_ACX_EEPROM_INFORMATION,
5312 + IO_ACX_PCI_ARB_CFG,
5314 +/* ***** ABSOLUTELY ALWAYS KEEP OFFSETS IN SYNC WITH THE INITIALIZATION
5315 +** OF THE I/O ARRAYS!!!! (grep for '^IO_ACX') ***** */
5317 +/* Values for IO_ACX_INT_TRIG register: */
5318 +/* inform hw that rxdesc in queue needs processing */
5319 +#define INT_TRIG_RXPRC 0x08
5320 +/* inform hw that txdesc in queue needs processing */
5321 +#define INT_TRIG_TXPRC 0x04
5322 +/* ack that we received info from info mailbox */
5323 +#define INT_TRIG_INFOACK 0x02
5324 +/* inform hw that we have filled command mailbox */
5325 +#define INT_TRIG_CMD 0x01
5327 +struct txhostdesc {
5328 + acx_ptr data_phy ACX_PACKED; /* 0x00 [u8 *] */
5329 + u16 data_offset ACX_PACKED; /* 0x04 */
5330 + u16 reserved ACX_PACKED; /* 0x06 */
5331 + u16 Ctl_16 ACX_PACKED; /* 16bit value, endianness!! */
5332 + u16 length ACX_PACKED; /* 0x0a */
5333 + acx_ptr desc_phy_next ACX_PACKED; /* 0x0c [txhostdesc *] */
5334 + acx_ptr pNext ACX_PACKED; /* 0x10 [txhostdesc *] */
5335 + u32 Status ACX_PACKED; /* 0x14, unused on Tx */
5336 +/* From here on you can use this area as you want (variable length, too!) */
5337 + u8 *data ACX_PACKED;
5340 +struct rxhostdesc {
5341 + acx_ptr data_phy ACX_PACKED; /* 0x00 [rxbuffer_t *] */
5342 + u16 data_offset ACX_PACKED; /* 0x04 */
5343 + u16 reserved ACX_PACKED; /* 0x06 */
5344 + u16 Ctl_16 ACX_PACKED; /* 0x08; 16bit value, endianness!! */
5345 + u16 length ACX_PACKED; /* 0x0a */
5346 + acx_ptr desc_phy_next ACX_PACKED; /* 0x0c [rxhostdesc_t *] */
5347 + acx_ptr pNext ACX_PACKED; /* 0x10 [rxhostdesc_t *] */
5348 + u32 Status ACX_PACKED; /* 0x14 */
5349 +/* From here on you can use this area as you want (variable length, too!) */
5350 + rxbuffer_t *data ACX_PACKED;
5353 +#endif /* ACX_PCI */
5355 +/***************************************************************
5356 +** USB structures and constants
5360 +/* Buffer size for fw upload */
5361 +#define ACX100_USB_RWMEM_MAXLEN 2048
5363 +/* Should be sent to the ctrlout endpoint */
5364 +#define ACX100_USB_ENBULKIN 6
5366 +/* The number of bulk URBs to use */
5367 +#define ACX100_USB_NUM_BULK_URBS 8
5369 +/* Should be sent to the bulkout endpoint */
5370 +#define ACX_USB_REQ_UPLOAD_FW 0x10
5371 +#define ACX_USB_REQ_ACK_CS 0x11
5372 +#define ACX_USB_REQ_CMD 0x12
5374 +/* Used for usb_txbuffer.desc field */
5375 +#define USB_TXBUF_TXDESC 0xA
5376 +/* Used for usb_txbuffer.hostData field */
5377 +#define USB_TXBUF_HD_ISDATA 0x10000
5378 +#define USB_TXBUF_HD_DIRECTED 0x20000
5379 +#define USB_TXBUF_HD_BROADCAST 0x40000
5380 +/* Size of header (everything up to data[]) */
5381 +#define USB_TXBUF_HDRSIZE 14
5382 +typedef struct usb_txbuffer {
5383 + u16 desc ACX_PACKED;
5384 + u16 MPDUlen ACX_PACKED;
5385 + u8 index ACX_PACKED;
5386 + u8 txRate ACX_PACKED;
5387 + u32 hostData ACX_PACKED;
5388 + u8 ctrl1 ACX_PACKED;
5389 + u8 ctrl2 ACX_PACKED;
5390 + u16 dataLength ACX_PACKED;
5391 + /* wlan packet content is placed here: */
5392 + u8 data[WLAN_A4FR_MAXLEN_WEP_FCS] ACX_PACKED;
5398 +} acx_usb_bulk_context_t;
5400 +typedef struct usb_tx {
5403 + wlandevice_t *priv;
5405 + /* actual USB bulk output data block is here: */
5406 + usb_txbuffer_t bulkout;
5409 +#endif /* ACX_USB */
5412 +/*============================================================================*
5413 + * Main acx per-device data structure (netdev_priv(dev)) *
5414 + *============================================================================*/
5415 +#define ACX_STATE_FW_LOADED 0x01
5416 +#define ACX_STATE_IFACE_UP 0x02
5418 +/* MAC mode (BSS type) defines
5419 + * Note that they shouldn't be redefined, since they are also used
5420 + * during communication with firmware */
5421 +#define ACX_MODE_0_ADHOC 0
5422 +#define ACX_MODE_1_UNUSED 1
5423 +#define ACX_MODE_2_STA 2
5424 +#define ACX_MODE_3_AP 3
5425 +/* These are our own inventions. Sending these to firmware
5426 +** makes it stop emitting beacons, which is exactly what we want
5427 +** for these modes */
5428 +#define ACX_MODE_MONITOR 0xfe
5429 +#define ACX_MODE_OFF 0xff
5430 +/* 'Submode': identifies exact status of ADHOC/STA host */
5431 +#define ACX_STATUS_0_STOPPED 0
5432 +#define ACX_STATUS_1_SCANNING 1
5433 +#define ACX_STATUS_2_WAIT_AUTH 2
5434 +#define ACX_STATUS_3_AUTHENTICATED 3
5435 +#define ACX_STATUS_4_ASSOCIATED 4
5437 +/* FIXME: this should be named something like struct acx_priv (typedef'd to
5440 +/* non-firmware struct, no packing necessary */
5441 +struct wlandevice {
5442 + /*** Device chain ***/
5443 + struct wlandevice *next; /* link for list of devices */
5445 + /*** Linux network device ***/
5446 + struct net_device *netdev; /* pointer to linux netdevice */
5447 + struct net_device *prev_nd; /* FIXME: We should not chain via our
5448 + * private struct wlandevice _and_
5449 + * the struct net_device. */
5450 + /*** Device statistics ***/
5451 + struct net_device_stats stats; /* net device statistics */
5452 +#ifdef WIRELESS_EXT
5453 + struct iw_statistics wstats; /* wireless statistics */
5455 + /*** Power managment ***/
5456 + struct pm_dev *pm; /* PM crap */
5458 + /*** Management timer ***/
5459 + struct timer_list mgmt_timer;
5462 + struct semaphore sem;
5464 +#if defined(PARANOID_LOCKING) /* Lock debugging */
5465 + const char *last_sem;
5466 + const char *last_lock;
5467 + unsigned long sem_time;
5468 + unsigned long lock_time;
5471 + /*** Hardware identification ***/
5472 + const char *chip_name;
5477 + u8 eeprom_version;
5479 + /*** Firmware identification ***/
5480 + char firmware_version[FW_ID_SIZE+1];
5481 + u32 firmware_numver;
5484 + /*** Device state ***/
5485 + u16 dev_state_mask;
5486 + u8 led_power; /* power LED status */
5487 + u32 get_mask; /* mask of settings to fetch from the card */
5488 + u32 set_mask; /* mask of settings to write to the card */
5490 + /* Barely used in USB case */
5493 + u8 after_interrupt_jobs; /* mini job list for doing actions after an interrupt occurred */
5494 + WORK_STRUCT after_interrupt_task; /* our task for after interrupt actions */
5496 + /*** scanning ***/
5497 + u16 scan_count; /* number of times to do channel scan */
5498 + u8 scan_mode; /* 0 == active, 1 == passive, 2 == background */
5500 + u16 scan_duration;
5501 + u16 scan_probe_delay;
5502 +#if WIRELESS_EXT > 15
5503 + struct iw_spy_data spy_data; /* FIXME: needs to be implemented! */
5506 + /*** Wireless network settings ***/
5507 + /* copy of the device address (ifconfig hw ether) that we actually use
5508 + ** for 802.11; copied over from the network device's MAC address
5509 + ** (ifconfig) when it makes sense only */
5510 + u8 dev_addr[MAX_ADDR_LEN];
5511 + u8 bssid[ETH_ALEN]; /* the BSSID after having joined */
5512 + u8 ap[ETH_ALEN]; /* The AP we want, FF:FF:FF:FF:FF:FF is any */
5513 + u16 aid; /* The Association ID sent from the AP / last used AID if we're an AP */
5514 + u16 mode; /* mode from iwconfig */
5515 + u16 status; /* 802.11 association status */
5516 + u8 essid_active; /* specific ESSID active, or select any? */
5517 + u8 essid_len; /* to avoid dozens of strlen() */
5518 + /* INCLUDES \0 termination for easy printf - but many places
5519 + ** simply want the string data memcpy'd plus a length indicator!
5520 + ** Keep that in mind... */
5521 + char essid[IW_ESSID_MAX_SIZE+1];
5522 + /* essid we are going to use for association, in case of "essid 'any'"
5523 + ** and in case of hidden ESSID (use configured ESSID then) */
5524 + char essid_for_assoc[IW_ESSID_MAX_SIZE+1];
5525 + char nick[IW_ESSID_MAX_SIZE+1]; /* see essid! */
5527 + u8 reg_dom_id; /* reg domain setting */
5528 + u16 reg_dom_chanmask;
5529 + u16 auth_or_assoc_retries;
5531 + unsigned long scan_start; /* YES, jiffies is defined as "unsigned long" */
5533 + /* stations known to us (if we're an ap) */
5534 + client_t sta_list[32]; /* tab is larger than list, so that */
5535 + client_t *sta_hash_tab[64]; /* hash collisions are not likely */
5536 + client_t *ap_client; /* this one is our AP (STA mode only) */
5538 + unsigned long dup_msg_expiry;
5541 + u16 last_seq_ctrl; /* duplicate packet detection */
5543 + /* 802.11 power save mode */
5545 + u8 ps_listen_interval;
5547 + u8 ps_hangover_period;
5548 + u16 ps_enhanced_transition_time;
5550 + /*** PHY settings ***/
5551 + u8 fallback_threshold;
5552 + u8 stepup_threshold;
5556 + u16 rate_bcast100;
5557 + u8 rate_auto; /* false if "iwconfig rate N" (WITHOUT 'auto'!) */
5558 + u8 preamble_mode; /* 0 == Long Preamble, 1 == Short, 2 == Auto */
5563 + /* u8 tx_level_val; */
5564 + /* u8 tx_level_auto; whether to do automatic power adjustment */
5566 + unsigned long recalib_time_last_success;
5567 + unsigned long recalib_time_last_attempt;
5568 + int recalib_failure_count;
5569 + int recalib_msg_ratelimit;
5570 + int retry_errors_msg_ratelimit;
5572 + unsigned long brange_time_last_state_change; /* time the power LED was last changed */
5573 + u8 brange_last_state; /* last state of the LED */
5574 + u8 brange_max_quality; /* maximum quality that equates to full speed */
5577 + u8 antenna; /* antenna settings */
5578 + u8 ed_threshold; /* energy detect threshold */
5579 + u8 cca; /* clear channel assessment */
5581 + u16 rts_threshold;
5584 + u16 msdu_lifetime;
5585 + u16 listen_interval; /* given in units of beacon interval */
5586 + u32 beacon_interval;
5592 + u8 rate_supported_len;
5593 + u8 rate_supported[13];
5595 + /*** Encryption settings (WEP) ***/
5596 + u32 auth_alg; /* used in transmit_authen1 */
5598 + u8 wep_restricted;
5599 + u8 wep_current_index;
5600 + wep_key_t wep_keys[DOT11_MAX_DEFAULT_WEP_KEYS]; /* the default WEP keys */
5601 + key_struct_t wep_key_struct[10];
5603 + /*** Card Rx/Tx management ***/
5612 +/*** PCI/USB/... must be last or else hw agnostic code breaks horribly ***/
5613 + /* hack to let common code compile. FIXME */
5614 + dma_addr_t rxhostdesc_startphy;
5616 + /*** PCI stuff ***/
5618 + /* pointers to tx buffers, tx host descriptors (in host memory)
5619 + ** and tx descrs in device memory */
5621 + txhostdesc_t *txhostdesc_start;
5622 + txdesc_t *txdesc_start; /* points to PCI-mapped memory */
5624 + rxbuffer_t *rxbuf_start;
5625 + rxhostdesc_t *rxhostdesc_start;
5626 + rxdesc_t *rxdesc_start;
5627 + /* physical addresses of above host memory areas */
5628 + dma_addr_t rxbuf_startphy;
5629 + /* dma_addr_t rxhostdesc_startphy; */
5630 + dma_addr_t txbuf_startphy;
5631 + dma_addr_t txhostdesc_startphy;
5632 + /* sizes of above host memory areas */
5633 + unsigned int txbuf_area_size;
5634 + unsigned int txhostdesc_area_size;
5635 + unsigned int rxbuf_area_size;
5636 + unsigned int rxhostdesc_area_size;
5638 + unsigned int txdesc_size; /* size per tx descr; ACX111 = ACX100 + 4 */
5639 + unsigned int tx_head; /* current ring buffer pool member index */
5640 + unsigned int tx_tail;
5641 + unsigned int rx_tail;
5643 + client_t *txc[TX_CNT];
5646 + u8 irqs_active; /* whether irq sending is activated */
5648 + const u16 *io; /* points to ACX100 or ACX111 I/O register address set */
5650 +#if defined(CONFIG_ACX_CFI)
5651 + struct device *dev;
5653 + struct pci_dev *pdev;
5656 + unsigned long membase;
5657 + unsigned long membase2;
5661 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 10)
5662 + /* 2.6.9-rc3-mm2 (2.6.9-bk4, too) introduced a shorter API version,
5663 + then it made its way into 2.6.10 */
5664 + u32 pci_state[16]; /* saved PCI state for suspend/resume */
5666 + u16 irq_mask; /* interrupt types to mask out (not wanted) with many IRQs activated */
5667 + u16 irq_mask_off; /* interrupt types to mask out (not wanted) with IRQs off */
5668 + unsigned int irq_loops_this_jiffy;
5669 + unsigned long irq_last_jiffies;
5671 + /* command interface */
5672 + void *cmd_area; /* points to PCI mapped memory */
5673 + void *info_area; /* points to PCI mapped memory */
5680 + /*** USB stuff ***/
5682 + struct usb_device *usbdev;
5684 + rxbuffer_t rxtruncbuf;
5685 + /* TODO: convert (bulkins,bulkrx_urbs,rxcons) triple into
5686 + ** struct usb_rx (see struct usb_tx for an example) */
5687 + rxbuffer_t bulkins[ACX100_USB_NUM_BULK_URBS];
5688 + struct urb *bulkrx_urbs[ACX100_USB_NUM_BULK_URBS];
5689 + /* Used by rx urb completion handler in order to find
5690 + ** corresponding priv/index pair */
5691 + acx_usb_bulk_context_t rxcons[ACX100_USB_NUM_BULK_URBS];
5692 + usb_tx_t usb_tx[ACX100_USB_NUM_BULK_URBS];
5694 + int bulkinep; /* bulk-in endpoint */
5695 + int bulkoutep; /* bulk-out endpoint */
5701 +/* For use with ACX1xx_IE_RXCONFIG */
5703 + * 13 include additional header (length etc.) *required*
5704 + * struct is defined in 'struct rxbuffer'
5705 + * is this bit acx100 only? does acx111 always put the header,
5706 + * and bit setting is irrelevant? --vda
5707 + * 10 receive frames only with SSID used in last join cmd
5708 + * 9 discard broadcast
5709 + * 8 receive packets for multicast address 1
5710 + * 7 receive packets for multicast address 0
5711 + * 6 discard all multicast packets
5712 + * 5 discard frames from foreign BSSID
5713 + * 4 discard frames with foreign destination MAC address
5714 + * 3 promiscuous mode (receive ALL frames, disable filter)
5716 + * 1 include phy header
5719 +#define RX_CFG1_INCLUDE_RXBUF_HDR 0x2000 /* ACX100 only */
5720 +#define RX_CFG1_FILTER_SSID 0x0400
5721 +#define RX_CFG1_FILTER_BCAST 0x0200
5722 +#define RX_CFG1_RCV_MC_ADDR1 0x0100
5723 +#define RX_CFG1_RCV_MC_ADDR0 0x0080
5724 +#define RX_CFG1_FILTER_ALL_MULTI 0x0040
5725 +#define RX_CFG1_FILTER_BSSID 0x0020
5726 +#define RX_CFG1_FILTER_MAC 0x0010
5727 +#define RX_CFG1_RCV_PROMISCUOUS 0x0008
5728 +#define RX_CFG1_INCLUDE_FCS 0x0004
5729 +#define RX_CFG1_INCLUDE_PHY_HDR (WANT_PHY_HDR ? 0x0002 : 0)
5731 + * 11 receive association requests etc.
5732 + * 10 receive authentication frames
5733 + * 9 receive beacon frames
5734 + * 8 receive contention free packets
5735 + * 7 receive control frames
5736 + * 6 receive data frames
5737 + * 5 receive broken frames
5738 + * 4 receive management frames
5739 + * 3 receive probe requests
5740 + * 2 receive probe responses
5741 + * 1 receive RTS/CTS/ACK frames
5744 +#define RX_CFG2_RCV_ASSOC_REQ 0x0800
5745 +#define RX_CFG2_RCV_AUTH_FRAMES 0x0400
5746 +#define RX_CFG2_RCV_BEACON_FRAMES 0x0200
5747 +#define RX_CFG2_RCV_CONTENTION_FREE 0x0100
5748 +#define RX_CFG2_RCV_CTRL_FRAMES 0x0080
5749 +#define RX_CFG2_RCV_DATA_FRAMES 0x0040
5750 +#define RX_CFG2_RCV_BROKEN_FRAMES 0x0020
5751 +#define RX_CFG2_RCV_MGMT_FRAMES 0x0010
5752 +#define RX_CFG2_RCV_PROBE_REQ 0x0008
5753 +#define RX_CFG2_RCV_PROBE_RESP 0x0004
5754 +#define RX_CFG2_RCV_ACK_FRAMES 0x0002
5755 +#define RX_CFG2_RCV_OTHER 0x0001
5757 +/* For use with ACX1xx_IE_FEATURE_CONFIG */
5758 +#define FEATURE1_80MHZ_CLOCK 0x00000040L
5759 +#define FEATURE1_4X 0x00000020L
5760 +#define FEATURE1_LOW_RX 0x00000008L
5761 +#define FEATURE1_EXTRA_LOW_RX 0x00000001L
5763 +#define FEATURE2_SNIFFER 0x00000080L
5764 +#define FEATURE2_NO_TXCRYPT 0x00000001L
5766 +/*-- get and set mask values --*/
5767 +#define GETSET_LED_POWER 0x00000001L
5768 +#define GETSET_STATION_ID 0x00000002L
5769 +#define SET_TEMPLATES 0x00000004L
5770 +#define SET_STA_LIST 0x00000008L
5771 +#define GETSET_TX 0x00000010L
5772 +#define GETSET_RX 0x00000020L
5773 +#define SET_RXCONFIG 0x00000040L
5774 +#define GETSET_ANTENNA 0x00000080L
5775 +#define GETSET_SENSITIVITY 0x00000100L
5776 +#define GETSET_TXPOWER 0x00000200L
5777 +#define GETSET_ED_THRESH 0x00000400L
5778 +#define GETSET_CCA 0x00000800L
5779 +#define GETSET_POWER_80211 0x00001000L
5780 +#define GETSET_RETRY 0x00002000L
5781 +#define GETSET_REG_DOMAIN 0x00004000L
5782 +#define GETSET_CHANNEL 0x00008000L
5783 +/* Used when ESSID changes etc and we need to scan for AP anew */
5784 +#define GETSET_RESCAN 0x00010000L
5785 +#define GETSET_MODE 0x00020000L
5786 +#define GETSET_WEP 0x00040000L
5787 +#define SET_WEP_OPTIONS 0x00080000L
5788 +#define SET_MSDU_LIFETIME 0x00100000L
5789 +#define SET_RATE_FALLBACK 0x00200000L
5790 +#define GETSET_ALL 0x80000000L
5793 +/*============================================================================*
5794 + * Firmware loading *
5795 + *============================================================================*/
5796 +/* Doh, 2.4.x also has CONFIG_FW_LOADER_MODULE
5797 + * (but doesn't have the new device model yet which we require!)
5798 + * FIXME: exact version that introduced new device handling? */
5799 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
5800 +#if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE)
5801 +#define USE_FW_LOADER_26 1
5802 +#define USE_FW_LOADER_LEGACY 0
5804 +#define USE_FW_LOADER_26 0
5805 +#define USE_FW_LOADER_LEGACY 1
5809 +#if USE_FW_LOADER_26
5810 +#include <linux/firmware.h> /* request_firmware() */
5811 +#include <linux/pci.h> /* struct pci_device */
5815 +/***********************************************************************
5817 +typedef struct acx100_ie_memblocksize {
5818 + u16 type ACX_PACKED;
5819 + u16 len ACX_PACKED;
5820 + u16 size ACX_PACKED;
5821 +} acx100_ie_memblocksize_t;
5823 +typedef struct acx100_ie_queueconfig {
5824 + u16 type ACX_PACKED;
5825 + u16 len ACX_PACKED;
5826 + u32 AreaSize ACX_PACKED;
5827 + u32 RxQueueStart ACX_PACKED;
5828 + u8 QueueOptions ACX_PACKED;
5829 + u8 NumTxQueues ACX_PACKED;
5830 + u8 NumRxDesc ACX_PACKED; /* for USB only */
5831 + u8 pad1 ACX_PACKED;
5832 + u32 QueueEnd ACX_PACKED;
5833 + u32 HostQueueEnd ACX_PACKED; /* QueueEnd2 */
5834 + u32 TxQueueStart ACX_PACKED;
5835 + u8 TxQueuePri ACX_PACKED;
5836 + u8 NumTxDesc ACX_PACKED;
5837 + u16 pad2 ACX_PACKED;
5838 +} acx100_ie_queueconfig_t;
5840 +typedef struct acx111_ie_queueconfig {
5841 + u16 type ACX_PACKED;
5842 + u16 len ACX_PACKED;
5843 + u32 tx_memory_block_address ACX_PACKED;
5844 + u32 rx_memory_block_address ACX_PACKED;
5845 + u32 rx1_queue_address ACX_PACKED;
5846 + u32 reserved1 ACX_PACKED;
5847 + u32 tx1_queue_address ACX_PACKED;
5848 + u8 tx1_attributes ACX_PACKED;
5849 + u16 reserved2 ACX_PACKED;
5850 + u8 reserved3 ACX_PACKED;
5851 +} acx111_ie_queueconfig_t;
5853 +typedef struct acx100_ie_memconfigoption {
5854 + u16 type ACX_PACKED;
5855 + u16 len ACX_PACKED;
5856 + u32 DMA_config ACX_PACKED;
5857 + acx_ptr pRxHostDesc ACX_PACKED;
5858 + u32 rx_mem ACX_PACKED;
5859 + u32 tx_mem ACX_PACKED;
5860 + u16 RxBlockNum ACX_PACKED;
5861 + u16 TxBlockNum ACX_PACKED;
5862 +} acx100_ie_memconfigoption_t;
5864 +typedef struct acx111_ie_memoryconfig {
5865 + u16 type ACX_PACKED;
5866 + u16 len ACX_PACKED;
5867 + u16 no_of_stations ACX_PACKED;
5868 + u16 memory_block_size ACX_PACKED;
5869 + u8 tx_rx_memory_block_allocation ACX_PACKED;
5870 + u8 count_rx_queues ACX_PACKED;
5871 + u8 count_tx_queues ACX_PACKED;
5872 + u8 options ACX_PACKED;
5873 + u8 fragmentation ACX_PACKED;
5874 + u16 reserved1 ACX_PACKED;
5875 + u8 reserved2 ACX_PACKED;
5877 + /* start of rx1 block */
5878 + u8 rx_queue1_count_descs ACX_PACKED;
5879 + u8 rx_queue1_reserved1 ACX_PACKED;
5880 + u8 rx_queue1_type ACX_PACKED; /* must be set to 7 */
5881 + u8 rx_queue1_prio ACX_PACKED; /* must be set to 0 */
5882 + acx_ptr rx_queue1_host_rx_start ACX_PACKED;
5883 + /* end of rx1 block */
5885 + /* start of tx1 block */
5886 + u8 tx_queue1_count_descs ACX_PACKED;
5887 + u8 tx_queue1_reserved1 ACX_PACKED;
5888 + u8 tx_queue1_reserved2 ACX_PACKED;
5889 + u8 tx_queue1_attributes ACX_PACKED;
5890 + /* end of tx1 block */
5891 +} acx111_ie_memoryconfig_t;
5893 +typedef struct acx_ie_memmap {
5894 + u16 type ACX_PACKED;
5895 + u16 len ACX_PACKED;
5896 + u32 CodeStart ACX_PACKED;
5897 + u32 CodeEnd ACX_PACKED;
5898 + u32 WEPCacheStart ACX_PACKED;
5899 + u32 WEPCacheEnd ACX_PACKED;
5900 + u32 PacketTemplateStart ACX_PACKED;
5901 + u32 PacketTemplateEnd ACX_PACKED;
5902 + u32 QueueStart ACX_PACKED;
5903 + u32 QueueEnd ACX_PACKED;
5904 + u32 PoolStart ACX_PACKED;
5905 + u32 PoolEnd ACX_PACKED;
5908 +typedef struct acx111_ie_feature_config {
5909 + u16 type ACX_PACKED;
5910 + u16 len ACX_PACKED;
5911 + u32 feature_options ACX_PACKED;
5912 + u32 data_flow_options ACX_PACKED;
5913 +} acx111_ie_feature_config_t;
5915 +typedef struct acx111_ie_tx_level {
5916 + u16 type ACX_PACKED;
5917 + u16 len ACX_PACKED;
5918 + u8 level ACX_PACKED;
5919 +} acx111_ie_tx_level_t;
5921 +#define PS_CFG_ENABLE 0x80
5922 +#define PS_CFG_PENDING 0x40 /* status flag when entering PS */
5923 +#define PS_CFG_WAKEUP_MODE_MASK 0x07
5924 +#define PS_CFG_WAKEUP_BY_HOST 0x03
5925 +#define PS_CFG_WAKEUP_EACH_ITVL 0x02
5926 +#define PS_CFG_WAKEUP_ON_DTIM 0x01
5927 +#define PS_CFG_WAKEUP_ALL_BEAC 0x00
5929 +/* Enhanced PS mode: sleep until Rx Beacon w/ the STA's AID bit set
5930 +** in the TIM; newer firmwares only(?) */
5931 +#define PS_OPT_ENA_ENHANCED_PS 0x04
5932 +#define PS_OPT_STILL_RCV_BCASTS 0x01
5934 +typedef struct acx100_ie_powermgmt {
5935 + u32 type ACX_PACKED;
5936 + u32 len ACX_PACKED;
5937 + u8 wakeup_cfg ACX_PACKED;
5938 + u8 listen_interval ACX_PACKED; /* for EACH_ITVL: wake up every "beacon units" interval */
5939 + u8 options ACX_PACKED;
5940 + u8 hangover_period ACX_PACKED; /* remaining wake time after Tx MPDU w/ PS bit, in values of 1/1024 seconds */
5941 + u16 enhanced_ps_transition_time ACX_PACKED; /* rem. wake time for Enh. PS */
5942 +} acx100_ie_powermgmt_t;
5944 +typedef struct acx111_ie_powermgmt {
5945 + u32 type ACX_PACKED;
5946 + u32 len ACX_PACKED;
5947 + u8 wakeup_cfg ACX_PACKED;
5948 + u8 listen_interval ACX_PACKED; /* for EACH_ITVL: wake up every "beacon units" interval */
5949 + u8 options ACX_PACKED;
5950 + u8 hangover_period ACX_PACKED; /* remaining wake time after Tx MPDU w/ PS bit, in values of 1/1024 seconds */
5951 + u32 beaconRxTime ACX_PACKED;
5952 + u32 enhanced_ps_transition_time ACX_PACKED; /* rem. wake time for Enh. PS */
5953 +} acx111_ie_powermgmt_t;
5956 +/***********************************************************************
5957 +** Commands and template structures
5961 +** SCAN command structure
5963 +** even though acx100 scan rates match RATE100 constants,
5964 +** acx111 ones do not match! Therefore we do not use RATE100 #defines */
5965 +#define ACX_SCAN_RATE_1 10
5966 +#define ACX_SCAN_RATE_2 20
5967 +#define ACX_SCAN_RATE_5 55
5968 +#define ACX_SCAN_RATE_11 110
5969 +#define ACX_SCAN_RATE_22 220
5970 +#define ACX_SCAN_OPT_ACTIVE 0x00 /* a bit mask */
5971 +#define ACX_SCAN_OPT_PASSIVE 0x01
5972 +/* Background scan: we go into Power Save mode (by transmitting
5973 +** NULL data frame to AP with the power mgmt bit set), do the scan,
5974 +** and then exit Power Save mode. A plus is that AP buffers frames
5975 +** for us while we do background scan. Thus we avoid frame losses.
5976 +** Background scan can be active or passive, just like normal one */
5977 +#define ACX_SCAN_OPT_BACKGROUND 0x02
5978 +typedef struct acx100_scan {
5979 + u16 count ACX_PACKED; /* number of scans to do, 0xffff == continuous */
5980 + u16 start_chan ACX_PACKED;
5981 + u16 flags ACX_PACKED; /* channel list mask; 0x8000 == all channels? */
5982 + u8 max_rate ACX_PACKED; /* max. probe rate */
5983 + u8 options ACX_PACKED; /* bit mask, see defines above */
5984 + u16 chan_duration ACX_PACKED;
5985 + u16 max_probe_delay ACX_PACKED;
5986 +} acx100_scan_t; /* length 0xc */
5988 +#define ACX111_SCAN_RATE_6 0x0B
5989 +#define ACX111_SCAN_RATE_9 0x0F
5990 +#define ACX111_SCAN_RATE_12 0x0A
5991 +#define ACX111_SCAN_RATE_18 0x0E
5992 +#define ACX111_SCAN_RATE_24 0x09
5993 +#define ACX111_SCAN_RATE_36 0x0D
5994 +#define ACX111_SCAN_RATE_48 0x08
5995 +#define ACX111_SCAN_RATE_54 0x0C
5996 +#define ACX111_SCAN_OPT_5GHZ 0x04 /* else 2.4GHZ */
5997 +#define ACX111_SCAN_MOD_SHORTPRE 0x01 /* you can combine SHORTPRE and PBCC */
5998 +#define ACX111_SCAN_MOD_PBCC 0x80
5999 +#define ACX111_SCAN_MOD_OFDM 0x40
6000 +typedef struct acx111_scan {
6001 + u16 count ACX_PACKED; /* number of scans to do */
6002 + u8 channel_list_select ACX_PACKED; /* 0: scan all channels, 1: from chan_list only */
6003 + u16 reserved1 ACX_PACKED;
6004 + u8 reserved2 ACX_PACKED;
6005 + u8 rate ACX_PACKED; /* rate for probe requests (if active scan) */
6006 + u8 options ACX_PACKED; /* bit mask, see defines above */
6007 + u16 chan_duration ACX_PACKED; /* min time to wait for reply on one channel (in TU) */
6008 + /* (active scan only) (802.11 section 11.1.3.2.2) */
6009 + u16 max_probe_delay ACX_PACKED; /* max time to wait for reply on one channel (active scan) */
6010 + /* time to listen on a channel (passive scan) */
6011 + u8 modulation ACX_PACKED;
6012 + u8 channel_list[26] ACX_PACKED; /* bits 7:0 first byte: channels 8:1 */
6013 + /* bits 7:0 second byte: channels 16:9 */
6014 + /* 26 bytes is enough to cover 802.11a */
6019 +** Radio calibration command structure
6021 +typedef struct acx111_cmd_radiocalib {
6022 +/* 0x80000000 == automatic calibration by firmware, according to interval;
6023 + * bits 0..3: select calibration methods to go through:
6024 + * calib based on DC, AfeDC, Tx mismatch, Tx equilization */
6025 + u32 methods ACX_PACKED;
6026 + u32 interval ACX_PACKED;
6027 +} acx111_cmd_radiocalib_t;
6031 +** Packet template structures
6033 +** Packet templates store contents of Beacon, Probe response, Probe request,
6034 +** Null data frame, and TIM data frame. Firmware automatically transmits
6035 +** contents of template at appropriate time:
6036 +** - Beacon: when configured as AP or Ad-hoc
6037 +** - Probe response: when configured as AP or Ad-hoc, whenever
6038 +** a Probe request frame is received
6039 +** - Probe request: when host issues SCAN command (active)
6040 +** - Null data frame: when entering 802.11 power save mode
6041 +** - TIM data: at the end of Beacon frames (if no TIM template
6042 +** is configured, then transmits default TIM)
6044 +** - size field must be set to size of actual template
6045 +** (NOT sizeof(struct) - templates are variable in length),
6046 +** size field is not itself counted.
6047 +** - members flagged with an asterisk must be initialized with host,
6048 +** rest must be zero filled.
6049 +** - variable length fields shown only in comments */
6050 +typedef struct acx_template_tim {
6051 + u16 size ACX_PACKED;
6052 + u8 tim_eid ACX_PACKED; /* 00 1 TIM IE ID * */
6053 + u8 len ACX_PACKED; /* 01 1 Length * */
6054 + u8 dtim_cnt ACX_PACKED; /* 02 1 DTIM Count */
6055 + u8 dtim_period ACX_PACKED; /* 03 1 DTIM Period */
6056 + u8 bitmap_ctrl ACX_PACKED; /* 04 1 Bitmap Control * (except bit0) */
6057 + /* 05 n Partial Virtual Bitmap * */
6058 + u8 variable[0x100 - 1-1-1-1-1] ACX_PACKED;
6059 +} acx_template_tim_t;
6061 +typedef struct acx100_template_probereq {
6062 + u16 size ACX_PACKED;
6063 + u16 fc ACX_PACKED; /* 00 2 fc */
6064 + u16 dur ACX_PACKED; /* 02 2 Duration */
6065 + u8 da[6] ACX_PACKED; /* 04 6 Destination Address * */
6066 + u8 sa[6] ACX_PACKED; /* 0A 6 Source Address * */
6067 + u8 bssid[6] ACX_PACKED; /* 10 6 BSSID * */
6068 + u16 seq ACX_PACKED; /* 16 2 Sequence Control */
6069 + u8 timestamp[8] ACX_PACKED;/* 18 8 Timestamp */
6070 + u16 beacon_interval ACX_PACKED; /* 20 2 Beacon Interval * */
6071 + u16 cap ACX_PACKED; /* 22 2 Capability Information * */
6073 + /* nn n Supported Rates * */
6074 + u8 variable[0x44 - 2-2-6-6-6-2-8-2-2] ACX_PACKED;
6075 +} acx100_template_probereq_t;
6077 +typedef struct acx111_template_probereq {
6078 + u16 size ACX_PACKED;
6079 + u16 fc ACX_PACKED; /* 00 2 fc * */
6080 + u16 dur ACX_PACKED; /* 02 2 Duration */
6081 + u8 da[6] ACX_PACKED; /* 04 6 Destination Address * */
6082 + u8 sa[6] ACX_PACKED; /* 0A 6 Source Address * */
6083 + u8 bssid[6] ACX_PACKED; /* 10 6 BSSID * */
6084 + u16 seq ACX_PACKED; /* 16 2 Sequence Control */
6086 + /* nn n Supported Rates * */
6087 + u8 variable[0x44 - 2-2-6-6-6-2] ACX_PACKED;
6088 +} acx111_template_probereq_t;
6090 +typedef struct acx_template_proberesp {
6091 + u16 size ACX_PACKED;
6092 + u16 fc ACX_PACKED; /* 00 2 fc * (bits [15:12] and [10:8] per 802.11 section 7.1.3.1) */
6093 + u16 dur ACX_PACKED; /* 02 2 Duration */
6094 + u8 da[6] ACX_PACKED; /* 04 6 Destination Address */
6095 + u8 sa[6] ACX_PACKED; /* 0A 6 Source Address */
6096 + u8 bssid[6] ACX_PACKED; /* 10 6 BSSID */
6097 + u16 seq ACX_PACKED; /* 16 2 Sequence Control */
6098 + u8 timestamp[8] ACX_PACKED;/* 18 8 Timestamp */
6099 + u16 beacon_interval ACX_PACKED; /* 20 2 Beacon Interval * */
6100 + u16 cap ACX_PACKED; /* 22 2 Capability Information * */
6102 + /* nn n Supported Rates * */
6103 + /* nn 1 DS Parameter Set * */
6104 + u8 variable[0x54 - 2-2-6-6-6-2-8-2-2] ACX_PACKED;
6105 +} acx_template_proberesp_t;
6106 +#define acx_template_beacon_t acx_template_proberesp_t
6107 +#define acx_template_beacon acx_template_proberesp
6109 +typedef struct acx_template_nullframe {
6110 + u16 size ACX_PACKED;
6111 + struct wlan_hdr_a3 hdr ACX_PACKED;
6112 +} acx_template_nullframe_t;
6116 +** JOIN command structure
6118 +** as opposed to acx100, acx111 dtim interval is AFTER rates_basic111.
6119 +** NOTE: took me about an hour to get !@#$%^& packing right --> struct packing is eeeeevil... */
6120 +typedef struct acx_joinbss {
6121 + u8 bssid[ETH_ALEN] ACX_PACKED;
6122 + u16 beacon_interval ACX_PACKED;
6125 + u8 dtim_interval ACX_PACKED;
6126 + u8 rates_basic ACX_PACKED;
6127 + u8 rates_supported ACX_PACKED;
6128 + } acx100 ACX_PACKED;
6130 + u16 rates_basic ACX_PACKED;
6131 + u8 dtim_interval ACX_PACKED;
6132 + } acx111 ACX_PACKED;
6134 + u8 genfrm_txrate ACX_PACKED; /* generated frame (bcn, proberesp, RTS, PSpoll) tx rate */
6135 + u8 genfrm_mod_pre ACX_PACKED; /* generated frame modulation/preamble:
6136 + ** bit7: PBCC, bit6: OFDM (else CCK/DQPSK/DBPSK)
6137 + ** bit5: short pre */
6138 + u8 macmode ACX_PACKED; /* BSS Type, must be one of ACX_MODE_xxx */
6139 + u8 channel ACX_PACKED;
6140 + u8 essid_len ACX_PACKED;
6141 + char essid[IW_ESSID_MAX_SIZE] ACX_PACKED;
6144 +#define JOINBSS_RATES_1 0x01
6145 +#define JOINBSS_RATES_2 0x02
6146 +#define JOINBSS_RATES_5 0x04
6147 +#define JOINBSS_RATES_11 0x08
6148 +#define JOINBSS_RATES_22 0x10
6150 +/* Looks like missing bits are used to indicate 11g rates!
6151 +** (it follows from the fact that constants below match 1:1 to RATE111_nn)
6152 +** This was actually seen! Look at that Assoc Request sent by acx111,
6153 +** it _does_ contain 11g rates in basic set:
6154 +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
6155 +01:30:20.074425 Authentication (Open System)-1: Succesful
6156 +01:30:20.076539 Authentication (Open System)-2:
6157 +01:30:20.076620 Acknowledgment
6158 +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]
6159 +01:30:20.122413 Assoc Response AID(1) :: Succesful
6160 +01:30:20.122679 Acknowledgment
6161 +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
6163 +#define JOINBSS_RATES_BASIC111_1 0x0001
6164 +#define JOINBSS_RATES_BASIC111_2 0x0002
6165 +#define JOINBSS_RATES_BASIC111_5 0x0004
6166 +#define JOINBSS_RATES_BASIC111_11 0x0020
6167 +#define JOINBSS_RATES_BASIC111_22 0x0100
6170 +/***********************************************************************
6172 +typedef struct mem_read_write {
6173 + u16 addr ACX_PACKED;
6174 + u16 type ACX_PACKED; /* 0x0 int. RAM / 0xffff MAC reg. / 0x81 PHY RAM / 0x82 PHY reg. */
6175 + u32 len ACX_PACKED;
6176 + u32 data ACX_PACKED;
6177 +} mem_read_write_t;
6179 +typedef struct firmware_image {
6180 + u32 chksum ACX_PACKED;
6181 + u32 size ACX_PACKED;
6182 + u8 data[1] ACX_PACKED; /* the byte array of the actual firmware... */
6183 +} firmware_image_t;
6185 +typedef struct acx_cmd_radioinit {
6186 + u32 offset ACX_PACKED;
6187 + u32 len ACX_PACKED;
6188 +} acx_cmd_radioinit_t;
6190 +typedef struct acx100_ie_wep_options {
6191 + u16 type ACX_PACKED;
6192 + u16 len ACX_PACKED;
6193 + u16 NumKeys ACX_PACKED; /* max # of keys */
6194 + u8 WEPOption ACX_PACKED; /* 0 == decrypt default key only, 1 == override decrypt */
6195 + u8 Pad ACX_PACKED; /* used only for acx111 */
6196 +} acx100_ie_wep_options_t;
6198 +typedef struct ie_dot11WEPDefaultKey {
6199 + u16 type ACX_PACKED;
6200 + u16 len ACX_PACKED;
6201 + u8 action ACX_PACKED;
6202 + u8 keySize ACX_PACKED;
6203 + u8 defaultKeyNum ACX_PACKED;
6204 + u8 key[29] ACX_PACKED; /* check this! was Key[19]. */
6205 +} ie_dot11WEPDefaultKey_t;
6207 +typedef struct acx111WEPDefaultKey {
6208 + u8 MacAddr[ETH_ALEN] ACX_PACKED;
6209 + u16 action ACX_PACKED; /* NOTE: this is a u16, NOT a u8!! */
6210 + u16 reserved ACX_PACKED;
6211 + u8 keySize ACX_PACKED;
6212 + u8 type ACX_PACKED;
6213 + u8 index ACX_PACKED;
6214 + u8 defaultKeyNum ACX_PACKED;
6215 + u8 counter[6] ACX_PACKED;
6216 + u8 key[32] ACX_PACKED; /* up to 32 bytes (for TKIP!) */
6217 +} acx111WEPDefaultKey_t;
6219 +typedef struct ie_dot11WEPDefaultKeyID {
6220 + u16 type ACX_PACKED;
6221 + u16 len ACX_PACKED;
6222 + u8 KeyID ACX_PACKED;
6223 +} ie_dot11WEPDefaultKeyID_t;
6225 +typedef struct acx100_cmd_wep_mgmt {
6226 + u8 MacAddr[ETH_ALEN] ACX_PACKED;
6227 + u16 Action ACX_PACKED;
6228 + u16 KeySize ACX_PACKED;
6229 + u8 Key[29] ACX_PACKED; /* 29*8 == 232bits == WEP256 */
6230 +} acx100_cmd_wep_mgmt_t;
6232 +typedef struct defaultkey {
6236 +typedef struct acx_ie_generic {
6237 + u16 type ACX_PACKED;
6238 + u16 len ACX_PACKED;
6240 + /* struct wep wp ACX_PACKED; */
6241 + /* Association ID IE: just a 16bit value: */
6243 + /* UNUSED? struct defaultkey dkey ACX_PACKED; */
6244 + /* generic member for quick implementation of commands */
6245 + u8 bytes[32] ACX_PACKED;
6247 +} acx_ie_generic_t;
6249 +/* Config Option structs */
6251 +typedef struct co_antennas {
6252 + u8 type ACX_PACKED;
6253 + u8 len ACX_PACKED;
6254 + u8 list[2] ACX_PACKED;
6257 +typedef struct co_powerlevels {
6258 + u8 type ACX_PACKED;
6259 + u8 len ACX_PACKED;
6260 + u16 list[8] ACX_PACKED;
6261 +} co_powerlevels_t;
6263 +typedef struct co_datarates {
6264 + u8 type ACX_PACKED;
6265 + u8 len ACX_PACKED;
6266 + u8 list[8] ACX_PACKED;
6269 +typedef struct co_domains {
6270 + u8 type ACX_PACKED;
6271 + u8 len ACX_PACKED;
6272 + u8 list[6] ACX_PACKED;
6275 +typedef struct co_product_id {
6276 + u8 type ACX_PACKED;
6277 + u8 len ACX_PACKED;
6278 + u8 list[128] ACX_PACKED;
6281 +typedef struct co_manuf_id {
6282 + u8 type ACX_PACKED;
6283 + u8 len ACX_PACKED;
6284 + u8 list[128] ACX_PACKED;
6287 +typedef struct co_fixed {
6288 + u8 type ACX_PACKED;
6289 + u8 len ACX_PACKED;
6290 + char NVSv[8] ACX_PACKED;
6291 + u8 MAC[6] ACX_PACKED;
6292 + u16 probe_delay ACX_PACKED;
6293 + u32 eof_memory ACX_PACKED;
6294 + u8 dot11CCAModes ACX_PACKED;
6295 + u8 dot11Diversity ACX_PACKED;
6296 + u8 dot11ShortPreambleOption ACX_PACKED;
6297 + u8 dot11PBCCOption ACX_PACKED;
6298 + u8 dot11ChannelAgility ACX_PACKED;
6299 + u8 dot11PhyType ACX_PACKED;
6300 +/* u8 dot11TempType ACX_PACKED;
6301 + u8 num_var ACX_PACKED; seems to be erased */
6305 +typedef struct acx111_ie_configoption {
6306 + co_fixed_t configoption_fixed ACX_PACKED;
6307 + co_antennas_t antennas ACX_PACKED;
6308 + co_powerlevels_t power_levels ACX_PACKED;
6309 + co_datarates_t data_rates ACX_PACKED;
6310 + co_domains_t domains ACX_PACKED;
6311 + co_product_id_t product_id ACX_PACKED;
6312 + co_manuf_t manufacturer ACX_PACKED;
6313 +} acx111_ie_configoption_t;
6316 +/***********************************************************************
6318 +#define CHECK_SIZEOF(type,size) { \
6319 + extern void BUG_bad_size_for_##type(void); \
6320 + if (sizeof(type)!=(size)) BUG_bad_size_for_##type(); \
6324 +acx_struct_size_check(void)
6326 + //CHECK_SIZEOF(txdesc_t, 0x30);
6327 + CHECK_SIZEOF(acx100_ie_memconfigoption_t, 24);
6328 + CHECK_SIZEOF(acx100_ie_queueconfig_t, 0x20);
6329 + //CHECK_SIZEOF(acx_joinbss_t, 0x30);
6333 +/*============================================================================*
6335 + *============================================================================*/
6336 +extern const u8 bitpos2ratebyte[];
6337 +extern const u8 bitpos2rate100[];
6339 +extern const u8 reg_domain_ids[];
6340 +extern const u8 reg_domain_ids_len;
6342 +extern const struct iw_handler_def acx_ioctl_handler_def;
6343 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
6344 --- linux-2.6.14-omap2/drivers/net/wireless/tiacx/cfi.c 1970-01-01 02:00:00.000000000 +0200
6345 +++ linux-h6300-omap2-2.6.14.3/drivers/net/wireless/tiacx/cfi.c 2005-10-29 22:02:44.000000000 +0300
6347 +/***********************************************************************
6348 +** Copyright (C) 2003 ACX100 Open Source Project
6350 +** The contents of this file are subject to the Mozilla Public
6351 +** License Version 1.1 (the "License"); you may not use this file
6352 +** except in compliance with the License. You may obtain a copy of
6353 +** the License at http://www.mozilla.org/MPL/
6355 +** Software distributed under the License is distributed on an "AS
6356 +** IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
6357 +** implied. See the License for the specific language governing
6358 +** rights and limitations under the License.
6360 +** Alternatively, the contents of this file may be used under the
6361 +** terms of the GNU Public License version 2 (the "GPL"), in which
6362 +** case the provisions of the GPL are applicable instead of the
6363 +** above. If you wish to allow the use of your version of this file
6364 +** only under the terms of the GPL and not to allow others to use
6365 +** your version of this file under the MPL, indicate your decision
6366 +** by deleting the provisions above and replace them with the notice
6367 +** and other provisions required by the GPL. If you do not delete
6368 +** the provisions above, a recipient may use your version of this
6369 +** file under either the MPL or the GPL.
6370 +** ---------------------------------------------------------------------
6371 +** Inquiries regarding the ACX100 Open Source Project can be
6372 +** made directly to:
6374 +** acx100-users@lists.sf.net
6375 +** http://acx100.sf.net
6376 +** ---------------------------------------------------------------------
6380 +#include <linux/config.h>
6381 +#include <linux/version.h>
6382 +#include <linux/kernel.h>
6383 +#include <linux/module.h>
6384 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
6385 +#include <linux/moduleparam.h>
6387 +#include <linux/sched.h>
6388 +#include <linux/types.h>
6389 +#include <linux/skbuff.h>
6390 +#include <linux/slab.h>
6391 +#include <linux/if_arp.h>
6392 +#include <linux/rtnetlink.h>
6393 +#include <linux/wireless.h>
6394 +#if WIRELESS_EXT >= 13
6395 +#include <net/iw_handler.h>
6397 +#include <linux/device.h>
6398 +#include <linux/netdevice.h>
6399 +#include <linux/etherdevice.h>
6400 +#include <linux/ioport.h>
6401 +#include <linux/pm.h>
6402 +#include <linux/vmalloc.h>
6404 +#include <asm/hardware.h>
6405 +#include <asm/mach-types.h>
6406 +#include <asm/sizes.h>
6407 +#include <asm/arch/tc.h>
6409 +#include <asm/io.h>
6410 +#include <asm/irq.h>
6411 +#include <asm/arch/gpio.h>
6412 +#include <asm/arch/pca9535.h>
6416 +#define CARDNAME "tnetw1100b"
6418 +/*================================================================*/
6419 +/* Local Constants */
6420 +#define PCI_TYPE (PCI_USES_MEM | PCI_ADDR0 | PCI_NO_ACPI_WAKE)
6421 +#define PCI_ACX100_REGION1 0x01
6422 +#define PCI_ACX100_REGION1_SIZE 0x1000 /* Memory size - 4K bytes */
6423 +#define PCI_ACX100_REGION2 0x02
6424 +#define PCI_ACX100_REGION2_SIZE 0x10000 /* Memory size - 64K bytes */
6426 +#define PCI_ACX111_REGION1 0x00
6427 +#define PCI_ACX111_REGION1_SIZE 0x2000 /* Memory size - 8K bytes */
6428 +#define PCI_ACX111_REGION2 0x01
6429 +#define PCI_ACX111_REGION2_SIZE 0x20000 /* Memory size - 128K bytes */
6431 +/* Texas Instruments Vendor ID */
6432 +#define PCI_VENDOR_ID_TI 0x104c
6434 +/* ACX100 22Mb/s WLAN controller */
6435 +#define PCI_DEVICE_ID_TI_TNETW1100A 0x8400
6436 +#define PCI_DEVICE_ID_TI_TNETW1100B 0x8401
6438 +/* ACX111 54Mb/s WLAN controller */
6439 +#define PCI_DEVICE_ID_TI_TNETW1130 0x9066
6441 +/* PCI Class & Sub-Class code, Network-'Other controller' */
6442 +#define PCI_CLASS_NETWORK_OTHERS 0x280
6444 +#define CARD_EEPROM_ID_SIZE 6
6445 +#define MAX_IRQLOOPS_PER_JIFFY (20000/HZ) /* a la orinoco.c */
6448 +/***********************************************************************
6450 +static void acx_l_disable_irq(wlandevice_t *priv);
6451 +static void acx_l_enable_irq(wlandevice_t *priv);
6452 +static int acx_drv_probe(struct device *dev);
6453 +static int acx_remove(struct device *dev);
6455 +static inline void test(wlandevice_t *priv);
6458 +static int acx_suspend(struct device *dev, pm_message_t state, u32 level);
6459 +static int acx_resume(struct device *dev, u32 level);
6462 +static void acx_i_tx_timeout(netdevice_t *dev);
6463 +static struct net_device_stats *acx_e_get_stats(netdevice_t *dev);
6464 +static struct iw_statistics *acx_e_get_wireless_stats(netdevice_t *dev);
6466 +static irqreturn_t acx_i_interrupt(int irq, void *dev_id, struct pt_regs *regs);
6467 +static void acx_i_set_multicast_list(netdevice_t *dev);
6469 +static int acx_e_open(netdevice_t *dev);
6470 +static int acx_e_close(netdevice_t *dev);
6471 +static void acx_s_up(netdevice_t *dev);
6472 +static void acx_s_down(netdevice_t *dev);
6475 +/***********************************************************************
6480 +/* #define INLINE_IO static */
6481 +#define INLINE_IO static inline
6484 +acx_read_reg32(wlandevice_t *priv, unsigned int offset)
6486 +#if ACX_IO_WIDTH == 32
6487 + return readl((u8 *)priv->iobase + priv->io[offset]);
6489 + return readw((u8 *)priv->iobase + priv->io[offset])
6490 + + (readw((u8 *)priv->iobase + priv->io[offset] + 2) << 16);
6495 +acx_read_reg16(wlandevice_t *priv, unsigned int offset)
6497 + return readw((u8 *)priv->iobase + priv->io[offset]);
6501 +acx_read_reg8(wlandevice_t *priv, unsigned int offset)
6503 + return readb((u8 *)priv->iobase + priv->io[offset]);
6507 +acx_write_reg32(wlandevice_t *priv, unsigned int offset, u32 val)
6509 +#if ACX_IO_WIDTH == 32
6510 + writel(val, (u8 *)priv->iobase + priv->io[offset]);
6512 + writew(val & 0xffff, (u8 *)priv->iobase + priv->io[offset]);
6513 + writew(val >> 16, (u8 *)priv->iobase + priv->io[offset] + 2);
6518 +acx_write_reg16(wlandevice_t *priv, unsigned int offset, u16 val)
6520 + writew(val, (u8 *)priv->iobase + priv->io[offset]);
6524 +acx_write_reg8(wlandevice_t *priv, unsigned int offset, u8 val)
6526 + writeb(val, (u8 *)priv->iobase + priv->io[offset]);
6529 +/* Handle PCI posting properly:
6530 + * Make sure that writes reach the adapter in case they require to be executed
6531 + * *before* the next write, by reading a random (and safely accessible) register.
6532 + * This call has to be made if there is no read following (which would flush the data
6533 + * to the adapter), yet the written data has to reach the adapter immediately. */
6535 +acx_write_flush(wlandevice_t *priv)
6537 + /* readb(priv->iobase + priv->io[IO_ACX_INFO_MAILBOX_OFFS]); */
6538 + /* faster version (accesses the first register, IO_ACX_SOFT_RESET,
6539 + * which should also be safe): */
6540 + readb(priv->iobase);
6544 +INLINE_IO void acx_mailbox_fill(wlandevice_t *priv, unsigned int offset, unsigned char val, int len){
6545 + unsigned int addr = offset;
6546 + unsigned int buff = 0;
6548 + // Fill the buffer
6549 + memset((void *) &buff, val, len);
6551 + acx_write_reg32(priv, IO_ACX_SLV_END_CTL, 0);
6552 + acx_write_reg32(priv, IO_ACX_SLV_MEM_CTL, 0x00010000);
6553 + acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR, addr);
6557 + acx_write_reg32(priv, IO_ACX_SLV_MEM_DATA,buff);
6558 + acx_write_flush(priv);
6566 + memset((void *) &buff, val , len);
6568 + acx_write_reg32(priv, IO_ACX_SLV_MEM_DATA,buff);
6569 + acx_write_flush(priv);
6574 +INLINE_IO void acx_mailbox_write(wlandevice_t *priv, unsigned int offset, void *cmd, int len){
6575 + unsigned char *buff = (unsigned char *) cmd;
6576 + unsigned int addr = offset;
6577 + unsigned int val = 0;
6583 + acx_write_reg32(priv, IO_ACX_SLV_END_CTL, 0);
6584 + acx_write_reg32(priv, IO_ACX_SLV_MEM_CTL, 0x00010000);
6585 + acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR, addr);
6588 + acx_write_reg32(priv, IO_ACX_SLV_MEM_DATA,*((unsigned int *) buff));
6589 + acx_write_flush(priv);
6598 + memcpy((void *) &val, (void *) buff, len);
6600 + acx_write_reg32(priv, IO_ACX_SLV_MEM_DATA,val);
6601 + acx_write_flush(priv);
6605 +INLINE_IO void acx_mailbox_read(wlandevice_t *priv, unsigned int offset, void *data, int len){
6606 + unsigned char *buff = (unsigned char *) data;
6607 + unsigned int addr = offset;
6608 + unsigned int value = 0;
6614 + acx_write_reg32(priv, IO_ACX_SLV_END_CTL, 0);
6615 + acx_write_reg32(priv, IO_ACX_SLV_MEM_CTL, 0x00010000);
6616 + acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR, addr);
6620 + *((unsigned int *) buff) = acx_read_reg32(priv, IO_ACX_SLV_MEM_DATA);
6628 + value = acx_read_reg32(priv, IO_ACX_SLV_MEM_DATA);
6629 + memcpy((void *) buff, (void *) &value, len);
6633 +/***********************************************************************
6635 +static const char name_acx100[] = "ACX100";
6636 +static const char name_tnetw1100a[] = "TNETW1100A";
6637 +static const char name_tnetw1100b[] = "TNETW1100B";
6639 +static const char name_acx111[] = "ACX111";
6640 +static const char name_tnetw1130[] = "TNETW1130";
6642 +struct device_driver acx_driver = {
6644 + .bus = &platform_bus_type,
6645 + .probe = acx_drv_probe,
6646 + .remove = acx_remove,
6648 + .suspend = acx_suspend,
6649 + .resume = acx_resume
6653 +typedef struct acx_device {
6654 + netdevice_t *newest;
6657 +/* if this driver was only about PCI devices, then we probably wouldn't
6658 + * need this linked list.
6659 + * But if we want to register ALL kinds of devices in one global list,
6660 + * then we need it and need to maintain it properly. */
6661 +static struct acx_device root_acx_dev = {
6664 +DECLARE_MUTEX(root_acx_dev_sem);
6667 +/***********************************************************************
6669 +static inline txdesc_t*
6670 +get_txdesc(wlandevice_t* priv, int index)
6672 + return (txdesc_t*) (((u8*)priv->txdesc_start) + index * priv->txdesc_size);
6675 +static inline txdesc_t*
6676 +move_txdesc(wlandevice_t* priv, txdesc_t* txdesc, int inc)
6678 + return (txdesc_t*) (((u8*)txdesc) + inc * priv->txdesc_size);
6681 +static txhostdesc_t*
6682 +acx_get_txhostdesc(wlandevice_t* priv, txdesc_t* txdesc)
6684 + int index = (u8*)txdesc - (u8*)priv->txdesc_start;
6685 + if (ACX_DEBUG && (index % priv->txdesc_size)) {
6686 + printk("bad txdesc ptr %p\n", txdesc);
6689 + index /= priv->txdesc_size;
6690 + if (ACX_DEBUG && (index >= TX_CNT)) {
6691 + printk("bad txdesc ptr %p\n", txdesc);
6694 + return &priv->txhostdesc_start[index*2];
6698 +acx_get_txc(wlandevice_t* priv, txdesc_t* txdesc)
6700 + int index = (u8*)txdesc - (u8*)priv->txdesc_start;
6701 + if (ACX_DEBUG && (index % priv->txdesc_size)) {
6702 + printk("bad txdesc ptr %p\n", txdesc);
6705 + index /= priv->txdesc_size;
6706 + if (ACX_DEBUG && (index >= TX_CNT)) {
6707 + printk("bad txdesc ptr %p\n", txdesc);
6710 + return priv->txc[index];
6714 +acx_put_txc(wlandevice_t* priv, txdesc_t* txdesc, client_t* c)
6716 + int index = (u8*)txdesc - (u8*)priv->txdesc_start;
6717 + if (ACX_DEBUG && (index % priv->txdesc_size)) {
6718 + printk("bad txdesc ptr %p\n", txdesc);
6721 + index /= priv->txdesc_size;
6722 + if (ACX_DEBUG && (index >= TX_CNT)) {
6723 + printk("bad txdesc ptr %p\n", txdesc);
6726 + priv->txc[index] = c;
6729 +/***********************************************************************
6730 +** EEPROM and PHY read/write helpers
6732 +/***********************************************************************
6733 +** acx_read_eeprom_offset
6735 +** Function called to read an octet in the EEPROM.
6737 +** This function is used by acx_probe_pci to check if the
6738 +** connected card is a legal one or not.
6741 +** priv ptr to wlandevice structure
6742 +** addr address to read in the EEPROM
6743 +** charbuf ptr to a char. This is where the read octet
6747 +** zero (0) - failed
6748 +** one (1) - success
6750 +** NOT ADAPTED FOR ACX111!!
6753 +acx_read_eeprom_offset(wlandevice_t *priv, u32 addr, u8 *charbuf)
6755 + int result = NOT_OK;
6758 + acx_write_reg32(priv, IO_ACX_EEPROM_CFG, 0);
6759 + acx_write_reg32(priv, IO_ACX_EEPROM_ADDR, addr);
6760 + acx_write_flush(priv);
6761 + acx_write_reg32(priv, IO_ACX_EEPROM_CTL, 2);
6764 + while (acx_read_reg16(priv, IO_ACX_EEPROM_CTL)) {
6765 + /* scheduling away instead of CPU burning loop
6766 + * doesn't seem to work here at all:
6767 + * awful delay, sometimes also failure.
6768 + * Doesn't matter anyway (only small delay). */
6769 + if (unlikely(!--count)) {
6770 + printk("%s: timeout waiting for EEPROM read\n",
6771 + priv->netdev->name);
6776 + *charbuf = acx_read_reg8(priv, IO_ACX_EEPROM_DATA);
6777 + acxlog(L_DEBUG, "EEPROM at 0x%04X = 0x%02X\n", addr, *charbuf);
6785 +/***********************************************************************
6786 +** Dummy EEPROM read? why?!
6789 +acx_read_eeprom_area(wlandevice_t *priv)
6794 + for (offs = 0x8c; offs < 0xb9; offs++) {
6795 + acx_read_eeprom_offset(priv, offs, &tmp[offs - 0x8c]);
6801 +/***********************************************************************
6802 +** We don't lock hw accesses here since we never r/w eeprom in IRQ
6803 +** Note: this function sleeps only because of GFP_KERNEL alloc
6807 +acx_s_write_eeprom_offset(wlandevice_t *priv, u32 addr, u32 len, const u8 *charbuf)
6809 + u8 *data_verify = NULL;
6810 + unsigned long flags;
6812 + int result = NOT_OK;
6815 + printk("acx: WARNING! I would write to EEPROM now. "
6816 + "Since I really DON'T want to unless you know "
6817 + "what you're doing (THIS CODE WILL PROBABLY "
6818 + "NOT WORK YET!), I will abort that now. And "
6819 + "definitely make sure to make a "
6820 + "/proc/driver/acx_wlan0_eeprom backup copy first!!! "
6821 + "(the EEPROM content includes the PCI config header!! "
6822 + "If you kill important stuff, then you WILL "
6823 + "get in trouble and people DID get in trouble already)\n");
6828 + data_verify = kmalloc(len, GFP_KERNEL);
6829 + if (!data_verify) {
6833 + /* first we need to enable the OE (EEPROM Output Enable) GPIO line
6834 + * to be able to write to the EEPROM.
6835 + * NOTE: an EEPROM writing success has been reported,
6836 + * but you probably have to modify GPIO_OUT, too,
6837 + * and you probably need to activate a different GPIO
6838 + * line instead! */
6839 + gpio_orig = acx_read_reg16(priv, IO_ACX_GPIO_OE);
6840 + acx_write_reg16(priv, IO_ACX_GPIO_OE, gpio_orig & ~1);
6841 + acx_write_flush(priv);
6843 + /* ok, now start writing the data out */
6844 + for (i = 0; i < len; i++) {
6845 + acx_write_reg32(priv, IO_ACX_EEPROM_CFG, 0);
6846 + acx_write_reg32(priv, IO_ACX_EEPROM_ADDR, addr + i);
6847 + acx_write_reg32(priv, IO_ACX_EEPROM_DATA, *(charbuf + i));
6848 + acx_write_flush(priv);
6849 + acx_write_reg32(priv, IO_ACX_EEPROM_CTL, 1);
6851 + while (acx_read_reg16(priv, IO_ACX_EEPROM_CTL)) {
6852 + if (unlikely(++count > 0xffff)) {
6853 + printk("WARNING, DANGER!!! "
6854 + "Timeout waiting for EEPROM write\n");
6860 + /* disable EEPROM writing */
6861 + acx_write_reg16(priv, IO_ACX_GPIO_OE, gpio_orig);
6862 + acx_write_flush(priv);
6864 + /* now start a verification run */
6866 + for (i = 0; i < len; i++) {
6867 + acx_write_reg32(priv, IO_ACX_EEPROM_CFG, 0);
6868 + acx_write_reg32(priv, IO_ACX_EEPROM_ADDR, addr + i);
6869 + acx_write_flush(priv);
6870 + acx_write_reg32(priv, IO_ACX_EEPROM_CTL, 2);
6872 + while (acx_read_reg16(priv, IO_ACX_EEPROM_CTL)) {
6873 + if (unlikely(!--count)) {
6874 + printk("timeout waiting for EEPROM read\n");
6879 + data_verify[i] = acx_read_reg16(priv, IO_ACX_EEPROM_DATA);
6882 + if (0 == memcmp(charbuf, data_verify, len))
6883 + result = OK; /* read data matches, success */
6886 + kfree(data_verify);
6890 +#endif /* UNUSED */
6893 +/***********************************************************************
6894 +** acxpci_s_read_phy_reg
6896 +** Messing with rx/tx disabling and enabling here
6897 +** (acx_write_reg32(priv, IO_ACX_ENABLE, 0b000000xx)) kills traffic
6900 +acxpci_s_read_phy_reg(wlandevice_t *priv, u32 reg, u8 *charbuf)
6902 + int result = NOT_OK;
6907 + acx_write_reg32(priv, IO_ACX_PHY_ADDR, reg);
6908 + acx_write_flush(priv);
6909 + acx_write_reg32(priv, IO_ACX_PHY_CTL, 2);
6912 + while (acx_read_reg32(priv, IO_ACX_PHY_CTL)) {
6913 + /* scheduling away instead of CPU burning loop
6914 + * doesn't seem to work here at all:
6915 + * awful delay, sometimes also failure.
6916 + * Doesn't matter anyway (only small delay). */
6917 + if (unlikely(!--count)) {
6918 + printk("%s: timeout waiting for phy read\n",
6919 + priv->netdev->name);
6925 + acxlog(L_DEBUG, "count was %u\n", count);
6926 + *charbuf = acx_read_reg8(priv, IO_ACX_PHY_DATA);
6928 + acxlog(L_DEBUG, "radio PHY at 0x%04X = 0x%02X\n", *charbuf, reg);
6930 + goto fail; /* silence compiler warning */
6937 +/***********************************************************************
6940 +acxpci_s_write_phy_reg(wlandevice_t *priv, u32 reg, u8 value)
6944 + /* FIXME: we didn't use 32bit access here since mprusko said that
6945 + * it results in distorted sensitivity on his card (huh!?!?
6946 + * doesn't happen with my setup...)
6947 + * But with the access reordering and flushing it
6948 + * shouldn't happen any more...
6949 + * FIXME: which radio is in the problematic card? My working one
6951 + acx_write_reg32(priv, IO_ACX_PHY_DATA, value);
6952 + acx_write_reg32(priv, IO_ACX_PHY_ADDR, reg);
6953 + acx_write_flush(priv);
6954 + acx_write_reg32(priv, IO_ACX_PHY_CTL, 1);
6955 + acx_write_flush(priv);
6956 + acxlog(L_DEBUG, "radio PHY write 0x%02X at 0x%04X\n", value, reg);
6963 +#define NO_AUTO_INCREMENT 1
6965 +/***********************************************************************
6968 +** Write the firmware image into the card.
6971 +** priv wlan device structure
6972 +** apfw_image firmware image.
6975 +** 1 firmware image corrupted
6979 +acx_s_write_fw(wlandevice_t *priv, const firmware_image_t *apfw_image, u32 offset)
6983 + /* we skip the first four bytes which contain the control sum */
6984 + const u8 *image = (u8*)apfw_image + 4;
6986 + /* start the image checksum by adding the image size value */
6987 + sum = image[0]+image[1]+image[2]+image[3];
6990 + acx_write_reg32(priv, IO_ACX_SLV_END_CTL, 0);
6992 +#if NO_AUTO_INCREMENT
6993 + acxlog(L_INIT, "not using auto increment for firmware loading\n");
6994 + acx_write_reg32(priv, IO_ACX_SLV_MEM_CTL, 0); /* use basic mode */
6996 + acx_write_reg32(priv, IO_ACX_SLV_MEM_CTL, 1); /* use autoincrement mode */
6997 + acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR, offset); /* configure start address */
6998 + acx_write_flush(priv);
7002 + size = le32_to_cpu(apfw_image->size) & (~3);
7004 + while (likely(len < size)) {
7005 + v32 = be32_to_cpu(*(u32*)image);
7006 + sum += image[0]+image[1]+image[2]+image[3];
7010 +#if NO_AUTO_INCREMENT
7011 + acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR, offset + len - 4);
7012 + acx_write_flush(priv);
7014 + acx_write_reg32(priv, IO_ACX_SLV_MEM_DATA, v32);
7017 + acxlog(L_DEBUG, "%s: firmware written\n", __func__);
7019 + /* compare our checksum with the stored image checksum */
7020 + return (sum != le32_to_cpu(apfw_image->chksum));
7024 +/***********************************************************************
7025 +** acx_s_validate_fw
7027 +** Compare the firmware image given with
7028 +** the firmware image written into the card.
7031 +** priv wlan device structure
7032 +** apfw_image firmware image.
7035 +** NOT_OK firmware image corrupted or not correctly written
7039 +acx_s_validate_fw(wlandevice_t *priv, const firmware_image_t *apfw_image,
7042 + u32 v32, w32, sum;
7045 + /* we skip the first four bytes which contain the control sum */
7046 + const u8 *image = (u8*)apfw_image + 4;
7048 + /* start the image checksum by adding the image size value */
7049 + sum = image[0]+image[1]+image[2]+image[3];
7052 + acx_write_reg32(priv, IO_ACX_SLV_END_CTL, 0);
7054 +#if NO_AUTO_INCREMENT
7055 + acx_write_reg32(priv, IO_ACX_SLV_MEM_CTL, 0); /* use basic mode */
7057 + acx_write_reg32(priv, IO_ACX_SLV_MEM_CTL, 1); /* use autoincrement mode */
7058 + acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR, offset); /* configure start address */
7062 + size = le32_to_cpu(apfw_image->size) & (~3);
7064 + while (likely(len < size)) {
7065 + v32 = be32_to_cpu(*(u32*)image);
7069 +#if NO_AUTO_INCREMENT
7070 + acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR, offset + len - 4);
7072 + w32 = acx_read_reg32(priv, IO_ACX_SLV_MEM_DATA);
7074 + if (unlikely(w32 != v32)) {
7075 + printk("acx: FATAL: firmware upload: "
7076 + "data parts at offset %d don't match (0x%08X vs. 0x%08X)! "
7077 + "I/O timing issues or defective memory, with DWL-xx0+? "
7078 + "ACX_IO_WIDTH=16 may help. Please report\n",
7084 + sum += (u8)w32 + (u8)(w32>>8) + (u8)(w32>>16) + (u8)(w32>>24);
7087 + /* sum control verification */
7088 + if (result != NOT_OK) {
7089 + if (sum != le32_to_cpu(apfw_image->chksum)) {
7090 + printk("acx: FATAL: firmware upload: "
7091 + "checksums don't match!\n");
7100 +/***********************************************************************
7104 +** wlandevice: private device that contains card device
7112 +acx_s_upload_fw(wlandevice_t *priv)
7114 + firmware_image_t *apfw_image = NULL;
7118 + char filename[sizeof("tiacx1NNcNN")];
7122 + /* Try combined, then main image */
7123 + priv->need_radio_fw = 0;
7124 + sprintf(filename, "tiacx1%02dc%02X",
7125 + IS_ACX111(priv)*11, priv->radio_type);
7127 + apfw_image = acx_s_read_fw(priv->dev, filename, &size);
7128 + if (!apfw_image) {
7129 + priv->need_radio_fw = 1;
7130 + filename[sizeof("tiacx1NN")-1] = '\0';
7131 + apfw_image = acx_s_read_fw(priv->dev, filename, &size);
7132 + if (!apfw_image) {
7138 + for (try = 1; try <= 5; try++) {
7139 + res = acx_s_write_fw(priv, apfw_image, 0);
7140 + acxlog(L_DEBUG|L_INIT, "acx_write_fw (main/combined):%d\n", res);
7142 + res = acx_s_validate_fw(priv, apfw_image, 0);
7143 + acxlog(L_DEBUG|L_INIT, "acx_validate_fw "
7144 + "(main/combined):%d\n", res);
7148 + SET_BIT(priv->dev_state_mask, ACX_STATE_FW_LOADED);
7151 + printk("acx: firmware upload attempt #%d FAILED, "
7152 + "retrying...\n", try);
7153 + acx_s_msleep(1000); /* better wait for a while... */
7156 + vfree((void *) apfw_image);
7163 +/***********************************************************************
7164 +** acx_s_upload_radio
7166 +** Uploads the appropriate radio module firmware
7170 +acx_s_upload_radio(wlandevice_t *priv)
7172 + acx_ie_memmap_t mm;
7173 + firmware_image_t *radio_image = NULL;
7174 + acx_cmd_radioinit_t radioinit;
7179 + char filename[sizeof("tiacx1NNrNN")];
7181 + if (!priv->need_radio_fw) return OK;
7185 + acx_s_interrogate(priv, &mm, ACX1xx_IE_MEMORY_MAP);
7186 + offset = le32_to_cpu(mm.CodeEnd);
7188 + sprintf(filename, "tiacx1%02dr%02X",
7189 + IS_ACX111(priv)*11,
7190 + priv->radio_type);
7191 + radio_image = acx_s_read_fw(priv->dev, filename, &size);
7192 + if (!radio_image) {
7193 + printk("acx: can't load radio module '%s'\n", filename);
7197 + acx_s_issue_cmd(priv, ACX1xx_CMD_SLEEP, NULL, 0);
7199 + for (try = 1; try <= 5; try++) {
7200 + res = acx_s_write_fw(priv, radio_image, offset);
7201 + acxlog(L_DEBUG|L_INIT, "acx_write_fw (radio): %d\n", res);
7203 + res = acx_s_validate_fw(priv, radio_image, offset);
7204 + acxlog(L_DEBUG|L_INIT, "acx_validate_fw (radio): %d\n", res);
7209 + printk("acx: radio firmware upload attempt #%d FAILED, "
7210 + "retrying...\n", try);
7211 + acx_s_msleep(1000); /* better wait for a while... */
7214 + acx_s_issue_cmd(priv, ACX1xx_CMD_WAKE, NULL, 0);
7215 + radioinit.offset = cpu_to_le32(offset);
7216 + /* no endian conversion needed, remains in card CPU area: */
7217 + radioinit.len = radio_image->size;
7219 + vfree(radio_image);
7224 + /* will take a moment so let's have a big timeout */
7225 + acx_s_issue_cmd_timeo(priv, ACX1xx_CMD_RADIOINIT,
7226 + &radioinit, sizeof(radioinit), CMD_TIMEOUT_MS(1000));
7228 + res = acx_s_interrogate(priv, &mm, ACX1xx_IE_MEMORY_MAP);
7234 +void write_reg(wlandevice_t *priv, int reg, u32 value){
7235 + acx_write_reg32(priv,IO_ACX_HW_SLAVE_REG_ADDR,priv->io[reg]);
7236 + acx_write_reg16(priv,IO_ACX_HW_SLAVE_REG_DATA,value);
7239 +u32 read_reg(wlandevice_t *priv, int reg){
7242 + acx_write_reg32(priv,IO_ACX_HW_SLAVE_REG_ADDR,reg);
7243 + value = acx_read_reg32(priv,IO_ACX_HW_SLAVE_REG_DATA);
7249 +/***********************************************************************
7253 +** wlandevice: private device that contains card device
7255 +** MAC will be reset
7259 +** resets onboard acx100 MAC
7261 +** Requires lock to be taken
7264 +acx_l_reset_mac(wlandevice_t *priv)
7270 + /* Pocket PC driver setting this register
7273 + acx_write_reg16(priv,IO_ACX_PCI_ARB_CFG,0x2);
7278 + acxlog(L_DEBUG, "%s: Halt eCPU ...\n", __func__);
7279 + temp = acx_read_reg16(priv, IO_ACX_ECPU_CTRL) | 0x1;
7280 + acx_write_reg16(priv, IO_ACX_ECPU_CTRL, temp);
7281 + acx_write_flush(priv);
7285 + /* now do soft reset of eCPU */
7286 + temp = acx_read_reg16(priv, IO_ACX_SOFT_RESET) | 0x1;
7287 + acxlog(L_DEBUG, "%s: enable soft reset...\n", __func__);
7288 + acx_write_reg16(priv, IO_ACX_SOFT_RESET, temp);
7289 + acx_write_flush(priv);
7293 + /* now reset bit again */
7294 + acxlog(L_DEBUG, "%s: disable soft reset and go to init mode...\n", __func__);
7295 + /* deassert eCPU reset */
7296 + acx_write_reg16(priv, IO_ACX_SOFT_RESET, temp & ~0x1);
7298 + /* now start a burst read from initial flash EEPROM */
7299 + temp = acx_read_reg16(priv, IO_ACX_EE_START) | 0x1;
7300 + acx_write_reg16(priv, IO_ACX_EE_START, temp);
7301 + acx_write_flush(priv);
7309 +/***********************************************************************
7310 +** acx_s_verify_init
7313 +acx_s_verify_init(wlandevice_t *priv)
7315 + int result = NOT_OK;
7320 + for (timer = 40; timer > 0; timer--) {
7321 + u16 irqstat = acx_read_reg16(priv, IO_ACX_IRQ_STATUS_NON_DES);
7322 + if (irqstat & HOST_INT_FCS_THRESHOLD) {
7324 + acx_write_reg16(priv, IO_ACX_IRQ_ACK, HOST_INT_FCS_THRESHOLD);
7327 + /* HZ / 50 resulted in 24 schedules for ACX100 on my machine,
7328 + * so better schedule away longer for greater efficiency,
7329 + * decrease loop count */
7339 +/***********************************************************************
7340 +** A few low-level helpers
7342 +** Note: these functions are not protected by lock
7343 +** and thus are never allowed to be called from IRQ.
7344 +** Also they must not race with fw upload which uses same hw regs
7347 +/***********************************************************************
7348 +** acx_read_info_status
7350 +/* Info mailbox format:
7353 +more bytes may follow
7354 + docs say about status:
7355 + 0x0000 info available (set by hw)
7356 + 0x0001 information received (must be set by host)
7357 + 0x1000 info available, mailbox overflowed (messages lost) (set by hw)
7358 + but in practice we've seen:
7359 + 0x9000 when we did not set status to 0x0001 on prev message
7360 + 0x1001 when we did set it
7361 + 0x0000 was never seen
7362 + conclusion: this is really a bitfield:
7363 + 0x1000 is 'info available' bit
7364 + 'mailbox overflowed' bit is 0x8000, not 0x1000
7365 + value of 0x0000 probably means that there is no message at all
7366 + P.S. I dunno how in hell hw is supposed to notice that messages are lost -
7367 + it does NOT clear bit 0x0001, and this bit will probably stay forever set
7368 + after we set it once. Let's hope this will be fixed in firmware someday
7371 +acx_read_info_status(wlandevice_t *priv)
7375 + acx_write_reg32(priv, IO_ACX_SLV_END_CTL, 0x0);
7376 + acx_write_reg32(priv, IO_ACX_SLV_MEM_CTL, 0x1);
7378 + acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR,
7379 + acx_read_reg32(priv, IO_ACX_INFO_MAILBOX_OFFS));
7381 + /* make sure we only read the data once all cfg registers are written: */
7382 + acx_write_flush(priv);
7383 + value = acx_read_reg32(priv, IO_ACX_SLV_MEM_DATA);
7385 + priv->info_type = (u16)value;
7386 + priv->info_status = (value >> 16);
7388 + /* inform hw that we have read this info message */
7389 + acx_write_reg32(priv, IO_ACX_SLV_MEM_DATA, priv->info_type | 0x00010000);
7390 + acx_write_flush(priv);
7391 + /* now bother hw to notice it: */
7392 + acx_write_reg16(priv, IO_ACX_INT_TRIG, INT_TRIG_INFOACK);
7393 + acx_write_flush(priv);
7395 + acxlog(L_CTL, "info_type 0x%04X, info_status 0x%04X\n",
7396 + priv->info_type, priv->info_status);
7400 +/***********************************************************************
7401 +** acx_write_cmd_type_or_status
7404 +acx_write_cmd_type_or_status(wlandevice_t *priv, u32 val)
7406 + acx_write_reg32(priv, IO_ACX_SLV_END_CTL, 0x0);
7407 + acx_write_reg32(priv, IO_ACX_SLV_MEM_CTL, 0x1); /* FIXME: why auto increment?? */
7409 + acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR,
7410 + acx_read_reg32(priv, IO_ACX_CMD_MAILBOX_OFFS));
7412 + /* make sure we only write the data once all config registers are written */
7413 + acx_write_flush(priv);
7414 + acx_write_reg32(priv, IO_ACX_SLV_MEM_DATA, val);
7415 + acx_write_flush(priv);
7418 +acx_write_cmd_type(wlandevice_t *priv, u32 val)
7420 + acx_write_cmd_type_or_status(priv, val);
7423 +acx_write_cmd_status(wlandevice_t *priv, u32 val)
7425 + acx_write_cmd_type_or_status(priv, val<<16);
7429 +/***********************************************************************
7430 +** acx_read_cmd_status
7433 +acx_read_cmd_status(wlandevice_t *priv)
7437 + acx_write_reg32(priv, IO_ACX_SLV_END_CTL, 0x0);
7438 + acx_write_reg32(priv, IO_ACX_SLV_MEM_CTL, 0x1); /* FIXME: why auto increment?? */
7440 + acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR,
7441 + acx_read_reg32(priv, IO_ACX_CMD_MAILBOX_OFFS));
7443 + /* make sure we only read the data once all config registers are written */
7444 + acx_write_flush(priv);
7445 + value = acx_read_reg32(priv, IO_ACX_SLV_MEM_DATA);
7447 + priv->cmd_type = (u16)value;
7448 + priv->cmd_status = (value >> 16);
7450 + acxlog(L_CTL, "cmd_type 0x%04X, cmd_status 0x%04X [%s]\n",
7451 + priv->cmd_type, priv->cmd_status,
7452 + acx_cmd_status_str(priv->cmd_status));
7455 +/***********************************************************************
7459 +** netdevice that contains the wlandevice priv variable
7464 +** device is hard reset
7468 +** This resets the acx100 device using low level hardware calls
7469 +** as well as uploads and verifies the firmware to the card
7472 +acx_s_reset_dev(netdevice_t *dev)
7474 + wlandevice_t *priv = netdev_priv(dev);
7475 + const char* msg = "";
7476 + unsigned long flags;
7477 + int result = NOT_OK;
7478 + u16 hardware_info;
7483 + /* we're doing a reset, so hardware is unavailable */
7485 + /* reset the device to make sure the eCPU is stopped
7486 + * to upload the firmware correctly */
7488 + acx_lock(priv, flags);
7490 + acx_l_reset_mac(priv);
7492 + ecpu_ctrl = acx_read_reg16(priv, IO_ACX_ECPU_CTRL) & 1;
7494 + msg = "eCPU is already running. ";
7498 +#ifdef WE_DONT_NEED_THAT_DO_WE
7499 + if (acx_read_reg16(priv, IO_ACX_SOR_CFG) & 2) {
7500 + /* eCPU most likely means "embedded CPU" */
7501 + msg = "eCPU did not start after boot from flash. ";
7505 + /* check sense on reset flags */
7506 + if (acx_read_reg16(priv, IO_ACX_SOR_CFG) & 0x10) {
7507 + printk("%s: eCPU did not start after boot (SOR), "
7508 + "is this fatal?\n", dev->name);
7511 + /* scan, if any, is stopped now, setting corresponding IRQ bit */
7512 + priv->irq_status |= HOST_INT_SCAN_COMPLETE;
7514 + acx_unlock(priv, flags);
7516 + /* without this delay acx100 may fail to report hardware_info
7517 + ** (see below). Most probably eCPU runs some init code */
7520 + /* Need to know radio type before fw load */
7521 + hardware_info = acx_read_reg16(priv, IO_ACX_EEPROM_INFORMATION);
7522 + priv->form_factor = hardware_info & 0xff;
7523 + priv->radio_type = hardware_info >> 8;
7525 + /* load the firmware */
7526 + if (OK != acx_s_upload_fw(priv)){
7527 + printk("Failed to load firmware\n");
7533 + /* now start eCPU by clearing bit */
7534 + acxlog(L_DEBUG, "booted eCPU up and waiting for completion...\n");
7535 + //acx_write_reg16(priv, IO_ACX_ECPU_CTRL, ecpu_ctrl & ~0x1);
7536 + write_reg(priv, IO_ACX_ECPU_CTRL, ecpu_ctrl & ~0x1);
7538 + /* wait for eCPU bootup */
7539 + if (OK != acx_s_verify_init(priv)) {
7540 + msg = "timeout waiting for eCPU. ";
7544 + acxlog(L_DEBUG, "eCPU has woken up, card is ready to be configured\n");
7546 + if (IS_ACX111(priv)) {
7547 + acxlog(L_DEBUG, "cleaning up cmd mailbox access area\n");
7548 + acx_write_cmd_status(priv, 0);
7549 + acx_read_cmd_status(priv);
7550 + if (priv->cmd_status) {
7551 + msg = "error cleaning cmd mailbox area. ";
7556 + /* TODO what is this one doing ?? adapt for acx111 */
7557 + if ((OK != acx_read_eeprom_area(priv)) && IS_ACX100(priv)) {
7558 + /* does "CIS" mean "Card Information Structure"?
7559 + * If so, then this would be a PCMCIA message...
7561 + msg = "CIS error. ";
7569 +/* Finish error message. Indicate which function failed */
7571 + acx_unlock(priv, flags);
7573 + printk("acx: %sreset_dev() FAILED\n", msg);
7579 +/***********************************************************************
7583 +acx_init_mboxes(wlandevice_t *priv)
7585 + u32 cmd_offs, info_offs;
7589 + cmd_offs = acx_read_reg32(priv, IO_ACX_CMD_MAILBOX_OFFS);
7590 + info_offs = acx_read_reg32(priv, IO_ACX_INFO_MAILBOX_OFFS);
7591 + priv->cmd_area = (u8 *) cmd_offs + 0x4;
7592 + priv->info_area = (u8 *) info_offs + 0x4;
7593 + acxlog(L_DEBUG, "iobase2=%p\n"
7594 + "cmd_mbox_offset=%X cmd_area=%p\n"
7595 + "info_mbox_offset=%X info_area=%p\n",
7597 + cmd_offs, priv->cmd_area,
7598 + info_offs, priv->info_area);
7604 +/*----------------------------------------------------------------
7605 +* acx_s_issue_cmd_timeo
7606 +* Excecutes a command in the command mailbox
7609 +* *pcmdparam = an pointer to the data. The data mustn't include
7610 +* the 4 byte command header!
7612 +* NB: we do _not_ take lock inside, so be sure to not touch anything
7613 +* which may interfere with IRQ handler operation
7615 +* TODO: busy wait is a bit silly, so:
7616 +* 1) stop doing many iters - go to sleep after first
7617 +* 2) go to waitqueue based approach: wait, not poll!
7618 +*----------------------------------------------------------------*/
7620 +#define FUNC "issue_cmd"
7624 +acxpci_s_issue_cmd_timeo(
7625 + wlandevice_t *priv,
7633 +acxpci_s_issue_cmd_timeo_debug(
7634 + wlandevice_t *priv,
7639 + const char* cmdstr)
7641 + unsigned long start = jiffies;
7643 + const char *devname;
7650 + devname = priv->netdev->name;
7651 + if (!devname || !devname[0])
7654 + acxlog(L_CTL, FUNC"(cmd:%s,buflen:%u,timeout:%ums,type:0x%04X)\n",
7655 + cmdstr, buflen, timeout,
7656 + buffer ? le16_to_cpu(((acx_ie_generic_t *)buffer)->type) : -1);
7658 + if (!(priv->dev_state_mask & ACX_STATE_FW_LOADED)) {
7659 + printk("%s: "FUNC"(): firmware is not loaded yet, "
7660 + "cannot execute commands!\n", devname);
7664 + if ((acx_debug & L_DEBUG) && (cmd != ACX1xx_CMD_INTERROGATE)) {
7665 + printk("input pdr (len=%u):\n", buflen);
7666 + acx_dump_bytes(buffer, buflen);
7669 + /* wait for firmware to become idle for our command submission */
7670 + counter = 199; /* in ms */
7672 + acx_read_cmd_status(priv);
7673 + /* Test for IDLE state */
7674 + if (!priv->cmd_status)
7676 + if (counter % 10 == 0) {
7677 + /* we waited 10 iterations, no luck. Sleep 10 ms */
7680 + } while (--counter);
7683 + /* the card doesn't get idle, we're in trouble */
7684 + printk("%s: "FUNC"(): cmd_status is not IDLE: 0x%04X!=0\n",
7685 + devname, priv->cmd_status);
7687 + } else if (counter < 190) { /* if waited >10ms... */
7688 + acxlog(L_CTL|L_DEBUG, FUNC"(): waited for IDLE %dms. "
7689 + "Please report\n", 199 - counter);
7692 + /* now write the parameters of the command if needed */
7693 + if (buffer && buflen) {
7694 + /* if it's an INTERROGATE command, just pass the length
7695 + * of parameters to read, as data */
7697 + if (cmd == ACX1xx_CMD_INTERROGATE)
7698 + acx_mailbox_fill(priv, (unsigned int) priv->cmd_area, 0xAA, buflen);
7700 + acx_mailbox_write(priv,
7701 + (unsigned int) priv->cmd_area,
7702 + buffer, (cmd == ACX1xx_CMD_INTERROGATE) ? 4 : buflen);
7705 + /* now write the actual command type */
7706 + priv->cmd_type = cmd;
7707 + acx_write_cmd_type(priv, cmd);
7708 + /* execute command */
7709 + acx_write_reg16(priv, IO_ACX_INT_TRIG, INT_TRIG_CMD);
7710 + acx_write_flush(priv);
7712 + /* wait for firmware to process command */
7714 + /* Ensure nonzero and not too large timeout.
7715 + ** Also converts e.g. 100->99, 200->199
7716 + ** which is nice but not essential */
7717 + timeout = (timeout-1) | 1;
7718 + if (unlikely(timeout > 1199))
7720 + /* clear CMD_COMPLETE bit. can be set only by IRQ handler: */
7721 + priv->irq_status &= ~HOST_INT_CMD_COMPLETE;
7723 + /* we schedule away sometimes (timeout can be large) */
7724 + counter = timeout;
7726 + if (!priv->irqs_active) { /* IRQ disabled: poll */
7727 + irqtype = acx_read_reg16(priv, IO_ACX_IRQ_STATUS_NON_DES);
7728 + if (irqtype & HOST_INT_CMD_COMPLETE) {
7729 + acx_write_reg16(priv, IO_ACX_IRQ_ACK,
7730 + HOST_INT_CMD_COMPLETE);
7733 + } else { /* Wait when IRQ will set the bit */
7734 + irqtype = priv->irq_status;
7735 + if (irqtype & HOST_INT_CMD_COMPLETE)
7739 + if (counter % 10 == 0) {
7740 + /* we waited 10 iterations, no luck. Sleep 10 ms */
7743 + } while (--counter);
7745 + /* save state for debugging */
7746 + acx_read_cmd_status(priv);
7747 + cmd_status = priv->cmd_status;
7749 + /* put the card in IDLE state */
7750 + priv->cmd_status = 0;
7751 + acx_write_cmd_status(priv, 0);
7753 + if (!counter) { /* timed out! */
7754 + printk("%s: "FUNC"(): timed out %s for CMD_COMPLETE. "
7755 + "irq bits:0x%04X irq_status:0x%04X timeout:%dms "
7756 + "cmd_status:%d (%s)\n",
7757 + devname, (priv->irqs_active) ? "waiting" : "polling",
7758 + irqtype, priv->irq_status, timeout,
7759 + cmd_status, acx_cmd_status_str(cmd_status));
7761 + } else if (timeout - counter > 30) { /* if waited >30ms... */
7762 + acxlog(L_CTL|L_DEBUG, FUNC"(): %s for CMD_COMPLETE %dms. "
7763 + "count:%d. Please report\n",
7764 + (priv->irqs_active) ? "waited" : "polled",
7765 + timeout - counter, counter);
7768 + if (1 != cmd_status) { /* it is not a 'Success' */
7769 + printk("%s: "FUNC"(): cmd_status is not SUCCESS: %d (%s). "
7770 + "Took %dms of %d\n",
7771 + devname, cmd_status, acx_cmd_status_str(cmd_status),
7772 + timeout - counter, timeout);
7773 + /* zero out result buffer */
7774 + if (buffer && buflen)
7775 + memset(buffer, 0, buflen);
7779 + /* read in result parameters if needed */
7780 + if (buffer && buflen && (cmd == ACX1xx_CMD_INTERROGATE)) {
7781 + //memcpy(buffer, priv->cmd_area, buflen);
7782 + acx_mailbox_read(priv, (unsigned int) priv->cmd_area, buffer, buflen);
7783 + if (acx_debug & L_DEBUG) {
7784 + printk("output buffer (len=%u): ", buflen);
7785 + acx_dump_bytes(buffer, buflen);
7789 + acxlog(L_CTL, FUNC"(%s): took %ld jiffies to complete\n",
7790 + cmdstr, jiffies - start);
7795 + /* Give enough info so that callers can avoid
7796 + ** printing their own diagnostic messages */
7798 + printk("%s: "FUNC"(cmd:%s) FAILED\n", devname, cmdstr);
7800 + printk("%s: "FUNC"(cmd:0x%04X) FAILED\n", devname, cmd);
7808 +/*----------------------------------------------------------------
7809 +* acx_s_get_firmware_version
7810 +*----------------------------------------------------------------*/
7812 +acx_s_get_firmware_version(wlandevice_t *priv)
7815 + u8 hexarr[4] = { 0, 0, 0, 0 };
7816 + int hexidx = 0, val = 0;
7822 + acx_s_interrogate(priv, &fw, ACX1xx_IE_FWREV);
7823 + memcpy(priv->firmware_version, fw.fw_id, FW_ID_SIZE);
7824 + priv->firmware_version[FW_ID_SIZE] = '\0';
7825 + acxlog(L_DEBUG, "fw_ver: fw_id='%s' hw_id=%08X\n",
7826 + priv->firmware_version, fw.hw_id);
7828 + if (strncmp(fw.fw_id, "Rev ", 4) != 0) {
7829 + printk("acx: strange firmware version string "
7830 + "'%s', please report\n", priv->firmware_version);
7831 + priv->firmware_numver = 0x01090407; /* assume 1.9.4.7 */
7833 + num = &fw.fw_id[4];
7836 + if ((c == '.') || (c == '\0')) {
7837 + hexarr[hexidx++] = val;
7838 + if ((hexidx > 3) || (c == '\0')) /* end? */
7843 + if ((c >= '0') && (c <= '9'))
7846 + c = c - 'a' + (char)10;
7850 + priv->firmware_numver = (u32)(
7851 + (hexarr[0] << 24) + (hexarr[1] << 16)
7852 + + (hexarr[2] << 8) + hexarr[3]);
7853 + acxlog(L_DEBUG, "firmware_numver 0x%08X\n", priv->firmware_numver);
7855 + if (IS_ACX111(priv)) {
7856 + if (priv->firmware_numver == 0x00010011) {
7857 + /* This one does not survive floodpinging */
7858 + printk("acx: firmware '%s' is known to be buggy, "
7859 + "please upgrade\n", priv->firmware_version);
7861 + if (priv->firmware_numver == 0x02030131) {
7862 + /* With this one, all rx packets look mangled
7863 + ** Most probably we simply do not know how to use it
7865 + printk("acx: firmware '%s' does not work well "
7866 + "with this driver\n", priv->firmware_version);
7870 + priv->firmware_id = le32_to_cpu(fw.hw_id);
7872 + /* we're able to find out more detailed chip names now */
7873 + switch (priv->firmware_id & 0xffff0000) {
7876 + priv->chip_name = name_tnetw1100a;
7879 + priv->chip_name = name_tnetw1100b;
7883 + priv->chip_name = name_tnetw1130;
7886 + printk("acx: unknown chip ID 0x%08X, "
7887 + "please report\n", priv->firmware_id);
7895 +/*----------------------------------------------------------------
7896 +* acx_display_hardware_details
7899 +* priv: ptr to wlandevice that contains all the details
7900 +* displayed by this function
7904 +* This function will display strings to the system log according
7905 +* to device form_factor and radio type. It will needed to be
7906 +*----------------------------------------------------------------*/
7908 +acx_display_hardware_details(wlandevice_t *priv)
7910 + const char *radio_str, *form_str;
7914 + switch (priv->radio_type) {
7915 + case RADIO_MAXIM_0D:
7916 + /* hmm, the DWL-650+ seems to have two variants,
7917 + * according to a windows driver changelog comment:
7918 + * RFMD and Maxim. */
7919 + radio_str = "Maxim";
7921 + case RADIO_RFMD_11:
7922 + radio_str = "RFMD";
7924 + case RADIO_RALINK_15:
7925 + radio_str = "Ralink";
7927 + case RADIO_RADIA_16:
7928 + radio_str = "Radia";
7930 + case RADIO_UNKNOWN_17:
7931 + /* TI seems to have a radio which is
7932 + * additionally 802.11a capable, too */
7933 + radio_str = "802.11a/b/g radio?! Please report";
7935 + case RADIO_UNKNOWN_19:
7936 + radio_str = "A radio used by Safecom cards?! Please report";
7939 + radio_str = "UNKNOWN, please report the radio type name!";
7943 + switch (priv->form_factor) {
7945 + form_str = "unspecified";
7948 + form_str = "(mini-)PCI / CardBus";
7954 + form_str = "Compact Flash";
7957 + form_str = "UNKNOWN, Please report";
7961 + printk("acx: form factor 0x%02X (%s), "
7962 + "radio type 0x%02X (%s), EEPROM version 0x%02X, "
7963 + "uploaded firmware '%s' (0x%08X)\n",
7964 + priv->form_factor, form_str, priv->radio_type, radio_str,
7965 + priv->eeprom_version, priv->firmware_version,
7966 + priv->firmware_id);
7971 +/***********************************************************************
7973 +#ifdef NONESSENTIAL_FEATURES
7974 +typedef struct device_id {
7975 + unsigned char id[6];
7980 +static const device_id_t
7984 + {'G', 'l', 'o', 'b', 'a', 'l'},
7989 + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
7991 + "SpeedStream SS1021 or Gigafast WF721-AEX"
7994 + {0x80, 0x81, 0x82, 0x83, 0x84, 0x85},
7996 + "DrayTek Vigor 520"
7999 + {'?', '?', '?', '?', '?', '?'},
8001 + "Level One WPC-0200"
8004 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
8006 + "DWL-650+ variant"
8011 +acx_show_card_eeprom_id(wlandevice_t *priv)
8013 + unsigned char buffer[CARD_EEPROM_ID_SIZE];
8016 + memset(&buffer, 0, CARD_EEPROM_ID_SIZE);
8017 + /* use direct EEPROM access */
8018 + for (i = 0; i < CARD_EEPROM_ID_SIZE; i++) {
8019 + if (OK != acx_read_eeprom_offset(priv,
8020 + ACX100_EEPROM_ID_OFFSET + i,
8023 + printk("acx: reading EEPROM FAILED\n");
8028 + for (i = 0; i < VEC_SIZE(device_ids); i++) {
8029 + if (!memcmp(&buffer, device_ids[i].id, CARD_EEPROM_ID_SIZE)) {
8030 + if (device_ids[i].descr) {
8031 + printk("acx: EEPROM card ID string check "
8032 + "found %s card ID: is this %s?\n",
8033 + device_ids[i].descr, device_ids[i].type);
8038 + if (i == VEC_SIZE(device_ids)) {
8039 + printk("acx: EEPROM card ID string check found "
8040 + "unknown card: expected 'Global', got '%.*s\'. "
8041 + "Please report\n", CARD_EEPROM_ID_SIZE, buffer);
8044 +#endif /* NONESSENTIAL_FEATURES */
8047 +/***********************************************************************
8050 +acx_s_device_chain_add(struct net_device *dev)
8052 + wlandevice_t *priv = netdev_priv(dev);
8054 + down(&root_acx_dev_sem);
8055 + priv->prev_nd = root_acx_dev.newest;
8056 + root_acx_dev.newest = dev;
8057 + priv->netdev = dev;
8058 + up(&root_acx_dev_sem);
8062 +acx_s_device_chain_remove(struct net_device *dev)
8064 + struct net_device *querydev;
8065 + struct net_device *olderdev;
8066 + struct net_device *newerdev;
8068 + down(&root_acx_dev_sem);
8069 + querydev = root_acx_dev.newest;
8071 + while (querydev) {
8072 + olderdev = ((wlandevice_t*)netdev_priv(querydev))->prev_nd;
8073 + if (0 == strcmp(querydev->name, dev->name)) {
8075 + /* if we were at the beginning of the
8076 + * list, then it's the list head that
8077 + * we need to update to point at the
8078 + * next older device */
8079 + root_acx_dev.newest = olderdev;
8081 + /* it's the device that is newer than us
8082 + * that we need to update to point at
8083 + * the device older than us */
8084 + ((wlandevice_t*)netdev_priv(newerdev))->
8085 + prev_nd = olderdev;
8089 + /* "newerdev" is actually the device of the old iteration,
8090 + * but since the list starts (root_acx_dev.newest)
8091 + * with the newest devices,
8092 + * it's newer than the ones following.
8093 + * Oh the joys of iterating from newest to oldest :-\ */
8094 + newerdev = querydev;
8096 + /* keep checking old devices for matches until we hit the end
8098 + querydev = olderdev;
8100 + up(&root_acx_dev_sem);
8104 +/***********************************************************************
8105 +** acx_free_desc_queues
8107 +** Releases the queues that have been allocated, the
8108 +** others have been initialised to NULL so this
8109 +** function can be used if only part of the queues were allocated.
8112 +acx_free_coherent(struct pci_dev *hwdev, size_t size,
8113 + void *vaddr, dma_addr_t dma_handle)
8115 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 53)
8116 + dma_free_coherent(hwdev == NULL ? NULL : &hwdev->dev,
8117 + size, vaddr, dma_handle);
8119 + pci_free_consistent(hwdev, size, vaddr, dma_handle);
8124 +acx_free_desc_queues(wlandevice_t *priv)
8126 +#define ACX_FREE_QUEUE(size, ptr, phyaddr) \
8128 + acx_free_coherent(0, size, ptr, phyaddr); \
8135 + ACX_FREE_QUEUE(priv->txhostdesc_area_size, priv->txhostdesc_start, priv->txhostdesc_startphy);
8136 + ACX_FREE_QUEUE(priv->txbuf_area_size, priv->txbuf_start, priv->txbuf_startphy);
8138 + priv->txdesc_start = NULL;
8140 + ACX_FREE_QUEUE(priv->rxhostdesc_area_size, priv->rxhostdesc_start, priv->rxhostdesc_startphy);
8141 + ACX_FREE_QUEUE(priv->rxbuf_area_size, priv->rxbuf_start, priv->rxbuf_startphy);
8143 + priv->rxdesc_start = NULL;
8149 +/*----------------------------------------------------------------
8150 +* acx_s_delete_dma_regions
8151 +*----------------------------------------------------------------*/
8153 +acx_s_delete_dma_regions(wlandevice_t *priv)
8155 + unsigned long flags;
8158 + /* disable radio Tx/Rx. Shouldn't we use the firmware commands
8159 + * here instead? Or are we that much down the road that it's no
8160 + * longer possible here? */
8161 + acx_write_reg16(priv, IO_ACX_ENABLE, 0);
8163 + acx_s_msleep(100);
8165 + acx_lock(priv, flags);
8166 + acx_free_desc_queues(priv);
8167 + acx_unlock(priv, flags);
8173 +/*----------------------------------------------------------------
8176 +* Probe routine called when a PCI device w/ matching ID is found.
8177 +* Here's the sequence:
8178 +* - Allocate the PCI resources.
8179 +* - Read the PCMCIA attribute memory to make sure we have a WLAN card
8181 +* - Initialize the dev and wlan data
8182 +* - Initialize the MAC
8185 +* pdev ptr to pci device structure containing info about
8186 +* pci configuration.
8187 +* id ptr to the device id entry that matched this device.
8191 +* negative - failed
8195 +----------------------------------------------------------------*/
8199 + 0x0000, /* IO_ACX_SOFT_RESET */
8201 + 0x0004, /* IO_ACX_HW_SLAVE_REG_ADDR */
8202 + 0x0008, /* IO_ACX_HW_SLAVE_REG_DATA */
8203 + 0x000c, /* IO_ACX_HW_SLAVE_REG_REG_CTRL */
8205 + 0x0014, /* IO_ACX_SLV_MEM_ADDR */
8206 + 0x0018, /* IO_ACX_SLV_MEM_DATA */
8207 + 0x001c, /* IO_ACX_SLV_MEM_CTL */
8208 + 0x0020, /* IO_ACX_SLV_END_CTL */
8209 + 0x0024, /* IO_ACX_CHIPID */
8211 + 0x0034, /* IO_ACX_FEMR */
8213 + 0x007c, /* IO_ACX_INT_TRIG */
8214 + 0x0098, /* IO_ACX_IRQ_MASK */
8215 + 0x00a4, /* IO_ACX_IRQ_STATUS_NON_DES */
8216 + 0x00a8, /* IO_ACX_IRQ_STATUS_CLEAR */
8217 + 0x00ac, /* IO_ACX_IRQ_ACK */
8218 + 0x00b0, /* IO_ACX_HINT_TRIG */
8220 + 0x0104, /* IO_ACX_ENABLE */
8222 + 0x0250, /* IO_ACX_EEPROM_CTL */
8223 + 0x0254, /* IO_ACX_EEPROM_ADDR */
8224 + 0x0258, /* IO_ACX_EEPROM_DATA */
8225 + 0x025c, /* IO_ACX_EEPROM_CFG */
8227 + 0x0268, /* IO_ACX_PHY_ADDR */
8228 + 0x026c, /* IO_ACX_PHY_DATA */
8229 + 0x0270, /* IO_ACX_PHY_CTL */
8231 + 0x0290, /* IO_ACX_GPIO_OE */
8233 + 0x0294, /* IO_ACX_GPIO_IN */
8234 + 0x0298, /* IO_ACX_GPIO_OUT */
8235 + 0x029c, /* IO_ACX_GPIO_PD */
8236 + 0x02a0, /* IO_ACX_GPIO_CFG */
8238 + 0x02a4, /* IO_ACX_CMD_MAILBOX_OFFS */
8239 + 0x02a8, /* IO_ACX_INFO_MAILBOX_OFFS */
8240 + 0x02ac, /* IO_ACX_EEPROM_INFORMATION */
8242 + 0x02d0, /* IO_ACX_EE_START */
8243 + 0x02d4, /* IO_ACX_SOR_CFG */
8244 + 0x02d8, /* IO_ACX_ECPU_CTRL */
8246 + 0x0804, /* IO_ACX_HI_CTL */
8247 + 0x0808, /* IO_ACX_LPWR_MGN */
8249 + 0x010c, /* IO_ACX_PCI_ARB_CFG */
8254 +acx_netdev_init(struct net_device *dev) {}
8256 +//FIXME: do the same for USB
8258 +acx_change_mtu(struct net_device *dev, int mtu)
8262 + MAX_MTU = WLAN_DATA_MAXLEN - (ETH_HLEN)
8265 + if (mtu < MIN_MTU || mtu > MAX_MTU)
8273 +static int acx_enable(struct platform_device *pdev){
8274 + unsigned long flags;
8276 + /* We need to disabe the interrupt
8279 + local_irq_save(flags);
8281 + /* Now lets turn on and
8282 + * reset the device.
8284 + pca9535_gpio_write(GPIO6, LOW);
8285 + pca9535_gpio_write(GPIO12, LOW);
8287 + /* TODO: someother configuration needs
8288 + * to be done here.
8291 + // Now we can enable interrupt.
8292 + local_irq_restore(flags);
8298 +static inline void test(wlandevice_t *priv) {
8299 + printk("===============================\n");
8300 + printk("Reset : %04x\n",acx_read_reg16(priv, IO_ACX_SOFT_RESET));
8301 + printk("eCPU CTL: %04x\n",acx_read_reg16(priv, IO_ACX_ECPU_CTRL));
8302 + printk("SOR CFG : %08x\n",acx_read_reg32(priv, IO_ACX_SOR_CFG));
8303 + printk("EE START: %08x\n",acx_read_reg32(priv, IO_ACX_EE_START));
8304 + printk("HI CTRL : %08x\n",acx_read_reg32(priv, IO_ACX_HI_CTRL));
8305 +// printk("Info : %08x\n",acx_read_reg32(priv, IO_ACX_EEPROM_INFORMATION));
8306 + printk("GPIO OE : %04x\n",acx_read_reg16(priv, IO_ACX_GPIO_OE));
8307 + printk("GPIO OUT: %04x\n",acx_read_reg16(priv, IO_ACX_GPIO_OUT));
8308 + printk("GPIO IN : %04x\n",acx_read_reg16(priv, IO_ACX_GPIO_IN));
8309 + printk("GPIO PD : %04x\n",acx_read_reg16(priv, IO_ACX_GPIO_PD));
8310 + printk("GPIO CFG: %04x\n",acx_read_reg16(priv, IO_ACX_GPIO_CFG));
8311 + printk("Chip ID : %08x\n",acx_read_reg32(priv, IO_ACX_CHIPID));
8314 + printk("HW CTRL : %08x\n",acx_read_reg32(priv,IO_ACX_HW_SLAVE_REG_CTRL));
8315 + printk("HW ADDR : %08x\n",acx_read_reg32(priv,IO_ACX_HW_SLAVE_REG_ADDR));
8316 + printk("HW DATA : %08x\n",acx_read_reg32(priv,IO_ACX_HW_SLAVE_REG_DATA));
8321 + printk("==============================\n");
8324 +static int __init acx_probe(struct net_device *ndev, void __iomem *addr, struct resource *res){
8325 + wlandevice_t *priv = netdev_priv(ndev);
8328 + ether_setup(ndev);
8330 + /* now that device init was successful, fill remaining fields... */
8331 + ndev->open = &acx_e_open;
8332 + ndev->stop = &acx_e_close;
8333 + ndev->hard_start_xmit = &acx_i_start_xmit;
8334 + ndev->get_stats = &acx_e_get_stats;
8335 + ndev->get_wireless_stats = &acx_e_get_wireless_stats;
8336 +#if WIRELESS_EXT >= 13
8337 + ndev->wireless_handlers = (struct iw_handler_def *)&acx_ioctl_handler_def;
8339 + ndev->do_ioctl = &acx_e_ioctl_old;
8341 + ndev->set_multicast_list = &acx_i_set_multicast_list;
8342 + ndev->tx_timeout = &acx_i_tx_timeout;
8343 + ndev->change_mtu = &acx_change_mtu;
8344 + ndev->watchdog_timeo = 4 * HZ;
8346 + spin_lock_init(&priv->lock); /* initial state: unlocked */
8347 + /* We do not start with downed sem: we want PARANOID_LOCKING to work */
8348 + sema_init(&priv->sem, 1); /* initial state: 1 (upped) */
8350 + priv->iobase = (unsigned char *) addr;
8351 + priv->iobase2 = 0;
8352 + priv->membase = res->start;
8353 + priv->chip_type = CHIPTYPE_ACX100;
8354 + priv->chip_name = name_acx100;
8355 + priv->io = IO_ACX100;
8356 + priv->mgmt_timer.function = (void (*)(unsigned long))0x0000dead;
8357 + spin_lock_init(&priv->lock);
8361 +#ifdef NONESSENTIAL_FEATURES
8362 + acx_show_card_eeprom_id(priv);
8363 +#endif /* NONESSENTIAL_FEATURES */
8365 + /* now we have our device, so make sure the kernel doesn't try
8366 + * to send packets even though we're not associated to a network yet */
8367 + acx_stop_queue(ndev, "after setup");
8369 + /* register new dev in linked list */
8370 + acx_s_device_chain_add(ndev);
8372 + if((ret = acx_s_reset_dev(ndev)) != OK){
8373 + /* Failed to reset device */
8378 + /* ok, basic setup is finished, now start initialising the card */
8380 + hardware_info = acx_read_reg16(priv, IO_ACX_EEPROM_INFORMATION);
8381 + priv->form_factor = (u8)(hardware_info & 0xff);
8382 + priv->radio_type = (u8)(hardware_info >> 8 & 0xff);
8385 + if (OK != acx_read_eeprom_offset(priv, 0x05, &priv->eeprom_version)) {
8387 + goto fail_read_eeprom_version;
8390 + if (OK != acx_s_init_mac(ndev)) {
8391 + acxlog(L_DEBUG | L_INIT,
8392 + "Danger Will Robinson, MAC did not come back\n");
8394 + goto fail_init_mac;
8397 + if (OK != acx_s_set_defaults(priv)) {
8398 + printk("acx: set_defaults() FAILED\n");
8399 + goto fail_set_defaults;
8402 + /* needs to be after acx_init_mac() due to necessary init stuff */
8403 + acx_s_get_firmware_version(priv);
8405 + acx_display_hardware_details(priv);
8407 + /* ...and register the card, AFTER everything else has been set up,
8408 + * since otherwise an ioctl could step on our feet due to
8409 + * firmware operations happening in parallel or uninitialized data */
8410 + ret = register_netdev(ndev);
8413 + "%s: Register net device of %s FAILED: %d\n",
8414 + __func__, ndev->name, ret);
8416 + goto fail_register_netdev;
8418 + acx_carrier_off(ndev, "on probe");
8420 +#ifdef CONFIG_PROC_FS
8421 + if (OK != acx_proc_register_entries(ndev)) {
8423 + goto fail_proc_register_entries;
8428 + great_inquisitor(priv);
8434 +#ifdef CONFIG_PROC_FS
8435 +fail_proc_register_entries:
8438 + if (priv->dev_state_mask & ACX_STATE_IFACE_UP)
8440 + unregister_netdev(ndev);
8442 +fail_register_netdev:
8443 + acx_s_delete_dma_regions(priv);
8446 +fail_read_eeprom_version:
8448 + acx_s_device_chain_remove(ndev);
8453 +static void dumpRegs(char *msg, unsigned char *base) {
8457 + printk("============= [ %s ] ===============\n",msg);
8459 + for(addr = 0; addr <= 0x0be0; addr+=4){
8460 + if(addr >= 0x0710 && addr <= 0x0740){
8462 + printk("Reg[%04x] : %08x\n",addr, val);
8467 + val = readw((u8 *) base + addr) + (readw((u8 *) base + addr + 2) << 16);
8469 + printk("Reg[%04x] : %08x\n",addr, val);
8473 + printk("=====================================\n");
8477 +static int __init acx_drv_probe(struct device *dev){
8478 + struct platform_device *pdev = to_platform_device(dev);
8479 + struct net_device *ndev = NULL;
8480 + struct resource *res = NULL;
8481 + unsigned int __iomem *addr = NULL;
8482 + wlandevice_t *priv = NULL;
8485 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
8487 + printk(KERN_ERR "Device not found\n");
8493 + if (!request_mem_region(res->start, SZ_32M, CARDNAME)) {
8494 + printk(KERN_ERR "Device busy\n");
8499 + // Create new ethernet device
8500 + ndev = alloc_netdev(sizeof(wlandevice_t), "wlan%d", acx_netdev_init);
8502 + printk("%s: could not allocate device.\n", CARDNAME);
8504 + goto out_release_io;
8506 + SET_MODULE_OWNER(ndev);
8507 + SET_NETDEV_DEV(ndev, dev);
8509 + // Get driver private data
8510 + priv = netdev_priv(ndev);
8512 + // Cleanup the private area
8513 + memset((void *) priv, 0, sizeof(wlandevice_t));
8515 + ndev->dma = (unsigned char)-1;
8516 + ndev->irq = platform_get_irq(pdev, 0);
8522 + /* Create IOMEM port so we
8523 + * can use to to read and write
8524 + * from card registers.
8526 + if(!(addr = ioremap(res->start, SZ_32M))){
8527 + printk(KERN_ERR "Failed to map ioport\n");
8532 + dev_set_drvdata(dev, ndev);
8534 + //dumpRegs("After",addr);
8537 + if((ret = acx_probe(ndev, addr,res))){
8538 + /* Something wrong we couldn't
8539 + * talke to the device.
8541 + printk(KERN_ERR "Failed to probe ACX\n");
8545 + printk("acx "WLAN_RELEASE": net device %s, driver compiled "
8546 + "against wireless extensions %d and Linux %s\n",
8547 + ndev->name, WIRELESS_EXT, UTS_RELEASE);
8552 + dev_set_drvdata(dev, NULL);
8555 + free_netdev(ndev);
8557 + release_mem_region(res->start, SZ_32M);
8562 +static int acx_remove(struct device *dev)
8564 + struct platform_device *pdev = to_platform_device(dev);
8565 + struct net_device *ndev = (dev? dev_get_drvdata(dev) : NULL);
8566 + wlandevice_t *priv = (ndev? (wlandevice_t *) netdev_priv(ndev) : NULL);
8567 + struct resource *res = NULL;
8570 + printk(KERN_ERR "Invalid network device structure\n");
8574 + dev_set_drvdata(dev, NULL);
8575 + unregister_netdev(ndev);
8578 + free_irq(ndev->irq, ndev);
8581 + iounmap(priv->iobase);
8582 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
8583 + release_mem_region(res->start, SZ_32M);
8585 + free_netdev(ndev);
8590 +/***********************************************************************
8593 +static int if_was_up = 0; /* FIXME: HACK, do it correctly sometime instead */
8595 +acx_suspend(struct device *dev, pm_message_t state, u32 level)
8598 + struct net_device *ndev = pci_get_drvdata(pdev);
8599 + wlandevice_t *priv = netdev_priv(dev);
8603 + acx_sem_lock(priv);
8605 + printk("acx: experimental suspend handler called for %p\n", priv);
8606 + if (netif_device_present(ndev)) {
8613 + netif_device_detach(ndev); /* This one cannot sleep */
8614 + acx_s_delete_dma_regions(priv);
8616 + acx_sem_unlock(priv);
8624 +acx_resume(struct device *dev, u32 level)
8627 + struct platform_device *pdev = to_platform_device(dev);
8628 + struct net_device *ndev;
8629 + wlandevice_t *priv;
8631 + printk(KERN_WARNING "rsm: resume\n");
8632 + ndev = dev_get_drvdata(dev);
8633 + printk(KERN_WARNING "rsm: got dev\n");
8635 + if (!netif_running(ndev))
8638 + priv = netdev_priv(ndev);
8640 + acx_sem_lock(priv);
8642 + printk(KERN_WARNING "rsm: got priv\n");
8644 + printk("acx: experimental resume handler called for %p!\n", priv);
8646 + acxlog(L_DEBUG, "rsm: power state set\n");
8648 + acxlog(L_DEBUG, "rsm: PCI state restored\n");
8649 + acx_s_reset_dev(ndev);
8650 + acxlog(L_DEBUG, "rsm: device reset done\n");
8652 + if (OK != acx_s_init_mac(ndev)) {
8653 + printk("rsm: init_mac FAILED\n");
8656 + acxlog(L_DEBUG, "rsm: init MAC done\n");
8658 + if (1 == if_was_up)
8660 + acxlog(L_DEBUG, "rsm: acx up\n");
8662 + /* now even reload all card parameters as they were before suspend,
8663 + * and possibly be back in the network again already :-)
8664 + * FIXME: should this be done in that scheduled task instead?? */
8665 + if (ACX_STATE_IFACE_UP & priv->dev_state_mask)
8666 + acx_s_update_card_settings(priv, 0, 1);
8667 + acxlog(L_DEBUG, "rsm: settings updated\n");
8668 + netif_device_attach(ndev);
8669 + acxlog(L_DEBUG, "rsm: device attached\n");
8670 +fail: /* we need to return OK here anyway, right? */
8671 + acx_sem_unlock(priv);
8676 +#endif /* CONFIG_PM */
8679 +/*----------------------------------------------------------------
8683 +* - Enables on-card interrupt requests
8684 +* - calls acx_start
8688 +* This function is called by acx_open (when ifconfig sets the
8690 +*----------------------------------------------------------------*/
8692 +acx_s_up(netdevice_t *dev)
8694 + wlandevice_t *priv = netdev_priv(dev);
8695 + unsigned long flags;
8699 + acx_lock(priv, flags);
8700 + acx_l_enable_irq(priv);
8701 + acx_unlock(priv, flags);
8703 + /* acx fw < 1.9.3.e has a hardware timer, and older drivers
8704 + ** used to use it. But we don't do that anymore, our OS
8705 + ** has reliable software timers */
8706 + init_timer(&priv->mgmt_timer);
8707 + priv->mgmt_timer.function = acx_i_timer;
8708 + priv->mgmt_timer.data = (unsigned long)priv;
8710 + /* Need to set ACX_STATE_IFACE_UP first, or else
8711 + ** timer won't be started by acx_set_status() */
8712 + SET_BIT(priv->dev_state_mask, ACX_STATE_IFACE_UP);
8713 + switch (priv->mode) {
8714 + case ACX_MODE_0_ADHOC:
8715 + case ACX_MODE_2_STA:
8716 + /* actual scan cmd will happen in start() */
8717 + acx_set_status(priv, ACX_STATUS_1_SCANNING); break;
8718 + case ACX_MODE_3_AP:
8719 + case ACX_MODE_MONITOR:
8720 + acx_set_status(priv, ACX_STATUS_4_ASSOCIATED); break;
8723 + acx_s_start(priv);
8729 +/*----------------------------------------------------------------
8733 +* - disables on-card interrupt request
8737 +* this disables the netdevice
8738 +*----------------------------------------------------------------*/
8740 +acx_s_down(netdevice_t *dev)
8742 + wlandevice_t *priv = netdev_priv(dev);
8743 + unsigned long flags;
8747 + /* Disable IRQs first, so that IRQs cannot race with us */
8748 + acx_lock(priv, flags);
8749 + acx_l_disable_irq(priv);
8750 + acx_unlock(priv, flags);
8752 + /* we really don't want to have an asynchronous tasklet disturb us
8753 + ** after something vital for its job has been shut down, so
8754 + ** end all remaining work now.
8756 + ** NB: carrier_off (done by set_status below) would lead to
8757 + ** not yet fully understood deadlock in FLUSH_SCHEDULED_WORK().
8758 + ** That's why we do FLUSH first.
8760 + ** NB2: we have a bad locking bug here: FLUSH_SCHEDULED_WORK()
8761 + ** waits for acx_e_after_interrupt_task to complete if it is running
8762 + ** on another CPU, but acx_e_after_interrupt_task
8763 + ** will sleep on sem forever, because it is taken by us!
8764 + ** Work around that by temporary sem unlock.
8765 + ** This will fail miserably if we'll be hit by concurrent
8766 + ** iwconfig or something in between. TODO! */
8767 + acx_sem_unlock(priv);
8768 + FLUSH_SCHEDULED_WORK();
8769 + acx_sem_lock(priv);
8771 + /* This is possible:
8772 + ** FLUSH_SCHEDULED_WORK -> acx_e_after_interrupt_task ->
8773 + ** -> set_status(ASSOCIATED) -> wake_queue()
8774 + ** That's why we stop queue _after_ FLUSH_SCHEDULED_WORK
8775 + ** lock/unlock is just paranoia, maybe not needed */
8776 + acx_lock(priv, flags);
8777 + acx_stop_queue(dev, "during close");
8778 + acx_set_status(priv, ACX_STATUS_0_STOPPED);
8779 + acx_unlock(priv, flags);
8781 + /* kernel/timer.c says it's illegal to del_timer_sync()
8782 + ** a timer which restarts itself. We guarantee this cannot
8783 + ** ever happen because acx_i_timer() never does this if
8784 + ** status is ACX_STATUS_0_STOPPED */
8785 + del_timer_sync(&priv->mgmt_timer);
8791 +/*----------------------------------------------------------------
8794 +* WLAN device open method. Called from p80211netdev when kernel
8795 +* device open (start) method is called in response to the
8796 +* SIOCSIFFLAGS ioctl changing the flags bit IFF_UP
8797 +* from clear to set.
8801 +* >0 f/w reported error
8802 +* <0 driver reported error
8806 +----------------------------------------------------------------*/
8808 +acx_e_open(netdevice_t *dev)
8810 + wlandevice_t *priv = netdev_priv(dev);
8815 + acxlog(L_INIT, "module count++\n");
8816 + WLAN_MOD_INC_USE_COUNT;
8818 + acx_sem_lock(priv);
8820 + acx_init_task_scheduler(priv);
8822 + /* request shared IRQ handler */
8823 + if (request_irq(dev->irq, acx_i_interrupt, SA_SHIRQ, dev->name, dev)) {
8824 + printk("%s: request_irq FAILED\n", dev->name);
8828 + acxlog(L_DEBUG|L_IRQ, "request_irq %d successful\n", dev->irq);
8833 + /* We don't currently have to do anything else.
8834 + * The setup of the MAC should be subsequently completed via
8835 + * the mlme commands.
8836 + * Higher layers know we're ready from dev->start==1 and
8837 + * dev->tbusy==0. Our rx path knows to pass up received/
8838 + * frames because of dev->flags&IFF_UP is true.
8841 + acx_sem_unlock(priv);
8848 +/*----------------------------------------------------------------
8851 +* WLAN device close method. Called from network core when kernel
8852 +* device close method is called in response to the
8853 +* SIOCSIIFFLAGS ioctl changing the flags bit IFF_UP
8854 +* from set to clear.
8855 +* (i.e. called for "ifconfig DEV down")
8859 +* >0 f/w reported error
8860 +* <0 driver reported error
8864 +----------------------------------------------------------------*/
8866 +acx_e_close(netdevice_t *dev)
8868 + wlandevice_t *priv = netdev_priv(dev);
8872 + acx_sem_lock(priv);
8874 + /* ifdown device */
8875 + CLEAR_BIT(priv->dev_state_mask, ACX_STATE_IFACE_UP);
8876 + if (netif_device_present(dev)) {
8880 + /* disable all IRQs, release shared IRQ handler */
8881 + acx_write_reg16(priv, IO_ACX_IRQ_MASK, 0xffff);
8882 + acx_write_reg16(priv, IO_ACX_FEMR, 0x0);
8883 + free_irq(dev->irq, dev);
8885 + /* We currently don't have to do anything else.
8886 + * Higher layers know we're not ready from dev->start==0 and
8887 + * dev->tbusy==1. Our rx path knows to not pass up received
8888 + * frames because of dev->flags&IFF_UP is false.
8890 + acxlog(L_INIT, "module count--\n");
8891 + WLAN_MOD_DEC_USE_COUNT;
8893 + acx_sem_unlock(priv);
8895 + acxlog(L_INIT, "closed device\n");
8901 +/*----------------------------------------------------------------
8904 +* Called from network core. Must not sleep!
8905 +*----------------------------------------------------------------*/
8907 +acx_i_tx_timeout(netdevice_t *dev)
8909 + wlandevice_t *priv = netdev_priv(dev);
8910 + unsigned long flags;
8911 + unsigned int tx_num_cleaned;
8915 + acx_lock(priv, flags);
8917 + /* clean processed tx descs, they may have been completely full */
8918 + tx_num_cleaned = acx_l_clean_tx_desc(priv);
8920 + /* nothing cleaned, yet (almost) no free buffers available?
8921 + * --> clean all tx descs, no matter which status!!
8922 + * Note that I strongly suspect that doing emergency cleaning
8923 + * may confuse the firmware. This is a last ditch effort to get
8924 + * ANYTHING to work again...
8926 + * TODO: it's best to simply reset & reinit hw from scratch...
8928 + if ((priv->tx_free <= TX_EMERG_CLEAN) && (tx_num_cleaned == 0)) {
8929 + printk("%s: FAILED to free any of the many full tx buffers. "
8930 + "Switching to emergency freeing. "
8931 + "Please report!\n", dev->name);
8932 + acx_l_clean_tx_desc_emergency(priv);
8935 + if (acx_queue_stopped(dev) && (ACX_STATUS_4_ASSOCIATED == priv->status))
8936 + acx_wake_queue(dev, "after tx timeout");
8938 + /* stall may have happened due to radio drift, so recalib radio */
8939 + acx_schedule_after_interrupt_task(priv, ACX_AFTER_IRQ_CMD_RADIO_RECALIB);
8941 + /* do unimportant work last */
8942 + printk("%s: tx timeout!\n", dev->name);
8943 + priv->stats.tx_errors++;
8945 + acx_unlock(priv, flags);
8951 +/*----------------------------------------------------------------
8953 +*----------------------------------------------------------------*/
8954 +static struct net_device_stats*
8955 +acx_e_get_stats(netdevice_t *dev)
8957 + wlandevice_t *priv = netdev_priv(dev);
8958 + return &priv->stats;
8962 +/*----------------------------------------------------------------
8963 +* acx_e_get_wireless_stats
8964 +*----------------------------------------------------------------*/
8965 +static struct iw_statistics*
8966 +acx_e_get_wireless_stats(netdevice_t *dev)
8968 + wlandevice_t *priv = netdev_priv(dev);
8969 + return &priv->wstats;
8973 +/*----------------------------------------------------------------
8974 +* acx_i_set_multicast_list
8975 +* FIXME: most likely needs refinement
8976 +*----------------------------------------------------------------*/
8978 +acx_i_set_multicast_list(netdevice_t *dev)
8980 + wlandevice_t *priv = netdev_priv(dev);
8981 + unsigned long flags;
8985 + acx_lock(priv, flags);
8987 + /* firmwares don't have allmulti capability,
8988 + * so just use promiscuous mode instead in this case. */
8989 + if (dev->flags & (IFF_PROMISC|IFF_ALLMULTI)) {
8990 + SET_BIT(priv->rx_config_1, RX_CFG1_RCV_PROMISCUOUS);
8991 + CLEAR_BIT(priv->rx_config_1, RX_CFG1_FILTER_ALL_MULTI);
8992 + SET_BIT(priv->set_mask, SET_RXCONFIG);
8993 + /* let kernel know in case *we* needed to set promiscuous */
8994 + dev->flags |= (IFF_PROMISC|IFF_ALLMULTI);
8996 + CLEAR_BIT(priv->rx_config_1, RX_CFG1_RCV_PROMISCUOUS);
8997 + SET_BIT(priv->rx_config_1, RX_CFG1_FILTER_ALL_MULTI);
8998 + SET_BIT(priv->set_mask, SET_RXCONFIG);
8999 + dev->flags &= ~(IFF_PROMISC|IFF_ALLMULTI);
9002 + /* cannot update card settings directly here, atomic context */
9003 + acx_schedule_after_interrupt_task(priv, ACX_AFTER_IRQ_UPDATE_CARD_CFG);
9005 + acx_unlock(priv, flags);
9011 +acx_l_update_link_quality_led(wlandevice_t *priv)
9015 + qual = acx_signal_determine_quality(priv->wstats.qual.level, priv->wstats.qual.noise);
9016 + if (qual > priv->brange_max_quality)
9017 + qual = priv->brange_max_quality;
9019 + if (time_after(jiffies, priv->brange_time_last_state_change +
9020 + (HZ/2 - HZ/2 * (unsigned long) qual/priv->brange_max_quality ) )) {
9021 + acx_l_power_led(priv, (priv->brange_last_state == 0));
9022 + priv->brange_last_state ^= 1; /* toggle */
9023 + priv->brange_time_last_state_change = jiffies;
9028 +/*----------------------------------------------------------------
9030 +*----------------------------------------------------------------*/
9032 +acx_l_enable_irq(wlandevice_t *priv)
9035 + acx_write_reg16(priv, IO_ACX_IRQ_MASK, priv->irq_mask);
9036 + acx_write_reg16(priv, IO_ACX_FEMR, 0x8000);
9037 + priv->irqs_active = 1;
9042 +/*----------------------------------------------------------------
9043 +* acx_l_disable_irq
9044 +*----------------------------------------------------------------*/
9046 +acx_l_disable_irq(wlandevice_t *priv)
9049 + acx_write_reg16(priv, IO_ACX_IRQ_MASK, priv->irq_mask_off);
9050 + acx_write_reg16(priv, IO_ACX_FEMR, 0x0);
9051 + priv->irqs_active = 0;
9055 +/* scan is complete. all frames now on the receive queue are valid */
9056 +#define INFO_SCAN_COMPLETE 0x0001
9057 +#define INFO_WEP_KEY_NOT_FOUND 0x0002
9058 +/* hw has been reset as the result of a watchdog timer timeout */
9059 +#define INFO_WATCH_DOG_RESET 0x0003
9060 +/* failed to send out NULL frame from PS mode notification to AP */
9061 +/* recommended action: try entering 802.11 PS mode again */
9062 +#define INFO_PS_FAIL 0x0004
9063 +/* encryption/decryption process on a packet failed */
9064 +#define INFO_IV_ICV_FAILURE 0x0005
9067 +acx_l_handle_info_irq(wlandevice_t *priv)
9070 + static const char * const info_type_msg[] = {
9073 + "WEP key not found",
9074 + "internal watchdog reset was done",
9075 + "failed to send powersave (NULL frame) notification to AP",
9076 + "encrypt/decrypt on a packet has failed",
9077 + "TKIP tx keys disabled",
9078 + "TKIP rx keys disabled",
9079 + "TKIP rx: key ID not found",
9087 + "TKIP IV value exceeds thresh"
9090 + acx_read_info_status(priv);
9091 + acxlog(L_IRQ, "got Info IRQ: status 0x%04X type 0x%04X: %s\n",
9092 + priv->info_status, priv->info_type,
9093 + info_type_msg[(priv->info_type >= VEC_SIZE(info_type_msg)) ?
9094 + 0 : priv->info_type]
9099 +/*----------------------------------------------------------------
9102 +* IRQ handler (atomic context, must not sleep, blah, blah)
9103 +*----------------------------------------------------------------*/
9105 +acx_log_unusual_irq(u16 irqtype) {
9107 + if (!printk_ratelimit())
9111 + printk("acx: got");
9112 + if (irqtype & HOST_INT_RX_DATA) {
9113 + printk(" Rx_Data");
9115 + /* HOST_INT_TX_COMPLETE */
9116 + if (irqtype & HOST_INT_TX_XFER) {
9117 + printk(" Tx_Xfer");
9119 + /* HOST_INT_RX_COMPLETE */
9120 + if (irqtype & HOST_INT_DTIM) {
9123 + if (irqtype & HOST_INT_BEACON) {
9124 + printk(" Beacon");
9126 + if (irqtype & HOST_INT_TIMER) {
9127 + acxlog(L_IRQ, " Timer");
9129 + if (irqtype & HOST_INT_KEY_NOT_FOUND) {
9130 + printk(" Key_Not_Found");
9132 + if (irqtype & HOST_INT_IV_ICV_FAILURE) {
9133 + printk(" IV_ICV_Failure");
9135 + /* HOST_INT_CMD_COMPLETE */
9136 + /* HOST_INT_INFO */
9137 + if (irqtype & HOST_INT_OVERFLOW) {
9138 + printk(" Overflow");
9140 + if (irqtype & HOST_INT_PROCESS_ERROR) {
9141 + printk(" Process_Error");
9143 + /* HOST_INT_SCAN_COMPLETE */
9144 + if (irqtype & HOST_INT_FCS_THRESHOLD) {
9145 + printk(" FCS_Threshold");
9147 + if (irqtype & HOST_INT_UNKNOWN) {
9148 + printk(" Unknown");
9150 + printk(" IRQ(s)\n");
9154 +acx_i_interrupt(int irq, void *dev_id, struct pt_regs *regs)
9156 + wlandevice_t *priv;
9157 + unsigned long flags;
9158 + unsigned int irqcount = MAX_IRQLOOPS_PER_JIFFY;
9159 + u16 irqtype, unmasked;
9161 + priv = (wlandevice_t *) (((netdevice_t *) dev_id)->priv);
9163 + /* LOCKING: can just spin_lock() since IRQs are disabled anyway.
9164 + * I am paranoid */
9165 + acx_lock(priv, flags);
9167 + unmasked = acx_read_reg16(priv, IO_ACX_IRQ_STATUS_CLEAR);
9168 + if (unlikely(0xffff == unmasked)) {
9169 + /* 0xffff value hints at missing hardware,
9170 + * so don't do anything.
9171 + * FIXME: that's not very clean - maybe we are able to
9172 + * establish a flag which definitely tells us that some
9173 + * hardware is absent and which we could check here?
9174 + * Hmm, but other drivers do the very same thing... */
9175 + acxlog(L_IRQ, "IRQ type:FFFF - device removed? IRQ_NONE\n");
9179 + /* We will check only "interesting" IRQ types */
9180 + irqtype = unmasked & ~priv->irq_mask;
9182 + /* We are on a shared IRQ line and it wasn't our IRQ */
9183 + acxlog(L_IRQ, "IRQ type:%04X, mask:%04X - all are masked, IRQ_NONE\n",
9184 + unmasked, priv->irq_mask);
9188 + /* Done here because IRQ_NONEs taking three lines of log
9189 + ** drive me crazy */
9192 +#define IRQ_ITERATE 1
9194 +if (jiffies != priv->irq_last_jiffies) {
9195 + priv->irq_loops_this_jiffy = 0;
9196 + priv->irq_last_jiffies = jiffies;
9199 +/* safety condition; we'll normally abort loop below
9200 + * in case no IRQ type occurred */
9201 +while (--irqcount) {
9203 + /* ACK all IRQs asap */
9204 + acx_write_reg16(priv, IO_ACX_IRQ_ACK, 0xffff);
9206 + acxlog(L_IRQ, "IRQ type:%04X, mask:%04X, type & ~mask:%04X\n",
9207 + unmasked, priv->irq_mask, irqtype);
9209 + /* Handle most important IRQ types first */
9210 + if (irqtype & HOST_INT_RX_COMPLETE) {
9211 + acxlog(L_IRQ, "got Rx_Complete IRQ\n");
9212 + acx_l_process_rx_desc(priv);
9214 + if (irqtype & HOST_INT_TX_COMPLETE) {
9215 + acxlog(L_IRQ, "got Tx_Complete IRQ\n");
9216 + /* don't clean up on each Tx complete, wait a bit
9217 + * unless we're going towards full, in which case
9218 + * we do it immediately, too (otherwise we might lockup
9219 + * with a full Tx buffer if we go into
9220 + * acx_l_clean_tx_desc() at a time when we won't wakeup
9221 + * the net queue in there for some reason...) */
9222 + if (priv->tx_free <= TX_START_CLEAN) {
9223 +#if TX_CLEANUP_IN_SOFTIRQ
9224 + acx_schedule_after_interrupt_task(priv, ACX_AFTER_IRQ_TX_CLEANUP);
9226 + acx_l_clean_tx_desc(priv);
9231 + /* Less frequent ones */
9233 + | HOST_INT_CMD_COMPLETE
9235 + | HOST_INT_SCAN_COMPLETE
9237 + if (irqtype & HOST_INT_CMD_COMPLETE) {
9238 + acxlog(L_IRQ, "got Command_Complete IRQ\n");
9239 + /* save the state for the running issue_cmd() */
9240 + SET_BIT(priv->irq_status, HOST_INT_CMD_COMPLETE);
9242 + if (irqtype & HOST_INT_INFO) {
9243 + acx_l_handle_info_irq(priv);
9245 + if (irqtype & HOST_INT_SCAN_COMPLETE) {
9246 + acxlog(L_IRQ, "got Scan_Complete IRQ\n");
9247 + /* need to do that in process context */
9248 + acx_schedule_after_interrupt_task(priv, ACX_AFTER_IRQ_COMPLETE_SCAN);
9249 + /* remember that fw is not scanning anymore */
9250 + SET_BIT(priv->irq_status, HOST_INT_SCAN_COMPLETE);
9254 + /* These we just log, but either they happen rarely
9255 + * or we keep them masked out */
9257 + | HOST_INT_RX_DATA
9258 + /* | HOST_INT_TX_COMPLETE */
9259 + | HOST_INT_TX_XFER
9260 + /* | HOST_INT_RX_COMPLETE */
9264 + | HOST_INT_KEY_NOT_FOUND
9265 + | HOST_INT_IV_ICV_FAILURE
9266 + /* | HOST_INT_CMD_COMPLETE */
9267 + /* | HOST_INT_INFO */
9268 + | HOST_INT_OVERFLOW
9269 + | HOST_INT_PROCESS_ERROR
9270 + /* | HOST_INT_SCAN_COMPLETE */
9271 + | HOST_INT_FCS_THRESHOLD
9272 + | HOST_INT_UNKNOWN
9274 + acx_log_unusual_irq(irqtype);
9278 + unmasked = acx_read_reg16(priv, IO_ACX_IRQ_STATUS_CLEAR);
9279 + irqtype = unmasked & ~priv->irq_mask;
9280 + /* Bail out if no new IRQ bits or if all are masked out */
9284 + if (unlikely(++priv->irq_loops_this_jiffy > MAX_IRQLOOPS_PER_JIFFY)) {
9285 + printk(KERN_ERR "acx: too many interrupts per jiffy!\n");
9286 + /* Looks like card floods us with IRQs! Try to stop that */
9287 + acx_write_reg16(priv, IO_ACX_IRQ_MASK, 0xffff);
9288 + /* This will short-circuit all future attempts to handle IRQ.
9289 + * We cant do much more... */
9290 + priv->irq_mask = 0;
9295 + /* Routine to perform blink with range */
9296 + if (unlikely(priv->led_power == 2))
9297 + acx_l_update_link_quality_led(priv);
9300 + /* acx_write_flush(priv); - not needed, last op was read anyway */
9301 + acx_unlock(priv, flags);
9303 + return IRQ_HANDLED;
9306 + acx_unlock(priv, flags);
9311 +/*----------------------------------------------------------------
9313 +*----------------------------------------------------------------*/
9315 +acx_l_power_led(wlandevice_t *priv, int enable)
9317 + u16 gpio_pled = IS_ACX111(priv) ? 0x0040 : 0x0800;
9319 + /* A hack. Not moving message rate limiting to priv->xxx
9320 + * (it's only a debug message after all) */
9321 + static int rate_limit = 0;
9323 + if (rate_limit++ < 3)
9324 + acxlog(L_IOCTL, "Please report in case toggling the power "
9325 + "LED doesn't work for your card!\n");
9327 + acx_write_reg16(priv, IO_ACX_GPIO_OUT,
9328 + acx_read_reg16(priv, IO_ACX_GPIO_OUT) & ~gpio_pled);
9330 + acx_write_reg16(priv, IO_ACX_GPIO_OUT,
9331 + acx_read_reg16(priv, IO_ACX_GPIO_OUT) | gpio_pled);
9335 +/***********************************************************************
9339 +/***********************************************************************
9342 +acx111pci_ioctl_info(
9343 + struct net_device *dev,
9344 + struct iw_request_info *info,
9345 + struct iw_param *vwrq,
9349 + wlandevice_t *priv = netdev_priv(dev);
9352 + rxhostdesc_t *rxhostdesc;
9353 + txhostdesc_t *txhostdesc;
9354 + struct acx111_ie_memoryconfig memconf;
9355 + struct acx111_ie_queueconfig queueconf;
9356 + unsigned long flags;
9358 + char memmap[0x34];
9359 + char rxconfig[0x8];
9360 + char fcserror[0x8];
9361 + char ratefallback[0x5];
9363 + if ( !(acx_debug & (L_IOCTL|L_DEBUG)) )
9365 + /* using printk() since we checked debug flag already */
9367 + acx_sem_lock(priv);
9369 + if (!IS_ACX111(priv)) {
9370 + printk("acx111-specific function called "
9371 + "with non-acx111 chip, aborting\n");
9375 + /* get Acx111 Memory Configuration */
9376 + memset(&memconf, 0, sizeof(memconf));
9377 + /* BTW, fails with 12 (Write only) error code.
9378 + ** Retained for easy testing of issue_cmd error handling :) */
9379 + acx_s_interrogate(priv, &memconf, ACX1xx_IE_QUEUE_CONFIG);
9381 + /* get Acx111 Queue Configuration */
9382 + memset(&queueconf, 0, sizeof(queueconf));
9383 + acx_s_interrogate(priv, &queueconf, ACX1xx_IE_MEMORY_CONFIG_OPTIONS);
9385 + /* get Acx111 Memory Map */
9386 + memset(memmap, 0, sizeof(memmap));
9387 + acx_s_interrogate(priv, &memmap, ACX1xx_IE_MEMORY_MAP);
9389 + /* get Acx111 Rx Config */
9390 + memset(rxconfig, 0, sizeof(rxconfig));
9391 + acx_s_interrogate(priv, &rxconfig, ACX1xx_IE_RXCONFIG);
9393 + /* get Acx111 fcs error count */
9394 + memset(fcserror, 0, sizeof(fcserror));
9395 + acx_s_interrogate(priv, &fcserror, ACX1xx_IE_FCS_ERROR_COUNT);
9397 + /* get Acx111 rate fallback */
9398 + memset(ratefallback, 0, sizeof(ratefallback));
9399 + acx_s_interrogate(priv, &ratefallback, ACX1xx_IE_RATE_FALLBACK);
9401 + /* force occurrence of a beacon interrupt */
9402 + /* TODO: comment why is this necessary */
9403 + acx_write_reg16(priv, IO_ACX_HINT_TRIG, HOST_INT_BEACON);
9405 + /* dump Acx111 Mem Configuration */
9406 + printk("dump mem config:\n"
9407 + "data read: %d, struct size: %d\n"
9408 + "Number of stations: %1X\n"
9409 + "Memory block size: %1X\n"
9410 + "tx/rx memory block allocation: %1X\n"
9411 + "count rx: %X / tx: %X queues\n"
9413 + "fragmentation %1X\n"
9414 + "Rx Queue 1 Count Descriptors: %X\n"
9415 + "Rx Queue 1 Host Memory Start: %X\n"
9416 + "Tx Queue 1 Count Descriptors: %X\n"
9417 + "Tx Queue 1 Attributes: %X\n",
9418 + memconf.len, (int) sizeof(memconf),
9419 + memconf.no_of_stations,
9420 + memconf.memory_block_size,
9421 + memconf.tx_rx_memory_block_allocation,
9422 + memconf.count_rx_queues, memconf.count_tx_queues,
9424 + memconf.fragmentation,
9425 + memconf.rx_queue1_count_descs,
9426 + acx2cpu(memconf.rx_queue1_host_rx_start),
9427 + memconf.tx_queue1_count_descs,
9428 + memconf.tx_queue1_attributes);
9430 + /* dump Acx111 Queue Configuration */
9431 + printk("dump queue head:\n"
9432 + "data read: %d, struct size: %d\n"
9433 + "tx_memory_block_address (from card): %X\n"
9434 + "rx_memory_block_address (from card): %X\n"
9435 + "rx1_queue address (from card): %X\n"
9436 + "tx1_queue address (from card): %X\n"
9437 + "tx1_queue attributes (from card): %X\n",
9438 + queueconf.len, (int) sizeof(queueconf),
9439 + queueconf.tx_memory_block_address,
9440 + queueconf.rx_memory_block_address,
9441 + queueconf.rx1_queue_address,
9442 + queueconf.tx1_queue_address,
9443 + queueconf.tx1_attributes);
9445 + /* dump Acx111 Mem Map */
9446 + printk("dump mem map:\n"
9447 + "data read: %d, struct size: %d\n"
9448 + "Code start: %X\n"
9450 + "WEP default key start: %X\n"
9451 + "WEP default key end: %X\n"
9452 + "STA table start: %X\n"
9453 + "STA table end: %X\n"
9454 + "Packet template start: %X\n"
9455 + "Packet template end: %X\n"
9456 + "Queue memory start: %X\n"
9457 + "Queue memory end: %X\n"
9458 + "Packet memory pool start: %X\n"
9459 + "Packet memory pool end: %X\n"
9462 + *((u16 *)&memmap[0x02]), (int) sizeof(memmap),
9463 + *((u32 *)&memmap[0x04]),
9464 + *((u32 *)&memmap[0x08]),
9465 + *((u32 *)&memmap[0x0C]),
9466 + *((u32 *)&memmap[0x10]),
9467 + *((u32 *)&memmap[0x14]),
9468 + *((u32 *)&memmap[0x18]),
9469 + *((u32 *)&memmap[0x1C]),
9470 + *((u32 *)&memmap[0x20]),
9471 + *((u32 *)&memmap[0x24]),
9472 + *((u32 *)&memmap[0x28]),
9473 + *((u32 *)&memmap[0x2C]),
9474 + *((u32 *)&memmap[0x30]),
9478 + /* dump Acx111 Rx Config */
9479 + printk("dump rx config:\n"
9480 + "data read: %d, struct size: %d\n"
9482 + "rx filter config: %X\n",
9483 + *((u16 *)&rxconfig[0x02]), (int) sizeof(rxconfig),
9484 + *((u16 *)&rxconfig[0x04]),
9485 + *((u16 *)&rxconfig[0x06]));
9487 + /* dump Acx111 fcs error */
9488 + printk("dump fcserror:\n"
9489 + "data read: %d, struct size: %d\n"
9490 + "fcserrors: %X\n",
9491 + *((u16 *)&fcserror[0x02]), (int) sizeof(fcserror),
9492 + *((u32 *)&fcserror[0x04]));
9494 + /* dump Acx111 rate fallback */
9495 + printk("dump rate fallback:\n"
9496 + "data read: %d, struct size: %d\n"
9497 + "ratefallback: %X\n",
9498 + *((u16 *)&ratefallback[0x02]), (int) sizeof(ratefallback),
9499 + *((u8 *)&ratefallback[0x04]));
9501 + /* protect against IRQ */
9502 + acx_lock(priv, flags);
9504 + /* dump acx111 internal rx descriptor ring buffer */
9505 + rxdesc = priv->rxdesc_start;
9507 + /* loop over complete receive pool */
9508 + if (rxdesc) for (i = 0; i < RX_CNT; i++) {
9509 + printk("\ndump internal rxdesc %d:\n"
9512 + "acx mem pointer (dynamic) 0x%X\n"
9513 + "CTL (dynamic) 0x%X\n"
9514 + "Rate (dynamic) 0x%X\n"
9515 + "RxStatus (dynamic) 0x%X\n"
9516 + "Mod/Pre (dynamic) 0x%X\n",
9519 + acx2cpu(rxdesc->pNextDesc),
9520 + acx2cpu(rxdesc->ACXMemPtr),
9528 + /* dump host rx descriptor ring buffer */
9530 + rxhostdesc = priv->rxhostdesc_start;
9532 + /* loop over complete receive pool */
9533 + if (rxhostdesc) for (i = 0; i < RX_CNT; i++) {
9534 + printk("\ndump host rxdesc %d:\n"
9536 + "buffer mem pos 0x%X\n"
9537 + "buffer mem offset 0x%X\n"
9544 + acx2cpu(rxhostdesc->data_phy),
9545 + rxhostdesc->data_offset,
9546 + le16_to_cpu(rxhostdesc->Ctl_16),
9547 + le16_to_cpu(rxhostdesc->length),
9548 + acx2cpu(rxhostdesc->desc_phy_next),
9549 + rxhostdesc->Status);
9553 + /* dump acx111 internal tx descriptor ring buffer */
9554 + txdesc = priv->txdesc_start;
9556 + /* loop over complete transmit pool */
9557 + if (txdesc) for (i = 0; i < TX_CNT; i++) {
9558 + printk("\ndump internal txdesc %d:\n"
9562 + "acx mem pointer (dynamic) 0x%X\n"
9563 + "host mem pointer (dynamic) 0x%X\n"
9564 + "length (dynamic) 0x%X\n"
9565 + "CTL (dynamic) 0x%X\n"
9566 + "CTL2 (dynamic) 0x%X\n"
9567 + "Status (dynamic) 0x%X\n"
9568 + "Rate (dynamic) 0x%X\n",
9570 + (int) sizeof(struct txdesc),
9572 + acx2cpu(txdesc->pNextDesc),
9573 + acx2cpu(txdesc->AcxMemPtr),
9574 + acx2cpu(txdesc->HostMemPtr),
9575 + le16_to_cpu(txdesc->total_length),
9577 + txdesc->Ctl2_8, txdesc->error,
9578 + txdesc->u.r1.rate);
9579 + txdesc = move_txdesc(priv, txdesc, 1);
9582 + /* dump host tx descriptor ring buffer */
9584 + txhostdesc = priv->txhostdesc_start;
9586 + /* loop over complete host send pool */
9587 + if (txhostdesc) for (i = 0; i < TX_CNT * 2; i++) {
9588 + printk("\ndump host txdesc %d:\n"
9590 + "buffer mem pos 0x%X\n"
9591 + "buffer mem offset 0x%X\n"
9598 + acx2cpu(txhostdesc->data_phy),
9599 + txhostdesc->data_offset,
9600 + le16_to_cpu(txhostdesc->Ctl_16),
9601 + le16_to_cpu(txhostdesc->length),
9602 + acx2cpu(txhostdesc->desc_phy_next),
9603 + le32_to_cpu(txhostdesc->Status));
9607 + /* acx_write_reg16(priv, 0xb4, 0x4); */
9609 + acx_unlock(priv, flags);
9612 + acx_sem_unlock(priv);
9613 +#endif /* ACX_DEBUG */
9618 +/***********************************************************************
9621 +acx100pci_ioctl_set_phy_amp_bias(
9622 + struct net_device *dev,
9623 + struct iw_request_info *info,
9624 + struct iw_param *vwrq,
9627 + wlandevice_t *priv = netdev_priv(dev);
9628 + unsigned long flags;
9631 + if (!IS_ACX100(priv)) {
9633 + * Removing this check *might* damage
9634 + * hardware, since we're tweaking GPIOs here after all!!!
9635 + * You've been warned...
9637 + printk("acx: sorry, setting bias level for non-acx100 "
9638 + "is not supported yet\n");
9643 + printk("acx: invalid bias parameter, range is 0-7\n");
9647 + acx_sem_lock(priv);
9649 + /* Need to lock accesses to [IO_ACX_GPIO_OUT]:
9650 + * IRQ handler uses it to update LED */
9651 + acx_lock(priv, flags);
9652 + gpio_old = acx_read_reg16(priv, IO_ACX_GPIO_OUT);
9653 + acx_write_reg16(priv, IO_ACX_GPIO_OUT, (gpio_old & 0xf8ff) | ((u16)*extra << 8));
9654 + acx_unlock(priv, flags);
9656 + acxlog(L_DEBUG, "gpio_old: 0x%04X\n", gpio_old);
9657 + printk("%s: PHY power amplifier bias: old:%d, new:%d\n",
9659 + (gpio_old & 0x0700) >> 8, (unsigned char)*extra);
9661 + acx_sem_unlock(priv);
9667 +/***************************************************************
9668 +** acxpci_l_alloc_tx
9669 +** Actually returns a txdesc_t* ptr
9672 +acxpci_l_alloc_tx(wlandevice_t* priv)
9674 + struct txdesc *txdesc;
9679 + txdesc = get_txdesc(priv, priv->tx_head);
9680 + ctl8 = txdesc->Ctl_8;
9681 + if (unlikely(DESC_CTL_HOSTOWN != (ctl8 & DESC_CTL_DONE))) {
9682 + /* whoops, descr at current index is not free, so probably
9683 + * ring buffer already full */
9684 + /* FIXME: this causes a deadlock situation (endless
9685 + * loop) in case the current descriptor remains busy,
9686 + * so handle it a bit better in the future!! */
9687 + printk("acx: BUG: tx_head->Ctl8=0x%02X, (0x%02X & "
9688 + "0x"DESC_CTL_DONE_STR") != 0x"DESC_CTL_HOSTOWN_STR
9689 + ": failed to find free tx descr\n",
9696 + acxlog(L_BUFT, "tx: got desc %u, %u remain\n",
9697 + priv->tx_head, priv->tx_free);
9700 + * This comment is probably not entirely correct, needs further discussion
9701 + * (restored commented-out code below to fix Tx ring buffer overflow,
9702 + * since it's much better to have a slightly less efficiently used ring
9703 + * buffer rather than one which easily overflows):
9705 + * This doesn't do anything other than limit our maximum number of
9706 + * buffers used at a single time (we might as well just declare
9707 + * TX_STOP_QUEUE less descriptors when we open up.) We should just let it
9708 + * slide here, and back off TX_STOP_QUEUE in acx_l_clean_tx_desc, when given the
9709 + * opportunity to let the queue start back up.
9711 + if (priv->tx_free < TX_STOP_QUEUE) {
9712 + acxlog(L_BUF, "stop queue (%u tx desc left)\n",
9714 + acx_stop_queue(priv->netdev, NULL);
9717 + /* returning current descriptor, so advance to next free one */
9718 + priv->tx_head = (priv->tx_head + 1) % TX_CNT;
9722 + return (tx_t*)txdesc;
9726 +/***********************************************************************
9729 +acxpci_l_get_txbuf(wlandevice_t *priv, tx_t* tx_opaque)
9731 + return acx_get_txhostdesc(priv, (txdesc_t*)tx_opaque)->data;
9735 +/***********************************************************************
9736 +** acxpci_l_tx_data
9738 +** Can be called from IRQ (rx -> (AP bridging or mgmt response) -> tx).
9739 +** Can be called from acx_i_start_xmit (data frames from net core).
9742 +acxpci_l_tx_data(wlandevice_t *priv, tx_t* tx_opaque, int len)
9744 + txdesc_t *txdesc = (txdesc_t*)tx_opaque;
9745 + txhostdesc_t *hostdesc1, *hostdesc2;
9751 + /* fw doesn't tx such packets anyhow */
9752 + if (len < WLAN_HDR_A3_LEN)
9755 + hostdesc1 = acx_get_txhostdesc(priv, txdesc);
9756 + hostdesc2 = hostdesc1 + 1;
9758 + /* modify flag status in separate variable to be able to write it back
9759 + * in one big swoop later (also in order to have less device memory
9761 + Ctl_8 = txdesc->Ctl_8;
9762 + Ctl2_8 = txdesc->Ctl2_8;
9764 + /* DON'T simply set Ctl field to 0 here globally,
9765 + * it needs to maintain a consistent flag status (those are state flags!!),
9766 + * otherwise it may lead to severe disruption. Only set or reset particular
9767 + * flags at the exact moment this is needed...
9768 + * FIXME: what about Ctl2? Equally problematic? */
9770 + /* let chip do RTS/CTS handshaking before sending
9771 + * in case packet size exceeds threshold */
9772 + if (len > priv->rts_threshold)
9773 + SET_BIT(Ctl2_8, DESC_CTL2_RTS);
9775 + CLEAR_BIT(Ctl2_8, DESC_CTL2_RTS);
9778 + if (priv->wep_enabled)
9779 + SET_BIT(Ctl2_8, DESC_CTL2_WEP);
9781 + CLEAR_BIT(Ctl2_8, DESC_CTL2_WEP);
9784 + switch (priv->mode) {
9785 + case ACX_MODE_0_ADHOC:
9786 + case ACX_MODE_3_AP:
9787 + clt = acx_l_sta_list_get(priv, ((wlan_hdr_t*)hostdesc1->data)->a1);
9789 + case ACX_MODE_2_STA:
9790 + clt = priv->ap_client;
9793 +/* testing was done on acx111: */
9794 + case ACX_MODE_MONITOR:
9796 +/* sends CTS to self before packet */
9797 + + DESC_CTL2_SEQ /* don't increase sequence field */
9798 +/* not working (looks like good fcs is still added) */
9799 + + DESC_CTL2_FCS /* don't add the FCS */
9801 + + DESC_CTL2_MORE_FRAG
9803 + + DESC_CTL2_RETRY /* don't increase retry field */
9805 + + DESC_CTL2_POWER /* don't increase power mgmt. field */
9807 + + DESC_CTL2_WEP /* encrypt this frame */
9809 + + DESC_CTL2_DUR /* don't increase duration field */
9813 + default: /* ACX_MODE_OFF, ACX_MODE_MONITOR */
9818 + if (unlikely(clt && !clt->rate_cur)) {
9819 + printk("acx: driver bug! bad ratemask\n");
9823 + /* used in tx cleanup routine for auto rate and accounting: */
9824 + acx_put_txc(priv, txdesc, clt);
9826 + txdesc->total_length = cpu_to_le16(len);
9827 + hostdesc2->length = cpu_to_le16(len - WLAN_HDR_A3_LEN);
9828 + if (IS_ACX111(priv)) {
9829 + u16 rate_cur = clt ? clt->rate_cur : priv->rate_bcast;
9830 + /* note that if !txdesc->do_auto, txrate->cur
9831 + ** has only one nonzero bit */
9832 + txdesc->u.r2.rate111 = cpu_to_le16(
9834 + /* WARNING: I was never able to make it work with prism54 AP.
9835 + ** It was falling down to 1Mbit where shortpre is not applicable,
9836 + ** and not working at all at "5,11 basic rates only" setting.
9837 + ** I even didn't see tx packets in radio packet capture.
9838 + ** Disabled for now --vda */
9839 + /*| ((clt->shortpre && clt->cur!=RATE111_1) ? RATE111_SHORTPRE : 0) */
9841 +#ifdef TODO_FIGURE_OUT_WHEN_TO_SET_THIS
9842 + /* should add this to rate111 above as necessary */
9843 + | (clt->pbcc511 ? RATE111_PBCC511 : 0)
9845 + hostdesc1->length = cpu_to_le16(len);
9846 + } else { /* ACX100 */
9847 + u8 rate_100 = clt ? clt->rate_100 : priv->rate_bcast100;
9848 + txdesc->u.r1.rate = rate_100;
9849 +#ifdef TODO_FIGURE_OUT_WHEN_TO_SET_THIS
9850 + if (clt->pbcc511) {
9851 + if (n == RATE100_5 || n == RATE100_11)
9852 + n |= RATE100_PBCC511;
9855 + if (clt->shortpre && (clt->cur != RATE111_1))
9856 + SET_BIT(Ctl_8, DESC_CTL_SHORT_PREAMBLE); /* set Short Preamble */
9858 + /* set autodma and reclaim and 1st mpdu */
9859 + SET_BIT(Ctl_8, DESC_CTL_AUTODMA | DESC_CTL_RECLAIM | DESC_CTL_FIRSTFRAG);
9860 + hostdesc1->length = cpu_to_le16(WLAN_HDR_A3_LEN);
9862 + /* don't need to clean ack/rts statistics here, already
9863 + * done on descr cleanup */
9865 + /* clears Ctl DESC_CTL_HOSTOWN bit, thus telling that the descriptors
9866 + * are now owned by the acx100; do this as LAST operation */
9867 + CLEAR_BIT(Ctl_8, DESC_CTL_HOSTOWN);
9868 + /* flush writes before we release hostdesc to the adapter here */
9870 + CLEAR_BIT(hostdesc1->Ctl_16, cpu_to_le16(DESC_CTL_HOSTOWN));
9871 + CLEAR_BIT(hostdesc2->Ctl_16, cpu_to_le16(DESC_CTL_HOSTOWN));
9873 + /* write back modified flags */
9874 + txdesc->Ctl2_8 = Ctl2_8;
9875 + txdesc->Ctl_8 = Ctl_8;
9877 + /* unused: txdesc->tx_time = cpu_to_le32(jiffies); */
9878 +//TODO: should it be a mmiowb() instead? we are protecting against race with write[bwl]()
9879 + /* flush writes before we tell the adapter that it's its turn now */
9881 + acx_write_reg16(priv, IO_ACX_INT_TRIG, INT_TRIG_TXPRC);
9882 + acx_write_flush(priv);
9884 + /* log the packet content AFTER sending it,
9885 + * in order to not delay sending any further than absolutely needed
9886 + * Do separate logs for acx100/111 to have human-readable rates */
9887 + if (unlikely(acx_debug & (L_XFER|L_DATA))) {
9888 + u16 fc = ((wlan_hdr_t*)hostdesc1->data)->fc;
9889 + if (IS_ACX111(priv))
9890 + printk("tx: pkt (%s): len %d "
9891 + "rate %04X%s status %u\n",
9892 + acx_get_packet_type_string(le16_to_cpu(fc)), len,
9893 + le16_to_cpu(txdesc->u.r2.rate111),
9894 + (le16_to_cpu(txdesc->u.r2.rate111) & RATE111_SHORTPRE) ? "(SPr)" : "",
9897 + printk("tx: pkt (%s): len %d rate %03u%s status %u\n",
9898 + acx_get_packet_type_string(fc), len,
9899 + txdesc->u.r1.rate,
9900 + (Ctl_8 & DESC_CTL_SHORT_PREAMBLE) ? "(SPr)" : "",
9903 + if (acx_debug & L_DATA) {
9904 + printk("tx: 802.11 [%d]: ", len);
9905 + acx_dump_bytes(hostdesc1->data, len);
9913 +/***********************************************************************
9916 +acx_l_handle_tx_error(wlandevice_t *priv, u8 error, unsigned int finger)
9918 + const char *err = "unknown error";
9920 + /* hmm, should we handle this as a mask
9921 + * of *several* bits?
9922 + * For now I think only caring about
9923 + * individual bits is ok... */
9926 + err = "no Tx due to error in other fragment";
9927 + priv->wstats.discard.fragment++;
9930 + err = "Tx aborted";
9931 + priv->stats.tx_aborted_errors++;
9934 + err = "Tx desc wrong parameters";
9935 + priv->wstats.discard.misc++;
9938 + err = "WEP key not found";
9939 + priv->wstats.discard.misc++;
9942 + err = "MSDU lifetime timeout? - try changing "
9943 + "'iwconfig retry lifetime XXX'";
9944 + priv->wstats.discard.misc++;
9947 + err = "excessive Tx retries due to either distance "
9948 + "too high or unable to Tx or Tx frame error - "
9949 + "try changing 'iwconfig txpower XXX' or "
9950 + "'sens'itivity or 'retry'";
9951 + priv->wstats.discard.retries++;
9952 + /* FIXME: set (GETSET_TX|GETSET_RX) here
9953 + * (this seems to recalib radio on ACX100)
9954 + * after some more jiffies passed??
9955 + * But OTOH Tx error 0x20 also seems to occur on
9956 + * overheating, so I'm not sure whether we
9957 + * actually want that, since people maybe won't notice
9958 + * then that their hardware is slowly getting
9960 + * Or is it still a safe long distance from utter
9961 + * radio non-functionality despite many radio
9963 + * to final destructive overheating of the hardware?
9964 + * In this case we really should do recalib here...
9965 + * I guess the only way to find out is to do a
9966 + * potentially fatal self-experiment :-\
9967 + * Or maybe only recalib in case we're using Tx
9968 + * rate auto (on errors switching to lower speed
9969 + * --> less heat?) or 802.11 power save mode? */
9971 + /* ok, just do it.
9972 + * ENABLE_TX|ENABLE_RX helps, so even do
9973 + * DISABLE_TX and DISABLE_RX in order to perhaps
9974 + * have more impact. */
9975 + if (++priv->retry_errors_msg_ratelimit % 4 == 0) {
9976 + if (priv->retry_errors_msg_ratelimit <= 20)
9977 + printk("%s: several excessive Tx "
9978 + "retry errors occurred, attempting "
9979 + "to recalibrate radio. Radio "
9980 + "drift might be caused by increasing "
9981 + "card temperature, please check the card "
9982 + "before it's too late!\n",
9983 + priv->netdev->name);
9984 + if (priv->retry_errors_msg_ratelimit == 20)
9985 + printk("disabling above "
9986 + "notification message\n");
9988 + acx_schedule_after_interrupt_task(priv, ACX_AFTER_IRQ_CMD_RADIO_RECALIB);
9992 + err = "Tx buffer overflow";
9993 + priv->stats.tx_fifo_errors++;
9996 + err = "DMA error";
9997 + priv->wstats.discard.misc++;
10000 + priv->stats.tx_errors++;
10001 + if (priv->stats.tx_errors <= 20)
10002 + printk("%s: tx error 0x%02X, buf %02u! (%s)\n",
10003 + priv->netdev->name, error, finger, err);
10005 + printk("%s: tx error 0x%02X, buf %02u!\n",
10006 + priv->netdev->name, error, finger);
10010 +/***********************************************************************
10012 +/* Theory of operation:
10013 +** client->rate_cap is a bitmask of rates client is capable of.
10014 +** client->rate_cfg is a bitmask of allowed (configured) rates.
10015 +** It is set as a result of iwconfig rate N [auto]
10016 +** or iwpriv set_rates "N,N,N N,N,N" commands.
10017 +** It can be fixed (e.g. 0x0080 == 18Mbit only),
10018 +** auto (0x00ff == 18Mbit or any lower value),
10019 +** and code handles any bitmask (0x1081 == try 54Mbit,18Mbit,1Mbit _only_).
10021 +** client->rate_cur is a value for rate111 field in tx descriptor.
10022 +** It is always set to txrate_cfg sans zero or more most significant
10023 +** bits. This routine handles selection of new rate_cur value depending on
10024 +** outcome of last tx event.
10026 +** client->rate_100 is a precalculated rate value for acx100
10027 +** (we can do without it, but will need to calculate it on each tx).
10029 +** You cannot configure mixed usage of 5.5 and/or 11Mbit rate
10030 +** with PBCC and CCK modulation. Either both at CCK or both at PBCC.
10031 +** In theory you can implement it, but so far it is considered not worth doing.
10033 +** 22Mbit, of course, is PBCC always. */
10035 +/* maps acx100 tx descr rate field to acx111 one */
10037 +rate100to111(u8 r)
10040 + case RATE100_1: return RATE111_1;
10041 + case RATE100_2: return RATE111_2;
10043 + case (RATE100_5 | RATE100_PBCC511): return RATE111_5;
10045 + case (RATE100_11 | RATE100_PBCC511): return RATE111_11;
10046 + case RATE100_22: return RATE111_22;
10048 + printk("acx: unexpected acx100 txrate: %u! "
10049 + "Please report\n", r);
10050 + return RATE111_2;
10056 +acx_l_handle_txrate_auto(wlandevice_t *priv, struct client *txc,
10057 + unsigned int idx, u8 rate100, u16 rate111, u8 error)
10060 + u16 cur = txc->rate_cur;
10061 + int slower_rate_was_used;
10063 + /* FIXME: need to implement some kind of rate success memory
10064 + * which stores the success percentage per rate, to be taken
10065 + * into account when considering allowing a new rate, since it
10066 + * doesn't really help to stupidly count fallback/stepup,
10067 + * since one invalid rate will spoil the party anyway
10068 + * (such as 22M in case of 11M-only peers) */
10070 + /* vda: hmm. current code will do this:
10071 + ** 1. send packets at 11 Mbit, stepup++
10072 + ** 2. will try to send at 22Mbit. hardware will see no ACK,
10073 + ** retries at 11Mbit, success. code notes that used rate
10074 + ** is lower. stepup = 0, fallback++
10075 + ** 3. repeat step 2 fallback_count times. Fall back to
10076 + ** 11Mbit. go to step 1.
10077 + ** If stepup_count is large (say, 16) and fallback_count
10078 + ** is small (3), this wouldn't be too bad wrt throughput */
10080 + /* do some preparations, i.e. calculate the one rate that was
10081 + * used to send this packet */
10082 + if (IS_ACX111(priv)) {
10083 + sent_rate = 1 << highest_bit(rate111 & RATE111_ALL);
10085 + sent_rate = rate100to111(rate100);
10087 + /* sent_rate has only one bit set now, corresponding to tx rate
10088 + * which was used by hardware to tx this particular packet */
10090 + /* now do the actual auto rate management */
10091 + acxlog(L_DEBUG, "tx: %sclient=%p/"MACSTR" used=%04X cur=%04X cfg=%04X "
10092 + "__=%u/%u ^^=%u/%u\n",
10093 + (txc->ignore_count > 0) ? "[IGN] " : "",
10094 + txc, MAC(txc->address), sent_rate, cur, txc->rate_cfg,
10095 + txc->fallback_count, priv->fallback_threshold,
10096 + txc->stepup_count, priv->stepup_threshold
10099 + /* we need to ignore old packets already in the tx queue since
10100 + * they use older rate bytes configured before our last rate change,
10101 + * otherwise our mechanism will get confused by interpreting old data.
10102 + * Do it here only, in order to have the logging above */
10103 + if (txc->ignore_count) {
10104 + txc->ignore_count--;
10108 + /* true only if the only nonzero bit in sent_rate is
10109 + ** less significant than highest nonzero bit in cur */
10110 + slower_rate_was_used = ( cur > ((sent_rate<<1)-1) );
10112 + if (slower_rate_was_used || (error & 0x30)) {
10113 + txc->stepup_count = 0;
10114 + if (++txc->fallback_count <= priv->fallback_threshold)
10116 + txc->fallback_count = 0;
10118 + /* clear highest 1 bit in cur */
10119 + sent_rate = RATE111_54;
10120 + while (!(cur & sent_rate)) sent_rate >>= 1;
10121 + CLEAR_BIT(cur, sent_rate);
10123 + if (cur) { /* we can't disable all rates! */
10124 + acxlog(L_XFER, "tx: falling back to ratemask %04X\n", cur);
10125 + txc->rate_cur = cur;
10126 + txc->ignore_count = TX_CNT - priv->tx_free;
10128 + } else if (!slower_rate_was_used) {
10129 + txc->fallback_count = 0;
10130 + if (++txc->stepup_count <= priv->stepup_threshold)
10132 + txc->stepup_count = 0;
10134 + /* sanitize. Sort of not needed, but I dont trust hw that much...
10135 + ** what if it can report bogus tx rates sometimes? */
10136 + while (!(cur & sent_rate)) sent_rate >>= 1;
10137 + /* try to find a higher sent_rate that isn't yet in our
10138 + * current set, but is an allowed cfg */
10141 + if (sent_rate > txc->rate_cfg)
10142 + /* no higher rates allowed by config */
10144 + if (!(cur & sent_rate) && (txc->rate_cfg & sent_rate))
10147 + /* not found, try higher one */
10149 + SET_BIT(cur, sent_rate);
10150 + acxlog(L_XFER, "tx: stepping up to ratemask %04X\n", cur);
10151 + txc->rate_cur = cur;
10152 + /* FIXME: totally bogus - we could be sending to many peers at once... */
10153 + txc->ignore_count = TX_CNT - priv->tx_free;
10156 + /* calculate acx100 style rate byte if needed */
10157 + if (IS_ACX100(priv)) {
10158 + txc->rate_100 = bitpos2rate100[highest_bit(cur)];
10163 +/*----------------------------------------------------------------
10164 +* acx_l_log_txbuffer
10165 +*----------------------------------------------------------------*/
10167 +static inline void acx_l_log_txbuffer(const wlandevice_t *priv) {}
10170 +acx_l_log_txbuffer(wlandevice_t *priv)
10172 + txdesc_t *txdesc;
10175 + /* no FN_ENTER here, we don't want that */
10176 + /* no locks here, since it's entirely non-critical code */
10177 + txdesc = priv->txdesc_start;
10178 + if (!txdesc) return;
10179 + for (i = 0; i < TX_CNT; i++) {
10180 + if ((txdesc->Ctl_8 & DESC_CTL_DONE) == DESC_CTL_DONE)
10181 + printk("tx: buf %d done\n", i);
10182 + txdesc = move_txdesc(priv, txdesc, 1);
10188 +/*----------------------------------------------------------------
10189 +* acx_l_clean_tx_desc
10191 +* This function resets the txdescs' status when the ACX100
10192 +* signals the TX done IRQ (txdescs have been processed), starting with
10193 +* the pool index of the descriptor which we would use next,
10194 +* in order to make sure that we can be as fast as possible
10195 +* in filling new txdescs.
10196 +* Oops, now we have our own index, so everytime we get called we know
10197 +* where the next packet to be cleaned is.
10198 +* Hmm, still need to loop through the whole ring buffer now,
10199 +* since we lost sync for some reason when ping flooding or so...
10200 +* (somehow we don't get the IRQ for acx_l_clean_tx_desc any more when
10201 +* too many packets are being sent!)
10202 +* FIXME: currently we only process one packet, but this gets out of
10203 +* sync for some reason when ping flooding, so we need to loop,
10204 +* but the previous smart loop implementation causes the ping latency
10205 +* to rise dramatically (~3000 ms), at least on CardBus PheeNet WL-0022.
10206 +* Dunno what to do :-\
10207 +*----------------------------------------------------------------*/
10209 +acx_l_clean_tx_desc(wlandevice_t *priv)
10211 + txdesc_t *txdesc;
10212 + struct client *txc;
10217 + u8 error, ack_failures, rts_failures, rts_ok, r100;
10221 + if (unlikely(acx_debug & L_DEBUG))
10222 + acx_l_log_txbuffer(priv);
10224 + acxlog(L_BUFT, "tx: cleaning up bufs from %u\n", priv->tx_tail);
10226 + finger = priv->tx_tail;
10228 + to_process = TX_CNT;
10230 + txdesc = get_txdesc(priv, finger);
10232 + /* abort if txdesc is not marked as "Tx finished" and "owned" */
10233 + if ((txdesc->Ctl_8 & DESC_CTL_DONE) != DESC_CTL_DONE) {
10234 + /* we do need to have at least one cleaned,
10235 + * otherwise we wouldn't get called in the first place
10241 + /* remember descr values... */
10242 + error = txdesc->error;
10243 + ack_failures = txdesc->ack_failures;
10244 + rts_failures = txdesc->rts_failures;
10245 + rts_ok = txdesc->rts_ok;
10246 + r100 = txdesc->u.r1.rate;
10247 + r111 = txdesc->u.r2.rate111;
10249 +#if WIRELESS_EXT > 13 /* wireless_send_event() and IWEVTXDROP are WE13 */
10250 + /* need to check for certain error conditions before we
10251 + * clean the descriptor: we still need valid descr data here */
10252 + if (unlikely(0x30 & error)) {
10253 + /* only send IWEVTXDROP in case of retry or lifetime exceeded;
10254 + * all other errors mean we screwed up locally */
10255 + union iwreq_data wrqu;
10257 + txhostdesc_t *hostdesc;
10259 + hostdesc = acx_get_txhostdesc(priv, txdesc);
10260 + hdr = (wlan_hdr_t *)hostdesc->data;
10261 + MAC_COPY(wrqu.addr.sa_data, hdr->a1);
10262 + wireless_send_event(priv->netdev, IWEVTXDROP, &wrqu, NULL);
10265 + /* ...and free the descr */
10266 + txdesc->error = 0;
10267 + txdesc->ack_failures = 0;
10268 + txdesc->rts_failures = 0;
10269 + txdesc->rts_ok = 0;
10270 + /* signal host owning it LAST, since ACX already knows that this
10271 + * descriptor is finished since it set Ctl_8 accordingly:
10272 + * if _OWN is set at the beginning instead, our own get_tx
10273 + * might choose a Tx desc that isn't fully cleared
10274 + * (in case of bad locking). */
10275 + txdesc->Ctl_8 = DESC_CTL_HOSTOWN;
10279 + if ((priv->tx_free >= TX_START_QUEUE)
10280 + && (priv->status == ACX_STATUS_4_ASSOCIATED)
10281 + && (acx_queue_stopped(priv->netdev))
10283 + acxlog(L_BUF, "tx: wake queue (avail. Tx desc %u)\n",
10285 + acx_wake_queue(priv->netdev, NULL);
10288 + /* do error checking, rate handling and logging
10289 + * AFTER having done the work, it's faster */
10291 + /* do rate handling */
10292 + txc = acx_get_txc(priv, txdesc);
10293 + if (txc && priv->rate_auto) {
10294 + acx_l_handle_txrate_auto(priv, txc, finger, r100, r111, error);
10297 + if (unlikely(error))
10298 + acx_l_handle_tx_error(priv, error, finger);
10300 + if (IS_ACX111(priv))
10301 + acxlog(L_BUFT, "tx: cleaned %u: !ACK=%u !RTS=%u RTS=%u r111=%04X\n",
10302 + finger, ack_failures, rts_failures, rts_ok, r111);
10304 + acxlog(L_BUFT, "tx: cleaned %u: !ACK=%u !RTS=%u RTS=%u rate=%u\n",
10305 + finger, ack_failures, rts_failures, rts_ok, r100);
10307 + /* update pointer for descr to be cleaned next */
10308 + finger = (finger + 1) % TX_CNT;
10309 + } while (--to_process);
10311 + /* remember last position */
10312 + priv->tx_tail = finger;
10314 + FN_EXIT1(num_cleaned);
10315 + return num_cleaned;
10318 +/* clean *all* Tx descriptors, and regardless of their previous state.
10319 + * Used for brute-force reset handling. */
10321 +acx_l_clean_tx_desc_emergency(wlandevice_t *priv)
10323 + txdesc_t *txdesc;
10328 + for (i = 0; i < TX_CNT; i++) {
10329 + txdesc = get_txdesc(priv, i);
10332 + txdesc->ack_failures = 0;
10333 + txdesc->rts_failures = 0;
10334 + txdesc->rts_ok = 0;
10335 + txdesc->error = 0;
10336 + txdesc->Ctl_8 = DESC_CTL_HOSTOWN;
10339 + priv->tx_free = TX_CNT;
10345 +/*----------------------------------------------------------------
10346 +* acx_l_log_rxbuffer
10348 +* Called from IRQ context only
10349 +*----------------------------------------------------------------*/
10351 +static inline void acx_l_log_rxbuffer(const wlandevice_t *priv) {}
10354 +acx_l_log_rxbuffer(const wlandevice_t *priv)
10356 + const struct rxhostdesc *rxhostdesc;
10359 + /* no FN_ENTER here, we don't want that */
10361 + rxhostdesc = priv->rxhostdesc_start;
10362 + if (!rxhostdesc) return;
10363 + for (i = 0; i < RX_CNT; i++) {
10364 + if ((rxhostdesc->Ctl_16 & cpu_to_le16(DESC_CTL_HOSTOWN))
10365 + && (rxhostdesc->Status & cpu_to_le32(DESC_STATUS_FULL)))
10366 + printk("rx: buf %d full\n", i);
10373 +/***************************************************************
10374 +** acx_l_process_rx_desc
10376 +** Called directly and only from the IRQ handler
10379 +acx_l_process_rx_desc(wlandevice_t *priv)
10381 + rxhostdesc_t *hostdesc;
10382 + /* unsigned int curr_idx; */
10383 + unsigned int count = 0;
10387 + if (unlikely(acx_debug & L_BUFR)) {
10388 + acx_l_log_rxbuffer(priv);
10391 + /* First, have a loop to determine the first descriptor that's
10392 + * full, just in case there's a mismatch between our current
10393 + * rx_tail and the full descriptor we're supposed to handle. */
10395 + /* curr_idx = priv->rx_tail; */
10396 + hostdesc = &priv->rxhostdesc_start[priv->rx_tail];
10397 + priv->rx_tail = (priv->rx_tail + 1) % RX_CNT;
10398 + if ((hostdesc->Ctl_16 & cpu_to_le16(DESC_CTL_HOSTOWN))
10399 + && (hostdesc->Status & cpu_to_le32(DESC_STATUS_FULL))) {
10404 + if (unlikely(count > RX_CNT)) {
10405 + /* hmm, no luck: all descriptors empty, bail out */
10410 + /* now process descriptors, starting with the first we figured out */
10412 + acxlog(L_BUFR, "rx: tail=%u Ctl_16=%04X Status=%08X\n",
10413 + priv->rx_tail, hostdesc->Ctl_16, hostdesc->Status);
10415 + acx_l_process_rxbuf(priv, hostdesc->data);
10417 + hostdesc->Status = 0;
10418 + /* flush all writes before adapter sees CTL_HOSTOWN change */
10420 + /* Host no longer owns this, needs to be LAST */
10421 + CLEAR_BIT(hostdesc->Ctl_16, cpu_to_le16(DESC_CTL_HOSTOWN));
10423 + /* ok, descriptor is handled, now check the next descriptor */
10424 + /* curr_idx = priv->rx_tail; */
10425 + hostdesc = &priv->rxhostdesc_start[priv->rx_tail];
10427 + /* if next descriptor is empty, then bail out */
10428 + /* FIXME: is this check really entirely correct?? */
10430 +//FIXME: inconsistent with check in prev while() loop
10431 + if (!(hostdesc->Ctl & cpu_to_le16(DESC_CTL_HOSTOWN))
10432 + && !(hostdesc->Status & cpu_to_le32(DESC_STATUS_FULL))) */
10433 + if (!(hostdesc->Status & cpu_to_le32(DESC_STATUS_FULL)))
10436 + priv->rx_tail = (priv->rx_tail + 1) % RX_CNT;
10443 +/*----------------------------------------------------------------
10444 +* acx_s_create_tx_host_desc_queue
10445 +*----------------------------------------------------------------*/
10446 +static inline void*
10447 +acx_alloc_coherent(struct device *dev, size_t size,
10448 + dma_addr_t *dma_handle, int flag)
10450 + printk("Size : %ld\n",size);
10451 + dev->coherent_dma_mask = 0xffffffff;
10452 + return dma_alloc_coherent(dev, size, dma_handle, flag);
10456 +allocate(wlandevice_t *priv, size_t size, dma_addr_t *phy, const char *msg)
10458 + void *ptr = acx_alloc_coherent(priv->dev, size, phy, GFP_KERNEL);
10460 + acxlog(L_DEBUG, "%s sz=%d adr=0x%p phy=0x%08llx\n",
10461 + msg, (int)size, ptr, (unsigned long long)*phy);
10462 + memset(ptr, 0, size);
10465 + printk(KERN_ERR "acx: %s allocation FAILED (%d bytes)\n",
10471 +acx_s_create_tx_host_desc_queue(wlandevice_t *priv)
10473 + txhostdesc_t *hostdesc;
10475 + dma_addr_t hostdesc_phy;
10476 + dma_addr_t txbuf_phy;
10481 + /* allocate TX buffer */
10482 + priv->txbuf_area_size = TX_CNT * WLAN_A4FR_MAXLEN_WEP_FCS;
10483 + priv->txbuf_start = allocate(priv, priv->txbuf_area_size,
10484 + &priv->txbuf_startphy, "txbuf_start");
10485 + if (!priv->txbuf_start)
10488 + /* allocate the TX host descriptor queue pool */
10489 + priv->txhostdesc_area_size = TX_CNT * 2*sizeof(txhostdesc_t);
10490 + priv->txhostdesc_start = allocate(priv, priv->txhostdesc_area_size,
10491 + &priv->txhostdesc_startphy, "txhostdesc_start");
10492 + if (!priv->txhostdesc_start)
10494 + /* check for proper alignment of TX host descriptor pool */
10495 + if ((long) priv->txhostdesc_start & 3) {
10496 + printk("acx: driver bug: dma alloc returns unaligned address\n");
10500 +/* Each tx frame buffer is accessed by hardware via
10501 +** txdesc -> txhostdesc(s) -> framebuffer(s)
10502 +** We use only one txhostdesc per txdesc, but it looks like
10503 +** acx111 is buggy: it accesses second txhostdesc
10504 +** (via hostdesc.desc_phy_next field) even if
10505 +** txdesc->length == hostdesc->length and thus
10506 +** entire packet was placed into first txhostdesc.
10507 +** Due to this bug acx111 hangs unless second txhostdesc
10508 +** has hostdesc.length = 3 (or larger)
10509 +** Storing NULL into hostdesc.desc_phy_next
10510 +** doesn't seem to help.
10512 +/* It is not known whether we need to have 'extra' second
10513 +** txhostdescs for acx100. Maybe it is acx111-only bug.
10515 + hostdesc = priv->txhostdesc_start;
10516 + hostdesc_phy = priv->txhostdesc_startphy;
10517 + txbuf = priv->txbuf_start;
10518 + txbuf_phy = priv->txbuf_startphy;
10520 + for (i = 0; i < TX_CNT*2; i++) {
10521 + hostdesc_phy += sizeof(txhostdesc_t);
10523 + hostdesc->data_phy = cpu2acx(txbuf_phy);
10524 + /* done by memset(0): hostdesc->data_offset = 0; */
10525 + /* hostdesc->reserved = ... */
10526 + hostdesc->Ctl_16 = cpu_to_le16(DESC_CTL_HOSTOWN);
10527 + /* hostdesc->length = ... */
10528 + hostdesc->desc_phy_next = cpu2acx(hostdesc_phy);
10529 + /* done by memset(0): hostdesc->pNext = ptr2acx(NULL); */
10530 + /* hostdesc->Status = ... */
10531 + /* below: non-hardware fields */
10532 + hostdesc->data = txbuf;
10534 + txbuf += WLAN_HDR_A3_LEN;
10535 + txbuf_phy += WLAN_HDR_A3_LEN;
10537 + hostdesc->data_phy = cpu2acx(txbuf_phy);
10538 + /* done by memset(0): hostdesc->data_offset = 0; */
10539 + /* hostdesc->reserved = ... */
10540 + hostdesc->Ctl_16 = cpu_to_le16(DESC_CTL_HOSTOWN);
10541 + /* hostdesc->length = ...; */
10542 + hostdesc->desc_phy_next = cpu2acx(hostdesc_phy);
10543 + /* done by memset(0): hostdesc->pNext = ptr2acx(NULL); */
10544 + /* hostdesc->Status = ... */
10545 + /* below: non-hardware fields */
10546 + hostdesc->data = txbuf;
10548 + txbuf += WLAN_A4FR_MAXLEN_WEP_FCS - WLAN_HDR_A3_LEN;
10549 + txbuf_phy += WLAN_A4FR_MAXLEN_WEP_FCS - WLAN_HDR_A3_LEN;
10554 + hostdesc->desc_phy_next = cpu2acx(priv->txhostdesc_startphy);
10559 + printk("acx: create_tx_host_desc_queue FAILED\n");
10560 + /* dealloc will be done by free function on error case */
10561 + FN_EXIT1(NOT_OK);
10566 +/***************************************************************
10567 +** acx_s_create_rx_host_desc_queue
10569 +/* the whole size of a data buffer (header plus data body)
10570 + * plus 32 bytes safety offset at the end */
10571 +#define RX_BUFFER_SIZE (sizeof(rxbuffer_t) + 32)
10574 +acx_s_create_rx_host_desc_queue(wlandevice_t *priv)
10576 + rxhostdesc_t *hostdesc;
10577 + rxbuffer_t *rxbuf;
10578 + dma_addr_t hostdesc_phy;
10579 + dma_addr_t rxbuf_phy;
10584 + /* allocate the RX host descriptor queue pool */
10585 + priv->rxhostdesc_area_size = RX_CNT * sizeof(rxhostdesc_t);
10586 + priv->rxhostdesc_start = allocate(priv, priv->rxhostdesc_area_size,
10587 + &priv->rxhostdesc_startphy, "rxhostdesc_start");
10588 + if (!priv->rxhostdesc_start)
10590 + /* check for proper alignment of RX host descriptor pool */
10591 + if ((long) priv->rxhostdesc_start & 3) {
10592 + printk("acx: driver bug: dma alloc returns unaligned address\n");
10596 + /* allocate Rx buffer pool which will be used by the acx
10597 + * to store the whole content of the received frames in it */
10598 + priv->rxbuf_area_size = RX_CNT * RX_BUFFER_SIZE;
10599 + priv->rxbuf_start = allocate(priv, priv->rxbuf_area_size,
10600 + &priv->rxbuf_startphy, "rxbuf_start");
10601 + if (!priv->rxbuf_start)
10604 + rxbuf = priv->rxbuf_start;
10605 + rxbuf_phy = priv->rxbuf_startphy;
10606 + hostdesc = priv->rxhostdesc_start;
10607 + hostdesc_phy = priv->rxhostdesc_startphy;
10609 + /* don't make any popular C programming pointer arithmetic mistakes
10610 + * here, otherwise I'll kill you...
10611 + * (and don't dare asking me why I'm warning you about that...) */
10612 + for (i = 0; i < RX_CNT; i++) {
10613 + hostdesc->data = rxbuf;
10614 + hostdesc->data_phy = cpu2acx(rxbuf_phy);
10615 + hostdesc->length = cpu_to_le16(RX_BUFFER_SIZE);
10616 + CLEAR_BIT(hostdesc->Ctl_16, cpu_to_le16(DESC_CTL_HOSTOWN));
10618 + rxbuf_phy += sizeof(rxbuffer_t);
10619 + hostdesc_phy += sizeof(rxhostdesc_t);
10620 + hostdesc->desc_phy_next = cpu2acx(hostdesc_phy);
10624 + hostdesc->desc_phy_next = cpu2acx(priv->rxhostdesc_startphy);
10628 + printk("acx: create_rx_host_desc_queue FAILED\n");
10629 + /* dealloc will be done by free function on error case */
10630 + FN_EXIT1(NOT_OK);
10635 +/***************************************************************
10636 +** acx_s_create_hostdesc_queues
10639 +acx_s_create_hostdesc_queues(wlandevice_t *priv)
10642 + result = acx_s_create_tx_host_desc_queue(priv);
10643 + if (OK != result) return result;
10644 + result = acx_s_create_rx_host_desc_queue(priv);
10649 +/***************************************************************
10650 +** acx_create_tx_desc_queue
10653 +acx_create_tx_desc_queue(wlandevice_t *priv, u32 tx_queue_start)
10655 + txdesc_t *txdesc;
10656 + txhostdesc_t *hostdesc;
10657 + dma_addr_t hostmemptr;
10663 + priv->txdesc_size = sizeof(txdesc_t);
10665 + if (IS_ACX111(priv)) {
10666 + /* the acx111 txdesc is 4 bytes larger */
10667 + priv->txdesc_size = sizeof(txdesc_t) + 4;
10671 + priv->txdesc_start = (txdesc_t *) (priv->iobase2 + tx_queue_start);
10673 + acxlog(L_DEBUG, "priv->iobase2=%p\n"
10674 + "tx_queue_start=%08X\n"
10675 + "priv->txdesc_start=%p\n",
10678 + priv->txdesc_start);
10680 + priv->tx_free = TX_CNT;
10682 + /* done by memset: priv->tx_head = 0; */
10683 + /* done by memset: priv->tx_tail = 0; */
10684 + txdesc = priv->txdesc_start;
10685 + mem_offs = tx_queue_start;
10686 + hostmemptr = priv->txhostdesc_startphy;
10687 + hostdesc = priv->txhostdesc_start;
10690 + if (IS_ACX111(priv)) {
10691 + /* ACX111 has a preinitialized Tx buffer! */
10692 + /* loop over whole send pool */
10693 + /* FIXME: do we have to do the hostmemptr stuff here?? */
10694 + for (i = 0; i < TX_CNT; i++) {
10695 + txdesc->HostMemPtr = ptr2acx(hostmemptr);
10696 + txdesc->Ctl_8 = DESC_CTL_HOSTOWN;
10697 + /* reserve two (hdr desc and payload desc) */
10699 + hostmemptr += 2 * sizeof(txhostdesc_t);
10700 + txdesc = move_txdesc(priv, txdesc, 1);
10703 + /* ACX100 Tx buffer needs to be initialized by us */
10704 + /* clear whole send pool. sizeof is safe here (we are acx100) */
10705 + memset(priv->txdesc_start, 0, TX_CNT * sizeof(txdesc_t));
10707 + /* loop over whole send pool */
10708 + for (i = 0; i < TX_CNT; i++) {
10709 + acxlog(L_DEBUG, "configure card tx descriptor: 0x%p, "
10710 + "size: 0x%X\n", txdesc, priv->txdesc_size);
10712 + /* pointer to hostdesc memory */
10713 + /* FIXME: type-incorrect assignment, might cause trouble
10714 + * in some cases */
10715 + txdesc->HostMemPtr = ptr2acx(hostmemptr);
10716 + /* initialise ctl */
10717 + txdesc->Ctl_8 = DESC_CTL_INIT;
10718 + txdesc->Ctl2_8 = 0;
10719 + /* point to next txdesc */
10720 + txdesc->pNextDesc = cpu2acx(mem_offs + priv->txdesc_size);
10721 + /* reserve two (hdr desc and payload desc) */
10723 + hostmemptr += 2 * sizeof(txhostdesc_t);
10724 + /* go to the next one */
10725 + mem_offs += priv->txdesc_size;
10726 + /* ++ is safe here (we are acx100) */
10729 + /* go back to the last one */
10731 + /* and point to the first making it a ring buffer */
10732 + txdesc->pNextDesc = cpu2acx(tx_queue_start);
10739 +/***************************************************************
10740 +** acx_create_rx_desc_queue
10743 +acx_create_rx_desc_queue(wlandevice_t *priv, u32 rx_queue_start)
10745 + rxdesc_t *rxdesc;
10751 + /* done by memset: priv->rx_tail = 0; */
10753 + /* ACX111 doesn't need any further config: preconfigures itself.
10754 + * Simply print ring buffer for debugging */
10755 + if (IS_ACX111(priv)) {
10756 + /* rxdesc_start already set here */
10758 + priv->rxdesc_start = (rxdesc_t *) ((u8 *)priv->iobase2 + rx_queue_start);
10760 + rxdesc = priv->rxdesc_start;
10761 + for (i = 0; i < RX_CNT; i++) {
10762 + acxlog(L_DEBUG, "rx descriptor %d @ 0x%p\n", i, rxdesc);
10763 + rxdesc = priv->rxdesc_start = (rxdesc_t *)
10764 + (priv->iobase2 + acx2cpu(rxdesc->pNextDesc));
10767 + /* we didn't pre-calculate rxdesc_start in case of ACX100 */
10768 + /* rxdesc_start should be right AFTER Tx pool */
10769 + priv->rxdesc_start = (rxdesc_t *)
10770 + ((u8 *) priv->txdesc_start + (TX_CNT * sizeof(txdesc_t)));
10771 + /* NB: sizeof(txdesc_t) above is valid because we know
10772 + ** we are in if(acx100) block. Beware of cut-n-pasting elsewhere!
10773 + ** acx111's txdesc is larger! */
10775 + memset(priv->rxdesc_start, 0, RX_CNT * sizeof(rxdesc_t));
10777 + /* loop over whole receive pool */
10778 + rxdesc = priv->rxdesc_start;
10779 + mem_offs = rx_queue_start;
10780 + for (i = 0; i < RX_CNT; i++) {
10781 + acxlog(L_DEBUG, "rx descriptor @ 0x%p\n", rxdesc);
10782 + rxdesc->Ctl_8 = DESC_CTL_RECLAIM | DESC_CTL_AUTODMA;
10783 + /* point to next rxdesc */
10784 + rxdesc->pNextDesc = cpu2acx(mem_offs + sizeof(rxdesc_t));
10785 + /* go to the next one */
10786 + mem_offs += sizeof(rxdesc_t);
10789 + /* go to the last one */
10792 + /* and point to the first making it a ring buffer */
10793 + rxdesc->pNextDesc = cpu2acx(rx_queue_start);
10799 +/***************************************************************
10800 +** acx_create_desc_queues
10803 +acx_create_desc_queues(wlandevice_t *priv, u32 tx_queue_start, u32 rx_queue_start)
10805 + acx_create_tx_desc_queue(priv, tx_queue_start);
10806 + acx_create_rx_desc_queue(priv, rx_queue_start);
10810 +/***************************************************************
10811 +** acxpci_s_proc_diag_output
10814 +acxpci_s_proc_diag_output(char *p, wlandevice_t *priv)
10816 + const char *rtl, *thd, *ttl;
10817 + rxhostdesc_t *rxhostdesc;
10818 + txdesc_t *txdesc;
10823 + p += sprintf(p, "** Rx buf **\n");
10824 + rxhostdesc = priv->rxhostdesc_start;
10825 + if (rxhostdesc) for (i = 0; i < RX_CNT; i++) {
10826 + rtl = (i == priv->rx_tail) ? " [tail]" : "";
10827 + if ((rxhostdesc->Ctl_16 & cpu_to_le16(DESC_CTL_HOSTOWN))
10828 + && (rxhostdesc->Status & cpu_to_le32(DESC_STATUS_FULL)) )
10829 + p += sprintf(p, "%02u FULL%s\n", i, rtl);
10831 + p += sprintf(p, "%02u empty%s\n", i, rtl);
10834 + p += sprintf(p, "** Tx buf (free %d, Linux netqueue %s) **\n", priv->tx_free,
10835 + acx_queue_stopped(priv->netdev) ? "STOPPED" : "running");
10836 + txdesc = priv->txdesc_start;
10837 + if (txdesc) for (i = 0; i < TX_CNT; i++) {
10838 + thd = (i == priv->tx_head) ? " [head]" : "";
10839 + ttl = (i == priv->tx_tail) ? " [tail]" : "";
10840 + if (txdesc->Ctl_8 & DESC_CTL_ACXDONE)
10841 + p += sprintf(p, "%02u DONE (%02X)%s%s\n", i, txdesc->Ctl_8, thd, ttl);
10843 + if (!(txdesc->Ctl_8 & DESC_CTL_HOSTOWN))
10844 + p += sprintf(p, "%02u TxWait (%02X)%s%s\n", i, txdesc->Ctl_8, thd, ttl);
10846 + p += sprintf(p, "%02u empty (%02X)%s%s\n", i, txdesc->Ctl_8, thd, ttl);
10847 + txdesc = move_txdesc(priv, txdesc, 1);
10851 + "** PCI data **\n"
10852 + "txbuf_start %p, txbuf_area_size %u, txbuf_startphy %08llx\n"
10853 + "txdesc_size %u, txdesc_start %p\n"
10854 + "txhostdesc_start %p, txhostdesc_area_size %u, txhostdesc_startphy %08llx\n"
10855 + "rxdesc_start %p\n"
10856 + "rxhostdesc_start %p, rxhostdesc_area_size %u, rxhostdesc_startphy %08llx\n"
10857 + "rxbuf_start %p, rxbuf_area_size %u, rxbuf_startphy %08llx\n",
10858 + priv->txbuf_start, priv->txbuf_area_size, (u64)priv->txbuf_startphy,
10859 + priv->txdesc_size, priv->txdesc_start,
10860 + priv->txhostdesc_start, priv->txhostdesc_area_size, (u64)priv->txhostdesc_startphy,
10861 + priv->rxdesc_start,
10862 + priv->rxhostdesc_start, priv->rxhostdesc_area_size, (u64)priv->rxhostdesc_startphy,
10863 + priv->rxbuf_start, priv->rxbuf_area_size, (u64)priv->rxbuf_startphy);
10870 +/***********************************************************************
10873 +acx_proc_eeprom_output(char *buf, wlandevice_t *priv)
10880 + for (i = 0; i < 0x400; i++) {
10881 + acx_read_eeprom_offset(priv, i, p++);
10884 + FN_EXIT1(p - buf);
10889 +/***********************************************************************
10892 +acx_set_interrupt_mask(wlandevice_t *priv)
10894 + if (IS_ACX111(priv)) {
10895 + priv->irq_mask = (u16) ~(0
10896 + /* | HOST_INT_RX_DATA */
10897 + | HOST_INT_TX_COMPLETE
10898 + /* | HOST_INT_TX_XFER */
10899 + | HOST_INT_RX_COMPLETE
10900 + /* | HOST_INT_DTIM */
10901 + /* | HOST_INT_BEACON */
10902 + /* | HOST_INT_TIMER */
10903 + /* | HOST_INT_KEY_NOT_FOUND */
10904 + | HOST_INT_IV_ICV_FAILURE
10905 + | HOST_INT_CMD_COMPLETE
10907 + /* | HOST_INT_OVERFLOW */
10908 + /* | HOST_INT_PROCESS_ERROR */
10909 + | HOST_INT_SCAN_COMPLETE
10910 + | HOST_INT_FCS_THRESHOLD
10911 + /* | HOST_INT_UNKNOWN */
10913 + priv->irq_mask_off = (u16)~( HOST_INT_CMD_COMPLETE ); /* 0xfdff */
10915 + priv->irq_mask = (u16) ~(0
10916 + /* | HOST_INT_RX_DATA */
10917 + | HOST_INT_TX_COMPLETE
10918 + /* | HOST_INT_TX_XFER */
10919 + | HOST_INT_RX_COMPLETE
10920 + /* | HOST_INT_DTIM */
10921 + /* | HOST_INT_BEACON */
10922 + /* | HOST_INT_TIMER */
10923 + /* | HOST_INT_KEY_NOT_FOUND */
10924 + /* | HOST_INT_IV_ICV_FAILURE */
10925 + | HOST_INT_CMD_COMPLETE
10927 + /* | HOST_INT_OVERFLOW */
10928 + /* | HOST_INT_PROCESS_ERROR */
10929 + | HOST_INT_SCAN_COMPLETE
10930 + /* | HOST_INT_FCS_THRESHOLD */
10931 + /* | HOST_INT_UNKNOWN */
10933 + priv->irq_mask_off = (u16)~( HOST_INT_UNKNOWN ); /* 0x7fff */
10938 +/***********************************************************************
10941 +acx100_s_set_tx_level(wlandevice_t *priv, u8 level_dbm)
10943 + /* since it can be assumed that at least the Maxim radio has a
10944 + * maximum power output of 20dBm and since it also can be
10945 + * assumed that these values drive the DAC responsible for
10946 + * setting the linear Tx level, I'd guess that these values
10947 + * should be the corresponding linear values for a dBm value,
10948 + * in other words: calculate the values from that formula:
10949 + * Y [dBm] = 10 * log (X [mW])
10950 + * then scale the 0..63 value range onto the 1..100mW range (0..20 dBm)
10951 + * and you're done...
10952 + * Hopefully that's ok, but you never know if we're actually
10953 + * right... (especially since Windows XP doesn't seem to show
10954 + * actual Tx dBm values :-P) */
10956 + /* NOTE: on Maxim, value 30 IS 30mW, and value 10 IS 10mW - so the
10957 + * values are EXACTLY mW!!! Not sure about RFMD and others,
10959 + static const u8 dbm2val_maxim[21] = {
10967 + static const u8 dbm2val_rfmd[21] = {
10977 + switch (priv->radio_type) {
10978 + case RADIO_MAXIM_0D:
10979 + table = &dbm2val_maxim[0];
10981 + case RADIO_RFMD_11:
10982 + case RADIO_RALINK_15:
10983 + table = &dbm2val_rfmd[0];
10986 + printk("%s: unknown/unsupported radio type, "
10987 + "cannot modify tx power level yet!\n",
10988 + priv->netdev->name);
10991 + printk("%s: changing radio power level to %u dBm (%u)\n",
10992 + priv->netdev->name, level_dbm, table[level_dbm]);
10993 + acxpci_s_write_phy_reg(priv, 0x11, table[level_dbm]);
10998 +/*----------------------------------------------------------------
10999 +* acx_e_init_module
11001 +* Module initialization routine, called once at module load time.
11005 +* ~0 - failure, module is unloaded.
11008 +* process thread (insmod or modprobe)
11009 +----------------------------------------------------------------*/
11011 +acxcfi_e_init_module(void)
11017 + printk("acx: compiled to use 16bit I/O access only "
11018 + "(compatibility mode)\n");
11020 + acxlog(L_INIT, "running on a little-endian CPU\n");
11023 + "Compact Flash module " WLAN_RELEASE " initialized, "
11024 + "waiting for cards to probe...\n");
11027 + * Now let configure device
11030 + pca9535_gpio_direction(GPIO6, GPIO_OUTPUT);
11031 + pca9535_gpio_direction(GPIO12, GPIO_OUTPUT);
11033 + if ((omap_request_gpio(11)) < 0) {
11034 + printk("Error requesting gpio 11\n");
11037 + omap_set_gpio_direction (11, 1);
11038 + omap_set_gpio_dataout (11, 1);
11040 + res = driver_register(&acx_driver);
11047 +/*----------------------------------------------------------------
11048 +* acx_cleanup_module
11050 +* Called at module unload time. This is our last chance to
11051 +* clean up after ourselves.
11055 +----------------------------------------------------------------*/
11057 +acxcfi_e_cleanup_module(void)
11059 + struct net_device *dev;
11060 + unsigned long flags;
11064 + /* Since the whole module is about to be unloaded,
11065 + * we recursively shutdown all cards we handled instead
11066 + * of doing it in remove_pci() (which will be activated by us
11067 + * via pci_unregister_driver at the end).
11068 + * remove_pci() might just get called after a card eject,
11069 + * that's why hardware operations have to be done here instead
11070 + * when the hardware is available. */
11072 + down(&root_acx_dev_sem);
11074 + dev = root_acx_dev.newest;
11075 + while (dev != NULL) {
11076 + /* doh, netdev_priv() doesn't have const! */
11077 + wlandevice_t *priv = netdev_priv(dev);
11079 + acx_sem_lock(priv);
11081 + /* disable both Tx and Rx to shut radio down properly */
11082 + acx_s_issue_cmd(priv, ACX1xx_CMD_DISABLE_TX, NULL, 0);
11083 + acx_s_issue_cmd(priv, ACX1xx_CMD_DISABLE_RX, NULL, 0);
11086 + /* put the eCPU to sleep to save power
11087 + * Halting is not possible currently,
11088 + * since not supported by all firmware versions */
11089 + acx_s_issue_cmd(priv, ACX100_CMD_SLEEP, NULL, 0);
11091 + acx_lock(priv, flags);
11093 + /* disable power LED to save power :-) */
11094 + acxlog(L_INIT, "switching off power LED to save power :-)\n");
11095 + acx_l_power_led(priv, 0);
11097 + /* stop our eCPU */
11098 + if (IS_ACX111(priv)) {
11099 + /* FIXME: does this actually keep halting the eCPU?
11100 + * I don't think so...
11102 + acx_l_reset_mac(priv);
11107 + temp = acx_read_reg16(priv, IO_ACX_ECPU_CTRL) | 0x1;
11108 + acx_write_reg16(priv, IO_ACX_ECPU_CTRL, temp);
11109 + acx_write_flush(priv);
11112 + acx_unlock(priv, flags);
11114 + acx_sem_unlock(priv);
11116 + dev = priv->prev_nd;
11119 + up(&root_acx_dev_sem);
11121 + omap_free_gpio(11);
11122 + driver_unregister(&acx_driver);
11126 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
11127 --- linux-2.6.14-omap2/drivers/net/wireless/tiacx/common.c 1970-01-01 02:00:00.000000000 +0200
11128 +++ linux-h6300-omap2-2.6.14.3/drivers/net/wireless/tiacx/common.c 2005-09-28 23:54:23.000000000 +0300
11130 +/***********************************************************************
11131 +** Copyright (C) 2003 ACX100 Open Source Project
11133 +** The contents of this file are subject to the Mozilla Public
11134 +** License Version 1.1 (the "License"); you may not use this file
11135 +** except in compliance with the License. You may obtain a copy of
11136 +** the License at http://www.mozilla.org/MPL/
11138 +** Software distributed under the License is distributed on an "AS
11139 +** IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
11140 +** implied. See the License for the specific language governing
11141 +** rights and limitations under the License.
11143 +** Alternatively, the contents of this file may be used under the
11144 +** terms of the GNU Public License version 2 (the "GPL"), in which
11145 +** case the provisions of the GPL are applicable instead of the
11146 +** above. If you wish to allow the use of your version of this file
11147 +** only under the terms of the GPL and not to allow others to use
11148 +** your version of this file under the MPL, indicate your decision
11149 +** by deleting the provisions above and replace them with the notice
11150 +** and other provisions required by the GPL. If you do not delete
11151 +** the provisions above, a recipient may use your version of this
11152 +** file under either the MPL or the GPL.
11153 +** ---------------------------------------------------------------------
11154 +** Inquiries regarding the ACX100 Open Source Project can be
11155 +** made directly to:
11157 +** acx100-users@lists.sf.net
11158 +** http://acx100.sf.net
11159 +** ---------------------------------------------------------------------
11162 +#include <linux/config.h>
11163 +#include <linux/version.h>
11164 +#include <linux/module.h>
11165 +#include <linux/kernel.h>
11166 +#include <linux/sched.h>
11167 +#include <linux/types.h>
11168 +#include <linux/slab.h>
11169 +#include <linux/delay.h>
11170 +#include <linux/proc_fs.h>
11171 +#include <linux/if_arp.h>
11172 +#include <linux/rtnetlink.h>
11173 +#include <linux/netdevice.h>
11174 +#include <linux/etherdevice.h>
11175 +#include <linux/wireless.h>
11176 +#include <linux/pm.h>
11177 +#include <linux/vmalloc.h>
11178 +#include <asm/bug.h>
11179 +#if WIRELESS_EXT >= 13
11180 +#include <net/iw_handler.h>
11181 +#endif /* WE >= 13 */
11188 +/***********************************************************************
11190 +static client_t *acx_l_sta_list_alloc(wlandevice_t *priv);
11191 +static client_t *acx_l_sta_list_get_from_hash(wlandevice_t *priv, const u8 *address);
11193 +static int acx_l_process_data_frame_master(wlandevice_t *priv, rxbuffer_t *rxbuf);
11194 +static int acx_l_process_data_frame_client(wlandevice_t *priv, rxbuffer_t *rxbuf);
11195 +/* static int acx_l_process_NULL_frame(wlandevice_t *priv, rxbuffer_t *rxbuf, int vala); */
11196 +static int acx_l_process_mgmt_frame(wlandevice_t *priv, rxbuffer_t *rxbuf);
11197 +static void acx_l_process_disassoc_from_sta(wlandevice_t *priv, const wlan_fr_disassoc_t *req);
11198 +static void acx_l_process_disassoc_from_ap(wlandevice_t *priv, const wlan_fr_disassoc_t *req);
11199 +static void acx_l_process_deauth_from_sta(wlandevice_t *priv, const wlan_fr_deauthen_t *req);
11200 +static void acx_l_process_deauth_from_ap(wlandevice_t *priv, const wlan_fr_deauthen_t *req);
11201 +static int acx_l_process_probe_response(wlandevice_t *priv, wlan_fr_proberesp_t *req, const rxbuffer_t *rxbuf);
11202 +static int acx_l_process_assocresp(wlandevice_t *priv, const wlan_fr_assocresp_t *req);
11203 +static int acx_l_process_reassocresp(wlandevice_t *priv, const wlan_fr_reassocresp_t *req);
11204 +static int acx_l_process_authen(wlandevice_t *priv, const wlan_fr_authen_t *req);
11205 +static int acx_l_transmit_assocresp(wlandevice_t *priv, const wlan_fr_assocreq_t *req);
11206 +static int acx_l_transmit_reassocresp(wlandevice_t *priv, const wlan_fr_reassocreq_t *req);
11207 +static int acx_l_transmit_deauthen(wlandevice_t *priv, const u8 *addr, u16 reason);
11208 +static int acx_l_transmit_authen1(wlandevice_t *priv);
11209 +static int acx_l_transmit_authen2(wlandevice_t *priv, const wlan_fr_authen_t *req, client_t *clt);
11210 +static int acx_l_transmit_authen3(wlandevice_t *priv, const wlan_fr_authen_t *req);
11211 +static int acx_l_transmit_authen4(wlandevice_t *priv, const wlan_fr_authen_t *req);
11212 +static int acx_l_transmit_assoc_req(wlandevice_t *priv);
11215 +/***********************************************************************
11218 +unsigned int acx_debug = L_ASSOC|L_INIT;
11220 +#if USE_FW_LOADER_LEGACY
11221 +static char *firmware_dir;
11223 +#if SEPARATE_DRIVER_INSTANCES
11227 +/* introduced earlier than 2.6.10, but takes more memory, so don't use it
11228 + * if there's no compile warning by kernel */
11229 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
11232 +/* parameter is 'debug', corresponding var is acx_debug */
11233 +module_param_named(debug, acx_debug, uint, 0);
11235 +#if USE_FW_LOADER_LEGACY
11236 +module_param(firmware_dir, charp, 0);
11242 +/* doh, 2.6.x screwed up big time: here the define has its own ";"
11243 + * ("double ; detected"), yet in 2.4.x it DOESN'T (the sane thing to do),
11245 +MODULE_PARM(acx_debug, "i");
11247 +#if USE_FW_LOADER_LEGACY
11248 +MODULE_PARM(firmware_dir, "s");
11254 +MODULE_PARM_DESC(debug, "Debug level mask (see L_xxx constants)");
11256 +#if USE_FW_LOADER_LEGACY
11257 +MODULE_PARM_DESC(firmware_dir, "Directory to load acx100 firmware files from");
11259 +#if SEPARATE_DRIVER_INSTANCES
11260 +MODULE_PARM(card, "i");
11261 +MODULE_PARM_DESC(card, "Associate only with card-th acx100 card from this driver instance");
11264 +/* Shoundn't be needed now, acx.firmware_dir= should work */
11265 +#if 0 /* USE_FW_LOADER_LEGACY */
11267 +acx_get_firmware_dir(const char *str)
11269 + /* I've seen other drivers just pass the string pointer,
11270 + * so hopefully that's safe */
11271 + firmware_dir = str;
11274 +__setup("acx_firmware_dir=", acx_get_firmware_dir);
11277 +#ifdef MODULE_LICENSE
11278 +MODULE_LICENSE("Dual MPL/GPL");
11280 +/* USB had this: MODULE_AUTHOR("Martin Wawro <martin.wawro AT uni-dortmund.de>"); */
11281 +MODULE_AUTHOR("ACX100 Open Source Driver development team");
11282 +MODULE_DESCRIPTION("Driver for TI ACX1xx based wireless cards (CardBus/PCI/USB)");
11285 +/***********************************************************************
11287 +/* Probably a number of acx's itermediate buffers for USB transfers,
11288 +** not to be confused with number of descriptors in tx/rx rings
11289 +** (which are not directly accessible to host in USB devices) */
11290 +#define USB_RX_CNT 10
11291 +#define USB_TX_CNT 10
11294 +/***********************************************************************
11297 +/* minutes to wait until next radio recalibration: */
11298 +#define RECALIB_PAUSE 5
11300 +const u8 reg_domain_ids[] =
11301 + { 0x10, 0x20, 0x30, 0x31, 0x32, 0x40, 0x41, 0x51 };
11302 +/* stupid workaround for the fact that in C the size of an external array
11303 + * cannot be determined from within a second file */
11304 +const u8 reg_domain_ids_len = sizeof(reg_domain_ids);
11305 +static const u16 reg_domain_channel_masks[] =
11306 + { 0x07ff, 0x07ff, 0x1fff, 0x0600, 0x1e00, 0x2000, 0x3fff, 0x01fc };
11309 +/***********************************************************************
11310 +** Debugging support
11312 +#ifdef PARANOID_LOCKING
11313 +static unsigned max_lock_time;
11314 +static unsigned max_sem_time;
11317 +acx_lock_unhold() { max_lock_time = 0; }
11319 +acx_sem_unhold() { max_sem_time = 0; }
11321 +static inline const char*
11322 +sanitize_str(const char *s)
11324 + const char* t = strrchr(s, '/');
11325 + if (t) return t + 1;
11330 +acx_lock_debug(wlandevice_t *priv, const char* where)
11332 + int count = 100*1000*1000;
11333 + where = sanitize_str(where);
11334 + while (--count) {
11335 + if (!spin_is_locked(&priv->lock)) break;
11339 + printk(KERN_EMERG "LOCKUP: already taken at %s!\n", priv->last_lock);
11342 + priv->last_lock = where;
11343 + rdtscl(priv->lock_time);
11346 +acx_unlock_debug(wlandevice_t *priv, const char* where)
11349 + if (!spin_is_locked(&priv->lock)) {
11350 + where = sanitize_str(where);
11351 + printk(KERN_EMERG "STRAY UNLOCK at %s!\n", where);
11355 + if (acx_debug & L_LOCK) {
11358 + diff -= priv->lock_time;
11359 + if (diff > max_lock_time) {
11360 + where = sanitize_str(where);
11361 + printk("max lock hold time %d CPU ticks from %s "
11362 + "to %s\n", diff, priv->last_lock, where);
11363 + max_lock_time = diff;
11368 +acx_down_debug(wlandevice_t *priv, const char* where)
11371 + int count = 5000/5;
11372 + where = sanitize_str(where);
11374 + while (--count) {
11375 + sem_count = atomic_read(&priv->sem.count);
11376 + if (sem_count) break;
11380 + printk(KERN_EMERG "D STATE at %s! last sem at %s\n",
11381 + where, priv->last_sem);
11384 + priv->last_sem = where;
11385 + priv->sem_time = jiffies;
11386 + down(&priv->sem);
11387 + if (acx_debug & L_LOCK) {
11388 + printk("%s: sem_down %d -> %d\n",
11389 + where, sem_count, atomic_read(&priv->sem.count));
11393 +acx_up_debug(wlandevice_t *priv, const char* where)
11395 + int sem_count = atomic_read(&priv->sem.count);
11397 + where = sanitize_str(where);
11398 + printk(KERN_EMERG "STRAY UP at %s! sem.count=%d\n", where, sem_count);
11401 + if (acx_debug & L_LOCK) {
11402 + unsigned diff = jiffies - priv->sem_time;
11403 + if (diff > max_sem_time) {
11404 + where = sanitize_str(where);
11405 + printk("max sem hold time %d jiffies from %s "
11406 + "to %s\n", diff, priv->last_sem, where);
11407 + max_sem_time = diff;
11411 + if (acx_debug & L_LOCK) {
11412 + where = sanitize_str(where);
11413 + printk("%s: sem_up %d -> %d\n",
11414 + where, sem_count, atomic_read(&priv->sem.count));
11417 +#endif /* PARANOID_LOCKING */
11420 +/***********************************************************************
11424 +static int acx_debug_func_indent;
11425 +#define DEBUG_TSC 0
11426 +#define FUNC_INDENT_INCREMENT 2
11429 +#define TIMESTAMP(d) unsigned long d; rdtscl(d)
11431 +#define TIMESTAMP(d) unsigned long d = jiffies
11435 +spaces[] = " " " "; /* Nx10 spaces */
11438 +log_fn_enter(const char *funcname)
11443 + indent = acx_debug_func_indent;
11444 + if (indent >= sizeof(spaces))
11445 + indent = sizeof(spaces)-1;
11447 + printk("%08ld %s==> %s\n",
11449 + spaces + (sizeof(spaces)-1) - indent,
11453 + acx_debug_func_indent += FUNC_INDENT_INCREMENT;
11456 +log_fn_exit(const char *funcname)
11461 + acx_debug_func_indent -= FUNC_INDENT_INCREMENT;
11463 + indent = acx_debug_func_indent;
11464 + if (indent >= sizeof(spaces))
11465 + indent = sizeof(spaces)-1;
11467 + printk("%08ld %s<== %s\n",
11469 + spaces + (sizeof(spaces)-1) - indent,
11474 +log_fn_exit_v(const char *funcname, int v)
11479 + acx_debug_func_indent -= FUNC_INDENT_INCREMENT;
11481 + indent = acx_debug_func_indent;
11482 + if (indent >= sizeof(spaces))
11483 + indent = sizeof(spaces)-1;
11485 + printk("%08ld %s<== %s: %08X\n",
11487 + spaces + (sizeof(spaces)-1) - indent,
11492 +#endif /* ACX_DEBUG > 1 */
11495 +/***********************************************************************
11496 +** Basically a msleep with logging
11499 +acx_s_msleep(int ms)
11507 +/***********************************************************************
11508 +** Not inlined: it's larger than it seems
11511 +acx_print_mac(const char *head, const u8 *mac, const char *tail)
11513 + printk("%s"MACSTR"%s", head, MAC(mac), tail);
11517 +/***********************************************************************
11518 +** acx_get_status_name
11520 +static const char*
11521 +acx_get_status_name(u16 status)
11523 + static const char * const str[] = {
11524 + "STOPPED", "SCANNING", "WAIT_AUTH",
11525 + "AUTHENTICATED", "ASSOCIATED", "INVALID??"
11527 + return str[(status < VEC_SIZE(str)) ? status : VEC_SIZE(str)-1];
11531 +/***********************************************************************
11532 +** acx_get_packet_type_string
11536 +acx_get_packet_type_string(u16 fc)
11538 + static const char * const mgmt_arr[] = {
11539 + "MGMT/AssocReq", "MGMT/AssocResp", "MGMT/ReassocReq",
11540 + "MGMT/ReassocResp", "MGMT/ProbeReq", "MGMT/ProbeResp",
11541 + "MGMT/UNKNOWN", "MGMT/UNKNOWN", "MGMT/Beacon", "MGMT/ATIM",
11542 + "MGMT/Disassoc", "MGMT/Authen", "MGMT/Deauthen"
11544 + static const char * const ctl_arr[] = {
11545 + "CTL/PSPoll", "CTL/RTS", "CTL/CTS", "CTL/Ack", "CTL/CFEnd",
11548 + static const char * const data_arr[] = {
11549 + "DATA/DataOnly", "DATA/Data CFAck", "DATA/Data CFPoll",
11550 + "DATA/Data CFAck/CFPoll", "DATA/Null", "DATA/CFAck",
11551 + "DATA/CFPoll", "DATA/CFAck/CFPoll"
11553 + const char *str = "UNKNOWN";
11554 + u8 fstype = (WF_FC_FSTYPE & fc) >> 4;
11557 + switch (WF_FC_FTYPE & fc) {
11558 + case WF_FTYPE_MGMT:
11559 + str = "MGMT/UNKNOWN";
11560 + if (fstype < VEC_SIZE(mgmt_arr))
11561 + str = mgmt_arr[fstype];
11563 + case WF_FTYPE_CTL:
11564 + ctl = fstype - 0x0a;
11565 + str = "CTL/UNKNOWN";
11566 + if (ctl < VEC_SIZE(ctl_arr))
11567 + str = ctl_arr[ctl];
11569 + case WF_FTYPE_DATA:
11570 + str = "DATA/UNKNOWN";
11571 + if (fstype < VEC_SIZE(data_arr))
11572 + str = data_arr[fstype];
11580 +/***********************************************************************
11581 +** acx_cmd_status_str
11584 +acx_cmd_status_str(unsigned int state)
11586 + static const char * const cmd_error_strings[] = {
11589 + "Unknown Command",
11590 + "Invalid Information Element",
11591 + "Channel rejected",
11592 + "Channel invalid in current regulatory domain",
11594 + "Command rejected (read-only information element)",
11595 + "Command rejected",
11596 + "Already asleep",
11597 + "TX in progress",
11600 + "RX in progress",
11601 + "Invalid parameter",
11602 + "Scan in progress",
11605 + return state < VEC_SIZE(cmd_error_strings) ?
11606 + cmd_error_strings[state] : "UNKNOWN REASON";
11610 +/***********************************************************************
11611 +** get_status_string
11613 +static const char*
11614 +get_status_string(unsigned int status)
11616 + /* A bit shortened, but hopefully still understandable */
11617 + static const char * const status_str[] = {
11618 + /* 0 */ "Successful",
11619 + /* 1 */ "Unspecified failure",
11620 + /* 2 */ "reserved",
11621 + /* 3 */ "reserved",
11622 + /* 4 */ "reserved",
11623 + /* 5 */ "reserved",
11624 + /* 6 */ "reserved",
11625 + /* 7 */ "reserved",
11626 + /* 8 */ "reserved",
11627 + /* 9 */ "reserved",
11628 + /*10 */ "Cannot support all requested capabilities in Capability Information field",
11629 + /*11 */ "Reassoc denied (reason outside of 802.11b scope)",
11630 + /*12 */ "Assoc denied (reason outside of 802.11b scope), maybe MAC filtering by peer?",
11631 + /*13 */ "Responding station doesnt support specified auth algorithm",
11632 + /*14 */ "Auth rejected: wrong transaction sequence number",
11633 + /*15 */ "Auth rejected: challenge failure",
11634 + /*16 */ "Auth rejected: timeout for next frame in sequence",
11635 + /*17 */ "Assoc denied: too many STAs on this AP",
11636 + /*18 */ "Assoc denied: requesting STA doesnt support all data rates in basic set",
11637 + /*19 */ "Assoc denied: requesting STA doesnt support Short Preamble",
11638 + /*20 */ "Assoc denied: requesting STA doesnt support PBCC Modulation",
11639 + /*21 */ "Assoc denied: requesting STA doesnt support Channel Agility"
11640 + /*22 */ "reserved",
11641 + /*23 */ "reserved",
11642 + /*24 */ "reserved",
11643 + /*25 */ "Assoc denied: requesting STA doesnt support Short Slot Time",
11644 + /*26 */ "Assoc denied: requesting STA doesnt support DSSS-OFDM"
11647 + return status_str[status < VEC_SIZE(status_str) ? status : 2];
11651 +/***********************************************************************
11654 +acx_log_bad_eid(wlan_hdr_t* hdr, int len, wlan_ie_t* ie_ptr)
11656 + acxlog(L_ASSOC, "acx: unknown EID %d in mgmt frame at offset %d\n",
11657 + ie_ptr->eid, (int) ((u8*)ie_ptr - (u8*)hdr));
11658 + if (acx_debug & (L_DATA|L_ASSOC)) {
11659 + printk("frame (%s): ",
11660 + acx_get_packet_type_string(le16_to_cpu(hdr->fc)));
11661 + acx_dump_bytes(hdr, len);
11666 +/***********************************************************************
11670 +acx_dump_bytes(const void *data, int num)
11672 + const u8* ptr = (const u8*)data;
11679 + while (num >= 16) {
11680 + printk( "%02X %02X %02X %02X %02X %02X %02X %02X "
11681 + "%02X %02X %02X %02X %02X %02X %02X %02X\n",
11682 + ptr[0], ptr[1], ptr[2], ptr[3],
11683 + ptr[4], ptr[5], ptr[6], ptr[7],
11684 + ptr[8], ptr[9], ptr[10], ptr[11],
11685 + ptr[12], ptr[13], ptr[14], ptr[15]);
11690 + while (--num > 0)
11691 + printk("%02X ", *ptr++);
11692 + printk("%02X\n", *ptr);
11698 +/***********************************************************************
11699 +** maps acx111 tx descr rate field to acx100 one
11702 +bitpos2rate100[] = {
11703 + RATE100_1 ,/* 0 */
11704 + RATE100_2 ,/* 1 */
11705 + RATE100_5 ,/* 2 */
11706 + RATE100_2 ,/* 3, should not happen */
11707 + RATE100_2 ,/* 4, should not happen */
11708 + RATE100_11 ,/* 5 */
11709 + RATE100_2 ,/* 6, should not happen */
11710 + RATE100_2 ,/* 7, should not happen */
11711 + RATE100_22 ,/* 8 */
11712 + RATE100_2 ,/* 9, should not happen */
11713 + RATE100_2 ,/* 10, should not happen */
11714 + RATE100_2 ,/* 11, should not happen */
11715 + RATE100_2 ,/* 12, should not happen */
11716 + RATE100_2 ,/* 13, should not happen */
11717 + RATE100_2 ,/* 14, should not happen */
11718 + RATE100_2 ,/* 15, should not happen */
11722 +acx_rate111to100(u16 r) {
11723 + return bitpos2rate100[highest_bit(r)];
11727 +/***********************************************************************
11728 +** Calculate level like the feb 2003 windows driver seems to do
11731 +acx_signal_to_winlevel(u8 rawlevel)
11733 + /* u8 winlevel = (u8) (0.5 + 0.625 * rawlevel); */
11734 + u8 winlevel = ((4 + (rawlevel * 5)) / 8);
11736 + if (winlevel > 100)
11742 +acx_signal_determine_quality(u8 signal, u8 noise)
11746 + qual = (((signal - 30) * 100 / 70) + (100 - noise * 4)) / 2;
11756 +/***********************************************************************
11757 +** Interrogate/configure commands
11762 + ACX100_IE_ACX_TIMER_LEN,
11763 + ACX1xx_IE_POWER_MGMT_LEN,
11764 + ACX1xx_IE_QUEUE_CONFIG_LEN,
11765 + ACX100_IE_BLOCK_SIZE_LEN,
11766 + ACX1xx_IE_MEMORY_CONFIG_OPTIONS_LEN,
11767 + ACX1xx_IE_RATE_FALLBACK_LEN,
11768 + ACX100_IE_WEP_OPTIONS_LEN,
11769 + ACX1xx_IE_MEMORY_MAP_LEN, /* ACX1xx_IE_SSID_LEN, */
11771 + ACX1xx_IE_ASSOC_ID_LEN,
11773 + ACX111_IE_CONFIG_OPTIONS_LEN,
11774 + ACX1xx_IE_FWREV_LEN,
11775 + ACX1xx_IE_FCS_ERROR_COUNT_LEN,
11776 + ACX1xx_IE_MEDIUM_USAGE_LEN,
11777 + ACX1xx_IE_RXCONFIG_LEN,
11780 + ACX1xx_IE_FIRMWARE_STATISTICS_LEN,
11782 + ACX1xx_IE_FEATURE_CONFIG_LEN,
11783 + ACX111_IE_KEY_CHOOSE_LEN,
11787 +CtlLengthDot11[] = {
11789 + ACX1xx_IE_DOT11_STATION_ID_LEN,
11791 + ACX100_IE_DOT11_BEACON_PERIOD_LEN,
11792 + ACX1xx_IE_DOT11_DTIM_PERIOD_LEN,
11793 + ACX1xx_IE_DOT11_SHORT_RETRY_LIMIT_LEN,
11794 + ACX1xx_IE_DOT11_LONG_RETRY_LIMIT_LEN,
11795 + ACX100_IE_DOT11_WEP_DEFAULT_KEY_WRITE_LEN,
11796 + ACX1xx_IE_DOT11_MAX_XMIT_MSDU_LIFETIME_LEN,
11798 + ACX1xx_IE_DOT11_CURRENT_REG_DOMAIN_LEN,
11799 + ACX1xx_IE_DOT11_CURRENT_ANTENNA_LEN,
11801 + ACX1xx_IE_DOT11_TX_POWER_LEVEL_LEN,
11802 + ACX1xx_IE_DOT11_CURRENT_CCA_MODE_LEN,
11803 + ACX100_IE_DOT11_ED_THRESHOLD_LEN,
11804 + ACX1xx_IE_DOT11_WEP_DEFAULT_KEY_SET_LEN,
11811 +#define FUNC "configure"
11814 +acx_s_configure(wlandevice_t *priv, void *pdr, int type)
11818 +acx_s_configure_debug(wlandevice_t *priv, void *pdr, int type, const char* typestr)
11824 + if (type < 0x1000)
11825 + len = CtlLength[type];
11827 + len = CtlLengthDot11[type - 0x1000];
11829 + acxlog(L_CTL, FUNC"(type:%s,len:%u)\n", typestr, len);
11830 + if (unlikely(!len)) {
11831 + acxlog(L_DEBUG, "zero-length type %s?!\n", typestr);
11834 + ((acx_ie_generic_t *)pdr)->type = cpu_to_le16(type);
11835 + ((acx_ie_generic_t *)pdr)->len = cpu_to_le16(len);
11836 + res = acx_s_issue_cmd(priv, ACX1xx_CMD_CONFIGURE, pdr, len + 4);
11839 + printk("%s: "FUNC"(type:%s) FAILED\n", priv->netdev->name, typestr);
11841 + printk("%s: "FUNC"(type:0x%X) FAILED\n", priv->netdev->name, type);
11843 + /* dump_stack() is already done in issue_cmd() */
11849 +#define FUNC "interrogate"
11852 +acx_s_interrogate(wlandevice_t *priv, void *pdr, int type)
11856 +acx_s_interrogate_debug(wlandevice_t *priv, void *pdr, int type,
11857 + const char* typestr)
11863 + if (type < 0x1000)
11864 + len = CtlLength[type];
11866 + len = CtlLengthDot11[type-0x1000];
11867 + acxlog(L_CTL, FUNC"(type:%s,len:%u)\n", typestr, len);
11869 + printk("Type : %08x, Len : %04x\n",type,len);
11871 + ((acx_ie_generic_t *)pdr)->type = cpu_to_le16(type);
11872 + ((acx_ie_generic_t *)pdr)->len = cpu_to_le16(len);
11873 + res = acx_s_issue_cmd(priv, ACX1xx_CMD_INTERROGATE, pdr, len + 4);
11876 + printk("%s: "FUNC"(type:%s) FAILED\n", priv->netdev->name, typestr);
11878 + printk("%s: "FUNC"(type:0x%X) FAILED\n", priv->netdev->name, type);
11880 + /* dump_stack() is already done in issue_cmd() */
11887 +great_inquisitor(wlandevice_t *priv)
11890 + u16 type ACX_PACKED;
11891 + u16 len ACX_PACKED;
11892 + /* 0x200 was too large here: */
11893 + u8 data[0x100 - 4] ACX_PACKED;
11899 + /* 0..0x20, 0x1000..0x1020 */
11900 + for (type = 0; type <= 0x1020; type++) {
11901 + if (type == 0x21)
11903 + ie.type = cpu_to_le16(type);
11904 + ie.len = cpu_to_le16(sizeof(ie) - 4);
11905 + acx_s_issue_cmd(priv, ACX1xx_CMD_INTERROGATE, &ie, sizeof(ie));
11912 +#ifdef CONFIG_PROC_FS
11913 +/***********************************************************************
11916 +/***********************************************************************
11917 +** acx_l_proc_output
11918 +** Generate content for our /proc entry
11921 +** buf is a pointer to write output to
11922 +** priv is the usual pointer to our private struct wlandevice
11924 +** number of bytes actually written to buf
11929 +acx_l_proc_output(char *buf, wlandevice_t *priv)
11937 + "acx driver version:\t\t" WLAN_RELEASE "\n"
11938 + "Wireless extension version:\t" STRING(WIRELESS_EXT) "\n"
11939 + "chip name:\t\t\t%s (0x%08X)\n"
11940 + "radio type:\t\t\t0x%02X\n"
11941 + "form factor:\t\t\t0x%02X\n"
11942 + "EEPROM version:\t\t\t0x%02X\n"
11943 + "firmware version:\t\t%s (0x%08X)\n",
11944 + priv->chip_name, priv->firmware_id,
11945 + priv->radio_type,
11946 + priv->form_factor,
11947 + priv->eeprom_version,
11948 + priv->firmware_version, priv->firmware_numver);
11950 + for (i = 0; i < VEC_SIZE(priv->sta_list); i++) {
11951 + struct client *bss = &priv->sta_list[i];
11952 + if (!bss->used) continue;
11953 + p += sprintf(p, "BSS %u BSSID "MACSTR" ESSID %s channel %u "
11954 + "Cap 0x%X SIR %u SNR %u\n",
11955 + i, MAC(bss->bssid), (char*)bss->essid, bss->channel,
11956 + bss->cap_info, bss->sir, bss->snr);
11958 + p += sprintf(p, "status:\t\t\t%u (%s)\n",
11959 + priv->status, acx_get_status_name(priv->status));
11961 + FN_EXIT1(p - buf);
11966 +/***********************************************************************
11969 +acx_s_proc_diag_output(char *buf, wlandevice_t *priv)
11972 + fw_stats_t *fw_stats;
11973 + unsigned long flags;
11977 + fw_stats = kmalloc(sizeof(fw_stats_t), GFP_KERNEL);
11982 + memset(fw_stats, 0, sizeof(fw_stats_t));
11984 + acx_lock(priv, flags);
11986 + if (IS_PCI(priv))
11987 + p = acxpci_s_proc_diag_output(p, priv);
11991 + "** network status **\n"
11992 + "dev_state_mask 0x%04X\n"
11993 + "status %u (%s), "
11994 + "mode %u, channel %u, "
11995 + "reg_dom_id 0x%02X, reg_dom_chanmask 0x%04X, ",
11996 + priv->dev_state_mask,
11997 + priv->status, acx_get_status_name(priv->status),
11998 + priv->mode, priv->channel,
11999 + priv->reg_dom_id, priv->reg_dom_chanmask
12002 + "ESSID \"%s\", essid_active %d, essid_len %d, "
12003 + "essid_for_assoc \"%s\", nick \"%s\"\n"
12004 + "WEP ena %d, restricted %d, idx %d\n",
12005 + priv->essid, priv->essid_active, (int)priv->essid_len,
12006 + priv->essid_for_assoc, priv->nick,
12007 + priv->wep_enabled, priv->wep_restricted,
12008 + priv->wep_current_index);
12009 + p += sprintf(p, "dev_addr "MACSTR"\n", MAC(priv->dev_addr));
12010 + p += sprintf(p, "bssid "MACSTR"\n", MAC(priv->bssid));
12011 + p += sprintf(p, "ap_filter "MACSTR"\n", MAC(priv->ap));
12015 + "** PHY status **\n"
12016 + "tx_disabled %d, tx_level_dbm %d\n" /* "tx_level_val %d, tx_level_auto %d\n" */
12017 + "sensitivity %d, antenna 0x%02X, ed_threshold %d, cca %d, preamble_mode %d\n"
12018 + "rts_threshold %d, short_retry %d, long_retry %d, msdu_lifetime %d, listen_interval %d, beacon_interval %d\n",
12019 + priv->tx_disabled, priv->tx_level_dbm, /* priv->tx_level_val, priv->tx_level_auto, */
12020 + priv->sensitivity, priv->antenna, priv->ed_threshold, priv->cca, priv->preamble_mode,
12021 + priv->rts_threshold, priv->short_retry, priv->long_retry, priv->msdu_lifetime, priv->listen_interval, priv->beacon_interval);
12023 + acx_unlock(priv, flags);
12025 + if (OK != acx_s_interrogate(priv, fw_stats, ACX1xx_IE_FIRMWARE_STATISTICS))
12028 + "** Firmware **\n"
12029 + "QUERY FAILED!!\n");
12033 + "** Firmware **\n"
12034 + "version \"%s\"\n"
12035 + "tx_desc_overfl %u, rx_OutOfMem %u, rx_hdr_overfl %u, rx_hdr_use_next %u\n"
12036 + "rx_dropped_frame %u, rx_frame_ptr_err %u, rx_xfr_hint_trig %u, rx_dma_req %u\n"
12037 + "rx_dma_err %u, tx_dma_req %u, tx_dma_err %u, cmd_cplt %u, fiq %u\n"
12038 + "rx_hdrs %u, rx_cmplt %u, rx_mem_overfl %u, rx_rdys %u, irqs %u\n"
12039 + "acx_trans_procs %u, decrypt_done %u, dma_0_done %u, dma_1_done %u\n",
12040 + priv->firmware_version,
12041 + le32_to_cpu(fw_stats->tx_desc_of),
12042 + le32_to_cpu(fw_stats->rx_oom),
12043 + le32_to_cpu(fw_stats->rx_hdr_of),
12044 + le32_to_cpu(fw_stats->rx_hdr_use_next),
12045 + le32_to_cpu(fw_stats->rx_dropped_frame),
12046 + le32_to_cpu(fw_stats->rx_frame_ptr_err),
12047 + le32_to_cpu(fw_stats->rx_xfr_hint_trig),
12048 + le32_to_cpu(fw_stats->rx_dma_req),
12049 + le32_to_cpu(fw_stats->rx_dma_err),
12050 + le32_to_cpu(fw_stats->tx_dma_req),
12051 + le32_to_cpu(fw_stats->tx_dma_err),
12052 + le32_to_cpu(fw_stats->cmd_cplt),
12053 + le32_to_cpu(fw_stats->fiq),
12054 + le32_to_cpu(fw_stats->rx_hdrs),
12055 + le32_to_cpu(fw_stats->rx_cmplt),
12056 + le32_to_cpu(fw_stats->rx_mem_of),
12057 + le32_to_cpu(fw_stats->rx_rdys),
12058 + le32_to_cpu(fw_stats->irqs),
12059 + le32_to_cpu(fw_stats->acx_trans_procs),
12060 + le32_to_cpu(fw_stats->decrypt_done),
12061 + le32_to_cpu(fw_stats->dma_0_done),
12062 + le32_to_cpu(fw_stats->dma_1_done));
12064 + "tx_exch_complet %u, commands %u, acx_rx_procs %u\n"
12065 + "hw_pm_mode_changes %u, host_acks %u, pci_pm %u, acm_wakeups %u\n"
12066 + "wep_key_count %u, wep_default_key_count %u, dot11_def_key_mib %u\n"
12067 + "wep_key_not_found %u, wep_decrypt_fail %u\n",
12068 + le32_to_cpu(fw_stats->tx_exch_complet),
12069 + le32_to_cpu(fw_stats->commands),
12070 + le32_to_cpu(fw_stats->acx_rx_procs),
12071 + le32_to_cpu(fw_stats->hw_pm_mode_changes),
12072 + le32_to_cpu(fw_stats->host_acks),
12073 + le32_to_cpu(fw_stats->pci_pm),
12074 + le32_to_cpu(fw_stats->acm_wakeups),
12075 + le32_to_cpu(fw_stats->wep_key_count),
12076 + le32_to_cpu(fw_stats->wep_default_key_count),
12077 + le32_to_cpu(fw_stats->dot11_def_key_mib),
12078 + le32_to_cpu(fw_stats->wep_key_not_found),
12079 + le32_to_cpu(fw_stats->wep_decrypt_fail));
12084 + FN_EXIT1(p - buf);
12089 +/***********************************************************************
12092 +acx_s_proc_phy_output(char *buf, wlandevice_t *priv)
12100 + if (RADIO_RFMD_11 != priv->radio_type) {
12101 + printk("sorry, not yet adapted for radio types "
12102 + "other than RFMD, please verify "
12103 + "PHY size etc. first!\n");
12108 + /* The PHY area is only 0x80 bytes long; further pages after that
12109 + * only have some page number registers with altered value,
12110 + * all other registers remain the same. */
12111 + for (i = 0; i < 0x80; i++) {
12112 + acx_s_read_phy_reg(priv, i, p++);
12115 + FN_EXIT1(p - buf);
12120 +/***********************************************************************
12121 +** acx_e_read_proc_XXXX
12122 +** Handle our /proc entry
12125 +** standard kernel read_proc interface
12127 +** number of bytes written to buf
12132 +acx_e_read_proc(char *buf, char **start, off_t offset, int count,
12133 + int *eof, void *data)
12135 + wlandevice_t *priv = (wlandevice_t *)data;
12136 + unsigned long flags;
12141 + acx_sem_lock(priv);
12142 + acx_lock(priv, flags);
12144 + length = acx_l_proc_output(buf, priv);
12145 + acx_unlock(priv, flags);
12146 + acx_sem_unlock(priv);
12148 + /* housekeeping */
12149 + if (length <= offset + count)
12151 + *start = buf + offset;
12152 + length -= offset;
12153 + if (length > count)
12157 + FN_EXIT1(length);
12162 +acx_e_read_proc_diag(char *buf, char **start, off_t offset, int count,
12163 + int *eof, void *data)
12165 + wlandevice_t *priv = (wlandevice_t *)data;
12170 + acx_sem_lock(priv);
12172 + length = acx_s_proc_diag_output(buf, priv);
12173 + acx_sem_unlock(priv);
12175 + /* housekeeping */
12176 + if (length <= offset + count)
12178 + *start = buf + offset;
12179 + length -= offset;
12180 + if (length > count)
12184 + FN_EXIT1(length);
12189 +acx_e_read_proc_eeprom(char *buf, char **start, off_t offset, int count,
12190 + int *eof, void *data)
12192 + wlandevice_t *priv = (wlandevice_t *)data;
12199 + if (IS_PCI(priv)) {
12200 + acx_sem_lock(priv);
12201 + length = acx_proc_eeprom_output(buf, priv);
12202 + acx_sem_unlock(priv);
12205 + /* housekeeping */
12206 + if (length <= offset + count)
12208 + *start = buf + offset;
12209 + length -= offset;
12210 + if (length > count)
12214 + FN_EXIT1(length);
12219 +acx_e_read_proc_phy(char *buf, char **start, off_t offset, int count,
12220 + int *eof, void *data)
12222 + wlandevice_t *priv = (wlandevice_t *)data;
12227 + acx_sem_lock(priv);
12229 + length = acx_s_proc_phy_output(buf, priv);
12230 + acx_sem_unlock(priv);
12232 + /* housekeeping */
12233 + if (length <= offset + count)
12235 + *start = buf + offset;
12236 + length -= offset;
12237 + if (length > count)
12241 + FN_EXIT1(length);
12246 +/***********************************************************************
12247 +** /proc files registration
12249 +static const char * const
12250 +proc_files[] = { "", "_diag", "_eeprom", "_phy" };
12252 +static read_proc_t * const
12253 +acx_proc_funcs[] = {
12255 + acx_e_read_proc_diag,
12256 + acx_e_read_proc_eeprom,
12257 + acx_e_read_proc_phy
12261 +manage_proc_entries(const struct net_device *dev, int remove)
12263 + /* doh, netdev_priv() doesn't have const! */
12264 + wlandevice_t *priv = netdev_priv((struct net_device *)dev);
12265 + char procbuf[80];
12268 + for (i = 0; i < 4; i++) {
12269 + sprintf(procbuf, "driver/acx_%s", dev->name);
12270 + strcat(procbuf, proc_files[i]);
12272 + acxlog(L_INIT, "creating /proc entry %s\n", procbuf);
12273 + if (!create_proc_read_entry(procbuf, 0, 0, acx_proc_funcs[i], priv))
12276 + acxlog(L_INIT, "removing /proc entry %s\n", procbuf);
12277 + remove_proc_entry(procbuf, NULL);
12284 +acx_proc_register_entries(const struct net_device *dev)
12286 + return manage_proc_entries(dev, 0);
12290 +acx_proc_unregister_entries(const struct net_device *dev)
12292 + return manage_proc_entries(dev, 1);
12294 +#endif /* CONFIG_PROC_FS */
12297 +/***********************************************************************
12298 +** acx_cmd_join_bssid
12300 +** Common code for both acx100 and acx111.
12302 +/* NB: does NOT match RATE100_nn but matches ACX[111]_SCAN_RATE_n */
12304 +bitpos2genframe_txrate[] = {
12305 + 10, /* 0. 1 Mbit/s */
12306 + 20, /* 1. 2 Mbit/s */
12307 + 55, /* 2. 5.5 Mbit/s */
12308 + 0x0B, /* 3. 6 Mbit/s */
12309 + 0x0F, /* 4. 9 Mbit/s */
12310 + 110, /* 5. 11 Mbit/s */
12311 + 0x0A, /* 6. 12 Mbit/s */
12312 + 0x0E, /* 7. 18 Mbit/s */
12313 + 220, /* 8. 22 Mbit/s */
12314 + 0x09, /* 9. 24 Mbit/s */
12315 + 0x0D, /* 10. 36 Mbit/s */
12316 + 0x08, /* 11. 48 Mbit/s */
12317 + 0x0C, /* 12. 54 Mbit/s */
12318 + 10, /* 13. 1 Mbit/s, should never happen */
12319 + 10, /* 14. 1 Mbit/s, should never happen */
12320 + 10, /* 15. 1 Mbit/s, should never happen */
12323 +/* Looks scary, eh?
12324 +** Actually, each one compiled into one AND and one SHIFT,
12325 +** 31 bytes in x86 asm (more if uints are replaced by u16/u8) */
12326 +static unsigned int
12327 +rate111to5bits(unsigned int rate)
12329 + return (rate & 0x7)
12330 + | ( (rate & RATE111_11) / (RATE111_11/JOINBSS_RATES_11) )
12331 + | ( (rate & RATE111_22) / (RATE111_22/JOINBSS_RATES_22) )
12336 +acx_s_cmd_join_bssid(wlandevice_t *priv, const u8 *bssid)
12338 + acx_joinbss_t tmp;
12339 + int dtim_interval;
12344 + dtim_interval = (ACX_MODE_0_ADHOC == priv->mode) ?
12345 + 1 : priv->dtim_interval;
12347 + memset(&tmp, 0, sizeof(tmp));
12349 + for (i = 0; i < ETH_ALEN; i++) {
12350 + tmp.bssid[i] = bssid[ETH_ALEN-1 - i];
12353 + tmp.beacon_interval = cpu_to_le16(priv->beacon_interval);
12355 + /* basic rate set. Control frame responses (such as ACK or CTS frames)
12356 + ** are sent with one of these rates */
12357 + if (IS_ACX111(priv)) {
12358 + /* It was experimentally determined that rates_basic
12359 + ** can take 11g rates as well, not only rates
12360 + ** defined with JOINBSS_RATES_BASIC111_nnn.
12361 + ** Just use RATE111_nnn constants... */
12362 + tmp.u.acx111.dtim_interval = dtim_interval;
12363 + tmp.u.acx111.rates_basic = cpu_to_le16(priv->rate_basic);
12364 + acxlog(L_ASSOC, "%s rates_basic %04X, rates_supported %04X\n",
12365 + __func__, priv->rate_basic, priv->rate_oper);
12367 + tmp.u.acx100.dtim_interval = dtim_interval;
12368 + tmp.u.acx100.rates_basic = rate111to5bits(priv->rate_basic);
12369 + tmp.u.acx100.rates_supported = rate111to5bits(priv->rate_oper);
12370 + acxlog(L_ASSOC, "%s rates_basic %04X->%02X, "
12371 + "rates_supported %04X->%02X\n",
12373 + priv->rate_basic, tmp.u.acx100.rates_basic,
12374 + priv->rate_oper, tmp.u.acx100.rates_supported);
12377 + /* Setting up how Beacon, Probe Response, RTS, and PS-Poll frames
12378 + ** will be sent (rate/modulation/preamble) */
12379 + tmp.genfrm_txrate = bitpos2genframe_txrate[lowest_bit(priv->rate_basic)];
12380 + tmp.genfrm_mod_pre = 0; /* FIXME: was = priv->capab_short (which is always 0); */
12381 + /* we can use short pre *if* all peers can understand it */
12382 + /* FIXME #2: we need to correctly set PBCC/OFDM bits here too */
12384 + /* we switch fw to STA mode in MONITOR mode, it seems to be
12385 + ** the only mode where fw does not emit beacons by itself
12386 + ** but allows us to send anything (we really want to retain
12387 + ** ability to tx arbitrary frames in MONITOR mode)
12389 + tmp.macmode = (priv->mode != ACX_MODE_MONITOR ? priv->mode : ACX_MODE_2_STA);
12390 + tmp.channel = priv->channel;
12391 + tmp.essid_len = priv->essid_len;
12392 + /* NOTE: the code memcpy'd essid_len + 1 before, which is WRONG! */
12393 + memcpy(tmp.essid, priv->essid, tmp.essid_len);
12394 + acx_s_issue_cmd(priv, ACX1xx_CMD_JOIN, &tmp, tmp.essid_len + 0x11);
12396 + acxlog(L_ASSOC|L_DEBUG, "BSS_Type = %u\n", tmp.macmode);
12397 + acxlog_mac(L_ASSOC|L_DEBUG, "JoinBSSID MAC:", priv->bssid, "\n");
12399 + acx_update_capabilities(priv);
12404 +/***********************************************************************
12405 +** acx_s_cmd_start_scan
12407 +** Issue scan command to the hardware
12410 +acx100_s_scan_chan(wlandevice_t *priv)
12416 + memset(&s, 0, sizeof(s));
12417 + s.count = cpu_to_le16(priv->scan_count);
12418 + s.start_chan = cpu_to_le16(1);
12419 + s.flags = cpu_to_le16(0x8000);
12420 + s.max_rate = priv->scan_rate;
12421 + s.options = priv->scan_mode;
12422 + s.chan_duration = cpu_to_le16(priv->scan_duration);
12423 + s.max_probe_delay = cpu_to_le16(priv->scan_probe_delay);
12425 + acx_s_issue_cmd(priv, ACX1xx_CMD_SCAN, &s, sizeof(s));
12430 +acx111_s_scan_chan(wlandevice_t *priv)
12436 + memset(&s, 0, sizeof(s));
12437 + s.count = cpu_to_le16(priv->scan_count);
12438 + s.channel_list_select = 0; /* scan every allowed channel */
12439 + /*s.channel_list_select = 1;*/ /* scan given channels */
12440 + s.rate = priv->scan_rate;
12441 + s.options = priv->scan_mode;
12442 + s.chan_duration = cpu_to_le16(priv->scan_duration);
12443 + s.max_probe_delay = cpu_to_le16(priv->scan_probe_delay);
12444 + /*s.modulation = 0x40;*/ /* long preamble? OFDM? -> only for active scan */
12445 + s.modulation = 0;
12446 + /*s.channel_list[0] = 6;
12447 + s.channel_list[1] = 4;*/
12449 + acx_s_issue_cmd(priv, ACX1xx_CMD_SCAN, &s, sizeof(s));
12454 +acx_s_cmd_start_scan(wlandevice_t *priv)
12456 + /* time_before check is 'just in case' thing */
12457 + if (!(priv->irq_status & HOST_INT_SCAN_COMPLETE)
12458 + && time_before(jiffies, priv->scan_start + 10*HZ)
12460 + acxlog(L_INIT, "start_scan: seems like previous scan "
12461 + "is still running. Not starting anew. Please report\n");
12465 + acxlog(L_INIT, "starting radio scan\n");
12466 + /* remember that fw is commanded to do scan */
12467 + priv->scan_start = jiffies;
12468 + CLEAR_BIT(priv->irq_status, HOST_INT_SCAN_COMPLETE);
12470 + if (IS_ACX100(priv)) {
12471 + acx100_s_scan_chan(priv);
12473 + acx111_s_scan_chan(priv);
12478 +/***********************************************************************
12479 +** acx111 feature config
12482 +acx111_s_get_feature_config(wlandevice_t *priv,
12483 + u32 *feature_options, u32 *data_flow_options)
12485 + struct acx111_ie_feature_config fc;
12487 + if (!IS_ACX111(priv)) {
12491 + memset(&fc, 0, sizeof(fc));
12493 + if (OK != acx_s_interrogate(priv, &fc, ACX1xx_IE_FEATURE_CONFIG)) {
12497 + "got Feature option:0x%X, DataFlow option: 0x%X\n",
12498 + fc.feature_options,
12499 + fc.data_flow_options);
12501 + if (feature_options)
12502 + *feature_options = le32_to_cpu(fc.feature_options);
12503 + if (data_flow_options)
12504 + *data_flow_options = le32_to_cpu(fc.data_flow_options);
12510 +acx111_s_set_feature_config(wlandevice_t *priv,
12511 + u32 feature_options, u32 data_flow_options,
12512 + unsigned int mode /* 0 == remove, 1 == add, 2 == set */)
12514 + struct acx111_ie_feature_config fc;
12516 + if (!IS_ACX111(priv)) {
12520 + if ((mode < 0) || (mode > 2))
12524 + /* need to modify old data */
12525 + acx111_s_get_feature_config(priv, &fc.feature_options, &fc.data_flow_options);
12527 + /* need to set a completely new value */
12528 + fc.feature_options = 0;
12529 + fc.data_flow_options = 0;
12532 + if (mode == 0) { /* remove */
12533 + CLEAR_BIT(fc.feature_options, cpu_to_le32(feature_options));
12534 + CLEAR_BIT(fc.data_flow_options, cpu_to_le32(data_flow_options));
12535 + } else { /* add or set */
12536 + SET_BIT(fc.feature_options, cpu_to_le32(feature_options));
12537 + SET_BIT(fc.data_flow_options, cpu_to_le32(data_flow_options));
12541 + "old: feature 0x%08X dataflow 0x%08X. mode: %u\n"
12542 + "new: feature 0x%08X dataflow 0x%08X\n",
12543 + feature_options, data_flow_options, mode,
12544 + le32_to_cpu(fc.feature_options),
12545 + le32_to_cpu(fc.data_flow_options));
12547 + if (OK != acx_s_configure(priv, &fc, ACX1xx_IE_FEATURE_CONFIG)) {
12555 +acx111_s_feature_off(wlandevice_t *priv, u32 f, u32 d)
12557 + return acx111_s_set_feature_config(priv, f, d, 0);
12560 +acx111_s_feature_on(wlandevice_t *priv, u32 f, u32 d)
12562 + return acx111_s_set_feature_config(priv, f, d, 1);
12565 +acx111_s_feature_set(wlandevice_t *priv, u32 f, u32 d)
12567 + return acx111_s_set_feature_config(priv, f, d, 2);
12571 +/***********************************************************************
12572 +** acx100_s_init_memory_pools
12575 +acx100_s_init_memory_pools(wlandevice_t *priv, const acx_ie_memmap_t *mmt)
12577 + acx100_ie_memblocksize_t MemoryBlockSize;
12578 + acx100_ie_memconfigoption_t MemoryConfigOption;
12579 + int TotalMemoryBlocks;
12581 + int TotalRxBlockSize;
12583 + int TotalTxBlockSize;
12587 + /* Let's see if we can follow this:
12588 + first we select our memory block size (which I think is
12589 + completely arbitrary) */
12590 + MemoryBlockSize.size = cpu_to_le16(priv->memblocksize);
12592 + /* Then we alert the card to our decision of block size */
12593 + if (OK != acx_s_configure(priv, &MemoryBlockSize, ACX100_IE_BLOCK_SIZE)) {
12597 + /* We figure out how many total blocks we can create, using
12598 + the block size we chose, and the beginning and ending
12599 + memory pointers, i.e.: end-start/size */
12600 + TotalMemoryBlocks = (le32_to_cpu(mmt->PoolEnd) - le32_to_cpu(mmt->PoolStart)) / priv->memblocksize;
12602 + acxlog(L_DEBUG, "TotalMemoryBlocks=%u (%u bytes)\n",
12603 + TotalMemoryBlocks, TotalMemoryBlocks*priv->memblocksize);
12605 + /* MemoryConfigOption.DMA_config bitmask:
12606 + // access to ACX memory is to be done:
12607 + 0x00080000 // using PCI conf space?!
12608 + 0x00040000 // using IO instructions?
12609 + 0x00000000 // using memory access instructions
12610 + 0x00020000 // use local memory block linked list (else what?)
12611 + 0x00010000 // use host indirect descriptors (else host must access ACX memory?)
12613 + if (IS_PCI(priv)) {
12614 + MemoryConfigOption.DMA_config = cpu_to_le32(0x30000);
12615 + /* Declare start of the Rx host pool */
12616 + MemoryConfigOption.pRxHostDesc = cpu2acx(priv->rxhostdesc_startphy);
12617 + acxlog(L_DEBUG, "pRxHostDesc 0x%08X, rxhostdesc_startphy 0x%lX\n",
12618 + acx2cpu(MemoryConfigOption.pRxHostDesc),
12619 + (long)priv->rxhostdesc_startphy);
12621 + MemoryConfigOption.DMA_config = cpu_to_le32(0x20000);
12624 + /* 50% of the allotment of memory blocks go to tx descriptors */
12625 + TxBlockNum = TotalMemoryBlocks / 2;
12626 + MemoryConfigOption.TxBlockNum = cpu_to_le16(TxBlockNum);
12628 + /* and 50% go to the rx descriptors */
12629 + RxBlockNum = TotalMemoryBlocks - TxBlockNum;
12630 + MemoryConfigOption.RxBlockNum = cpu_to_le16(RxBlockNum);
12632 + /* size of the tx and rx descriptor queues */
12633 + TotalTxBlockSize = TxBlockNum * priv->memblocksize;
12634 + TotalRxBlockSize = RxBlockNum * priv->memblocksize;
12635 + acxlog(L_DEBUG, "TxBlockNum %u RxBlockNum %u TotalTxBlockSize %u "
12636 + "TotalTxBlockSize %u\n", TxBlockNum, RxBlockNum,
12637 + TotalTxBlockSize, TotalRxBlockSize);
12640 + /* align the tx descriptor queue to an alignment of 0x20 (32 bytes) */
12641 + MemoryConfigOption.rx_mem =
12642 + cpu_to_le32((le32_to_cpu(mmt->PoolStart) + 0x1f) & ~0x1f);
12644 + /* align the rx descriptor queue to units of 0x20
12645 + * and offset it by the tx descriptor queue */
12646 + MemoryConfigOption.tx_mem =
12647 + cpu_to_le32((le32_to_cpu(mmt->PoolStart) + TotalRxBlockSize + 0x1f) & ~0x1f);
12648 + acxlog(L_DEBUG, "rx_mem %08X rx_mem %08X\n",
12649 + MemoryConfigOption.tx_mem, MemoryConfigOption.rx_mem);
12651 + /* alert the device to our decision */
12652 + if (OK != acx_s_configure(priv, &MemoryConfigOption, ACX1xx_IE_MEMORY_CONFIG_OPTIONS)) {
12656 + /* and tell the device to kick it into gear */
12657 + if (OK != acx_s_issue_cmd(priv, ACX100_CMD_INIT_MEMORY, NULL, 0)) {
12663 + FN_EXIT1(NOT_OK);
12668 +/***********************************************************************
12669 +** acx100_s_create_dma_regions
12671 +** Note that this fn messes up heavily with hardware, but we cannot
12672 +** lock it (we need to sleep). Not a problem since IRQs can't happen
12675 +acx100_s_create_dma_regions(wlandevice_t *priv)
12677 + acx100_ie_queueconfig_t queueconf;
12678 + acx_ie_memmap_t memmap;
12679 + int res = NOT_OK;
12680 + u32 tx_queue_start, rx_queue_start;
12684 + /* read out the acx100 physical start address for the queues */
12685 + if (OK != acx_s_interrogate(priv, &memmap, ACX1xx_IE_MEMORY_MAP)) {
12689 + tx_queue_start = le32_to_cpu(memmap.QueueStart);
12690 + rx_queue_start = tx_queue_start + TX_CNT * sizeof(txdesc_t);
12692 + acxlog(L_DEBUG, "initializing Queue Indicator\n");
12694 + memset(&queueconf, 0, sizeof(queueconf));
12696 + /* Not needed for PCI, so we can avoid setting them altogether */
12697 + if (IS_USB(priv)) {
12698 + queueconf.NumTxDesc = USB_TX_CNT;
12699 + queueconf.NumRxDesc = USB_RX_CNT;
12702 + /* calculate size of queues */
12703 + queueconf.AreaSize = cpu_to_le32(
12704 + TX_CNT * sizeof(txdesc_t) +
12705 + RX_CNT * sizeof(rxdesc_t) + 8
12707 + queueconf.NumTxQueues = 1; /* number of tx queues */
12708 + /* sets the beginning of the tx descriptor queue */
12709 + queueconf.TxQueueStart = memmap.QueueStart;
12710 + /* done by memset: queueconf.TxQueuePri = 0; */
12711 + queueconf.RxQueueStart = cpu_to_le32(rx_queue_start);
12712 + queueconf.QueueOptions = 1; /* auto reset descriptor */
12713 + /* sets the end of the rx descriptor queue */
12714 + queueconf.QueueEnd = cpu_to_le32(
12715 + rx_queue_start + RX_CNT * sizeof(rxdesc_t)
12717 + /* sets the beginning of the next queue */
12718 + queueconf.HostQueueEnd = cpu_to_le32(le32_to_cpu(queueconf.QueueEnd) + 8);
12719 + if (OK != acx_s_configure(priv, &queueconf, ACX1xx_IE_QUEUE_CONFIG)) {
12724 + if (IS_PCI(priv)) {
12725 + /* sets the beginning of the rx descriptor queue, after the tx descrs */
12726 + if (OK != acx_s_create_hostdesc_queues(priv))
12728 + acx_create_desc_queues(priv, tx_queue_start, rx_queue_start);
12732 + if (OK != acx_s_interrogate(priv, &memmap, ACX1xx_IE_MEMORY_MAP)) {
12736 + memmap.PoolStart = cpu_to_le32(
12737 + (le32_to_cpu(memmap.QueueEnd) + 4 + 0x1f) & ~0x1f
12740 + if (OK != acx_s_configure(priv, &memmap, ACX1xx_IE_MEMORY_MAP)) {
12744 + if (OK != acx100_s_init_memory_pools(priv, &memmap)) {
12752 + acx_s_msleep(1000); /* ? */
12753 + if (IS_PCI(priv))
12754 + acx_free_desc_queues(priv);
12761 +/***********************************************************************
12762 +** acx111_s_create_dma_regions
12764 +** Note that this fn messes up heavily with hardware, but we cannot
12765 +** lock it (we need to sleep). Not a problem since IRQs can't happen
12767 +#define ACX111_PERCENT(percent) ((percent)/5)
12770 +acx111_s_create_dma_regions(wlandevice_t *priv)
12772 + struct acx111_ie_memoryconfig memconf;
12773 + struct acx111_ie_queueconfig queueconf;
12774 + u32 tx_queue_start, rx_queue_start;
12778 + /* Calculate memory positions and queue sizes */
12780 + /* Set up our host descriptor pool + data pool */
12781 + if (IS_PCI(priv)) {
12782 + if (OK != acx_s_create_hostdesc_queues(priv))
12786 + memset(&memconf, 0, sizeof(memconf));
12787 + /* the number of STAs (STA contexts) to support
12788 + ** NB: was set to 1 and everything seemed to work nevertheless... */
12789 + memconf.no_of_stations = cpu_to_le16(VEC_SIZE(priv->sta_list));
12790 + /* specify the memory block size. Default is 256 */
12791 + memconf.memory_block_size = cpu_to_le16(priv->memblocksize);
12792 + /* let's use 50%/50% for tx/rx (specify percentage, units of 5%) */
12793 + memconf.tx_rx_memory_block_allocation = ACX111_PERCENT(50);
12794 + /* set the count of our queues
12795 + ** NB: struct acx111_ie_memoryconfig shall be modified
12796 + ** if we ever will switch to more than one rx and/or tx queue */
12797 + memconf.count_rx_queues = 1;
12798 + memconf.count_tx_queues = 1;
12799 + /* 0 == Busmaster Indirect Memory Organization, which is what we want
12800 + * (using linked host descs with their allocated mem).
12801 + * 2 == Generic Bus Slave */
12802 + /* done by memset: memconf.options = 0; */
12803 + /* let's use 25% for fragmentations and 75% for frame transfers
12804 + * (specified in units of 5%) */
12805 + memconf.fragmentation = ACX111_PERCENT(75);
12806 + /* Rx descriptor queue config */
12807 + memconf.rx_queue1_count_descs = RX_CNT;
12808 + memconf.rx_queue1_type = 7; /* must be set to 7 */
12809 + /* done by memset: memconf.rx_queue1_prio = 0; low prio */
12810 + if (IS_PCI(priv)) {
12811 + memconf.rx_queue1_host_rx_start = cpu2acx(priv->rxhostdesc_startphy);
12813 + /* Tx descriptor queue config */
12814 + memconf.tx_queue1_count_descs = TX_CNT;
12815 + /* done by memset: memconf.tx_queue1_attributes = 0; lowest priority */
12817 + /* NB1: this looks wrong: (memconf,ACX1xx_IE_QUEUE_CONFIG),
12818 + ** (queueconf,ACX1xx_IE_MEMORY_CONFIG_OPTIONS) look swapped, eh?
12819 + ** But it is actually correct wrt IE numbers.
12820 + ** NB2: sizeof(memconf) == 28 == 0x1c but configure(ACX1xx_IE_QUEUE_CONFIG)
12821 + ** writes 0x20 bytes (because same IE for acx100 uses struct acx100_ie_queueconfig
12822 + ** which is 4 bytes larger. what a mess. TODO: clean it up) */
12823 + if (OK != acx_s_configure(priv, &memconf, ACX1xx_IE_QUEUE_CONFIG)) {
12827 + acx_s_interrogate(priv, &queueconf, ACX1xx_IE_MEMORY_CONFIG_OPTIONS);
12829 + tx_queue_start = le32_to_cpu(queueconf.tx1_queue_address);
12830 + rx_queue_start = le32_to_cpu(queueconf.rx1_queue_address);
12832 + acxlog(L_INIT, "dump queue head (from card):\n"
12834 + "tx_memory_block_address: %X\n"
12835 + "rx_memory_block_address: %X\n"
12836 + "tx1_queue address: %X\n"
12837 + "rx1_queue address: %X\n",
12838 + le16_to_cpu(queueconf.len),
12839 + le32_to_cpu(queueconf.tx_memory_block_address),
12840 + le32_to_cpu(queueconf.rx_memory_block_address),
12844 + if (IS_PCI(priv))
12845 + acx_create_desc_queues(priv, tx_queue_start, rx_queue_start);
12850 + if (IS_PCI(priv))
12851 + acx_free_desc_queues(priv);
12853 + FN_EXIT1(NOT_OK);
12858 +/***********************************************************************
12859 +** acx_s_set_defaults
12860 +** Called from acx_s_init_mac
12863 +acx_s_set_defaults(wlandevice_t *priv)
12865 + unsigned long flags;
12869 + /* query some settings from the card.
12870 + * NOTE: for some settings, e.g. CCA and ED (ACX100!), an initial
12871 + * query is REQUIRED, otherwise the card won't work correctly!! */
12872 + priv->get_mask = GETSET_ANTENNA|GETSET_SENSITIVITY|GETSET_STATION_ID|GETSET_REG_DOMAIN;
12873 + /* Only ACX100 supports ED and CCA */
12874 + if (IS_ACX100(priv))
12875 + priv->get_mask |= GETSET_CCA|GETSET_ED_THRESH;
12877 + acx_s_update_card_settings(priv, 0, 0);
12879 + acx_lock(priv, flags);
12881 + /* set our global interrupt mask */
12882 + if (IS_PCI(priv))
12883 + acx_set_interrupt_mask(priv);
12885 + priv->led_power = 1; /* LED is active on startup */
12886 + priv->brange_max_quality = 60; /* LED blink max quality is 60 */
12887 + priv->brange_time_last_state_change = jiffies;
12889 + /* copy the MAC address we just got from the card
12890 + * into our MAC address used during current 802.11 session */
12891 + MAC_COPY(priv->dev_addr, priv->netdev->dev_addr);
12892 + sprintf(priv->essid, "STA%02X%02X%02X",
12893 + priv->dev_addr[3], priv->dev_addr[4], priv->dev_addr[5]);
12894 + priv->essid_len = sizeof("STAxxxxxx") - 1; /* make sure to adapt if changed above! */
12895 + priv->essid_active = 1;
12897 + /* we have a nick field to waste, so why not abuse it
12898 + * to announce the driver version? ;-) */
12899 + strncpy(priv->nick, "acx " WLAN_RELEASE, IW_ESSID_MAX_SIZE);
12901 + if (IS_PCI(priv)) {
12902 + if (IS_ACX111(priv)) {
12903 + /* Hope this is correct, only tested with domain 0x30 */
12904 + acx_read_eeprom_offset(priv, 0x16F, &priv->reg_dom_id);
12905 + } else if (priv->eeprom_version < 5) {
12906 + acx_read_eeprom_offset(priv, 0x16F, &priv->reg_dom_id);
12908 + acx_read_eeprom_offset(priv, 0x171, &priv->reg_dom_id);
12912 + priv->channel = 1;
12913 + /* 0xffff would be better, but then we won't get a "scan complete"
12914 + * interrupt, so our current infrastructure will fail: */
12915 + priv->scan_count = 1;
12916 + priv->scan_mode = ACX_SCAN_OPT_PASSIVE;
12917 + /* Doesn't work for acx100, do it only for acx111 for now */
12918 + if (IS_ACX111(priv)) {
12919 + priv->scan_mode = ACX_SCAN_OPT_ACTIVE;
12921 + priv->scan_duration = 100;
12922 + priv->scan_probe_delay = 200;
12923 + priv->scan_rate = ACX_SCAN_RATE_1;
12925 + priv->auth_alg = WLAN_AUTH_ALG_OPENSYSTEM;
12926 + priv->preamble_mode = 2; /* auto */
12927 + priv->listen_interval = 100;
12928 + priv->beacon_interval = DEFAULT_BEACON_INTERVAL;
12929 + priv->mode = ACX_MODE_2_STA;
12930 + priv->dtim_interval = DEFAULT_DTIM_INTERVAL;
12932 + priv->msdu_lifetime = DEFAULT_MSDU_LIFETIME;
12933 + SET_BIT(priv->set_mask, SET_MSDU_LIFETIME);
12935 + priv->rts_threshold = DEFAULT_RTS_THRESHOLD;
12937 + /* use standard default values for retry limits */
12938 + priv->short_retry = 7; /* max. retries for (short) non-RTS packets */
12939 + priv->long_retry = 4; /* max. retries for long (RTS) packets */
12940 + SET_BIT(priv->set_mask, GETSET_RETRY);
12942 + priv->fallback_threshold = 3;
12943 + priv->stepup_threshold = 10;
12944 + priv->rate_bcast = RATE111_1;
12945 + priv->rate_bcast100 = RATE100_1;
12946 + priv->rate_basic = RATE111_1 | RATE111_2;
12947 + priv->rate_auto = 1;
12948 + if (IS_ACX111(priv)) {
12949 + priv->rate_oper = RATE111_ALL;
12951 + priv->rate_oper = RATE111_ACX100_COMPAT;
12954 + /* configure card to do rate fallback when in auto rate mode. */
12955 + SET_BIT(priv->set_mask, SET_RATE_FALLBACK);
12957 + /* Supported Rates element - the rates here are given in units of
12958 + * 500 kbit/s, plus 0x80 added. See 802.11-1999.pdf item 7.3.2.2 */
12959 + acx_l_update_ratevector(priv);
12961 + priv->capab_short = 0;
12962 + priv->capab_pbcc = 1;
12963 + priv->capab_agility = 0;
12965 + SET_BIT(priv->set_mask, SET_RXCONFIG);
12967 + /* set some more defaults */
12968 + if (IS_ACX111(priv)) {
12969 + /* 30mW (15dBm) is default, at least in my acx111 card: */
12970 + priv->tx_level_dbm = 15;
12972 + /* don't use max. level, since it might be dangerous
12973 + * (e.g. WRT54G people experience
12974 + * excessive Tx power damage!) */
12975 + priv->tx_level_dbm = 18;
12977 + /* priv->tx_level_auto = 1; */
12978 + SET_BIT(priv->set_mask, GETSET_TXPOWER);
12980 + if (IS_ACX111(priv)) {
12981 + /* start with sensitivity level 1 out of 3: */
12982 + priv->sensitivity = 1;
12985 + /* better re-init the antenna value we got above */
12986 + SET_BIT(priv->set_mask, GETSET_ANTENNA);
12988 + priv->ps_wakeup_cfg = 0;
12989 + priv->ps_listen_interval = 0;
12990 + priv->ps_options = 0;
12991 + priv->ps_hangover_period = 0;
12992 + priv->ps_enhanced_transition_time = 0;
12993 +#ifdef POWER_SAVE_80211
12994 + SET_BIT(priv->set_mask, GETSET_POWER_80211);
12997 + MAC_BCAST(priv->ap);
12999 + acx_unlock(priv, flags);
13000 + acx_lock_unhold(); // hold time 844814 CPU ticks @2GHz
13002 + acx_s_initialize_rx_config(priv);
13009 +/***********************************************************************
13010 +** FIXME: this should be solved in a general way for all radio types
13011 +** by decoding the radio firmware module,
13012 +** since it probably has some standard structure describing how to
13013 +** set the power level of the radio module which it controls.
13014 +** Or maybe not, since the radio module probably has a function interface
13015 +** instead which then manages Tx level programming :-\
13018 +acx111_s_set_tx_level(wlandevice_t *priv, u8 level_dbm)
13020 + struct acx111_ie_tx_level tx_level;
13022 + /* my acx111 card has two power levels in its configoptions (== EEPROM):
13023 + * 1 (30mW) [15dBm]
13024 + * 2 (10mW) [10dBm]
13025 + * For now, just assume all other acx111 cards have the same.
13026 + * Ideally we would query it here, but we first need a
13027 + * standard way to query individual configoptions easily. */
13028 + if (level_dbm <= 12) {
13029 + tx_level.level = 2; /* 10 dBm */
13030 + priv->tx_level_dbm = 10;
13032 + tx_level.level = 1; /* 15 dBm */
13033 + priv->tx_level_dbm = 15;
13035 + if (level_dbm != priv->tx_level_dbm)
13036 + acxlog(L_INIT, "acx111 firmware has specific "
13037 + "power levels only: adjusted %d dBm to %d dBm!\n",
13038 + level_dbm, priv->tx_level_dbm);
13040 + return acx_s_configure(priv, &tx_level, ACX1xx_IE_DOT11_TX_POWER_LEVEL);
13044 +acx_s_set_tx_level(wlandevice_t *priv, u8 level_dbm)
13046 + if (IS_ACX111(priv)) {
13047 + return acx111_s_set_tx_level(priv, level_dbm);
13049 + if (IS_PCI(priv)) {
13050 + return acx100_s_set_tx_level(priv, level_dbm);
13056 +/***********************************************************************
13059 +/* Returns the current tx level (ACX111) */
13061 +acx111_s_get_tx_level(wlandevice_t *priv)
13063 + struct acx111_ie_tx_level tx_level;
13065 + tx_level.level = 0;
13066 + acx_s_interrogate(priv, &tx_level, ACX1xx_IE_DOT11_TX_POWER_LEVEL);
13067 + return tx_level.level;
13072 +/***********************************************************************
13076 +acx_s_init_mac(netdevice_t *dev)
13078 + wlandevice_t *priv = netdev_priv(dev);
13079 + int result = NOT_OK;
13083 + if (IS_PCI(priv)) {
13084 + priv->memblocksize = 256; /* 256 is default */
13085 + acx_init_mboxes(priv);
13086 + /* try to load radio for both ACX100 and ACX111, since both
13087 + * chips have at least some firmware versions making use of an
13088 + * external radio module */
13089 + acx_s_upload_radio(priv);
13091 + priv->memblocksize = 128;
13094 + if (IS_ACX111(priv)) {
13095 + /* for ACX111, the order is different from ACX100
13096 + 1. init packet templates
13097 + 2. create station context and create dma regions
13098 + 3. init wep default keys
13100 + if (OK != acx111_s_init_packet_templates(priv))
13103 + if (OK != acx111_s_create_dma_regions(priv)) {
13104 + printk("%s: acx111_create_dma_regions FAILED\n",
13109 + /* don't decrypt WEP in firmware */
13110 + if (OK != acx111_s_feature_on(priv, 0, FEATURE2_SNIFFER))
13114 + if (OK != acx100_s_init_wep(priv))
13116 + acxlog(L_DEBUG, "between init_wep and init_packet_templates\n");
13117 + if (OK != acx100_s_init_packet_templates(priv))
13120 + if (OK != acx100_s_create_dma_regions(priv)) {
13121 + printk("%s: acx100_create_dma_regions FAILED\n",
13127 + MAC_COPY(dev->dev_addr, priv->dev_addr);
13131 + FN_EXIT1(result);
13136 +/*----------------------------------------------------------------
13138 +* Called from IRQ context only
13139 +*----------------------------------------------------------------*/
13141 +acx_l_rxmonitor(wlandevice_t *priv, const rxbuffer_t *rxbuf)
13143 + wlansniffrm_t *msg;
13144 + struct sk_buff *skb;
13146 + unsigned int skb_len;
13147 + int payload_offset;
13151 + /* we are in big luck: the acx100 doesn't modify any of the fields */
13152 + /* in the 802.11 frame. just pass this packet into the PF_PACKET */
13153 + /* subsystem. yeah. */
13154 + payload_offset = ((u8*)acx_get_wlan_hdr(priv, rxbuf) - (u8*)rxbuf);
13155 + skb_len = RXBUF_BYTES_USED(rxbuf) - payload_offset;
13157 + /* sanity check */
13158 + if (skb_len > WLAN_A4FR_MAXLEN_WEP) {
13159 + printk("%s: monitor mode panic: oversized frame!\n",
13160 + priv->netdev->name);
13164 + if (priv->netdev->type == ARPHRD_IEEE80211_PRISM)
13165 + skb_len += sizeof(*msg);
13167 + /* allocate skb */
13168 + skb = dev_alloc_skb(skb_len);
13170 + printk("%s: no memory for skb (%u bytes)\n",
13171 + priv->netdev->name, skb_len);
13175 + skb_put(skb, skb_len);
13177 + /* when in raw 802.11 mode, just copy frame as-is */
13178 + if (priv->netdev->type == ARPHRD_IEEE80211)
13179 + datap = skb->data;
13180 + else { /* otherwise, emulate prism header */
13181 + msg = (wlansniffrm_t*)skb->data;
13184 + msg->msgcode = WLANSNIFFFRM;
13185 + msg->msglen = sizeof(*msg);
13186 + strncpy(msg->devname, priv->netdev->name, sizeof(msg->devname)-1);
13187 + msg->devname[sizeof(msg->devname)-1] = '\0';
13189 + msg->hosttime.did = WLANSNIFFFRM_hosttime;
13190 + msg->hosttime.status = WLANITEM_STATUS_data_ok;
13191 + msg->hosttime.len = 4;
13192 + msg->hosttime.data = jiffies;
13194 + msg->mactime.did = WLANSNIFFFRM_mactime;
13195 + msg->mactime.status = WLANITEM_STATUS_data_ok;
13196 + msg->mactime.len = 4;
13197 + msg->mactime.data = rxbuf->time;
13199 + msg->channel.did = WLANSNIFFFRM_channel;
13200 + msg->channel.status = WLANITEM_STATUS_data_ok;
13201 + msg->channel.len = 4;
13202 + msg->channel.data = priv->channel;
13204 + msg->rssi.did = WLANSNIFFFRM_rssi;
13205 + msg->rssi.status = WLANITEM_STATUS_no_value;
13206 + msg->rssi.len = 4;
13207 + msg->rssi.data = 0;
13209 + msg->sq.did = WLANSNIFFFRM_sq;
13210 + msg->sq.status = WLANITEM_STATUS_no_value;
13212 + msg->sq.data = 0;
13214 + msg->signal.did = WLANSNIFFFRM_signal;
13215 + msg->signal.status = WLANITEM_STATUS_data_ok;
13216 + msg->signal.len = 4;
13217 + msg->signal.data = rxbuf->phy_snr;
13219 + msg->noise.did = WLANSNIFFFRM_noise;
13220 + msg->noise.status = WLANITEM_STATUS_data_ok;
13221 + msg->noise.len = 4;
13222 + msg->noise.data = rxbuf->phy_level;
13224 + msg->rate.did = WLANSNIFFFRM_rate;
13225 + msg->rate.status = WLANITEM_STATUS_data_ok;
13226 + msg->rate.len = 4;
13227 + msg->rate.data = rxbuf->phy_plcp_signal / 5;
13229 + msg->istx.did = WLANSNIFFFRM_istx;
13230 + msg->istx.status = WLANITEM_STATUS_data_ok;
13231 + msg->istx.len = 4;
13232 + msg->istx.data = 0; /* tx=0: it's not a tx packet */
13234 + skb_len -= sizeof(*msg);
13236 + msg->frmlen.did = WLANSNIFFFRM_signal;
13237 + msg->frmlen.status = WLANITEM_STATUS_data_ok;
13238 + msg->frmlen.len = 4;
13239 + msg->frmlen.data = skb_len;
13242 + memcpy(datap, ((unsigned char*)rxbuf)+payload_offset, skb_len);
13244 + skb->dev = priv->netdev;
13245 + skb->dev->last_rx = jiffies;
13247 + skb->mac.raw = skb->data;
13248 + skb->ip_summed = CHECKSUM_NONE;
13249 + skb->pkt_type = PACKET_OTHERHOST;
13250 + skb->protocol = htons(ETH_P_80211_RAW);
13253 + priv->stats.rx_packets++;
13254 + priv->stats.rx_bytes += skb->len;
13260 +/***********************************************************************
13261 +** acx_l_rx_ieee802_11_frame
13263 +** Called from IRQ context only
13266 +/* All these contortions are for saner dup logging
13268 +** We want: (a) to know about excessive dups
13269 +** (b) to not spam kernel log about occasional dups
13271 +** 1/64 threshold was chosen by running "ping -A"
13272 +** It gave "rx: 59 DUPs in 2878 packets" only with 4 parallel
13273 +** "ping -A" streams running. */
13275 +acx_l_handle_dup(wlandevice_t *priv, u16 seq)
13277 + if (priv->dup_count) {
13278 + priv->nondup_count++;
13279 + if (time_after(jiffies, priv->dup_msg_expiry)) {
13280 + /* Log only if more than 1 dup in 64 packets */
13281 + if (priv->nondup_count/64 < priv->dup_count) {
13282 + printk(KERN_INFO "%s: rx: %d DUPs in "
13283 + "%d packets received in 10 secs\n",
13284 + priv->netdev->name,
13286 + priv->nondup_count);
13288 + priv->dup_count = 0;
13289 + priv->nondup_count = 0;
13292 + if (unlikely(seq == priv->last_seq_ctrl)) {
13293 + if (!priv->dup_count++)
13294 + priv->dup_msg_expiry = jiffies + 10*HZ;
13295 + priv->stats.rx_errors++;
13296 + return 1; /* a dup */
13298 + priv->last_seq_ctrl = seq;
13303 +acx_l_rx_ieee802_11_frame(wlandevice_t *priv, rxbuffer_t *rxbuf)
13305 + unsigned int ftype, fstype;
13306 + const wlan_hdr_t *hdr;
13307 + int result = NOT_OK;
13311 + hdr = acx_get_wlan_hdr(priv, rxbuf);
13313 + /* see IEEE 802.11-1999.pdf chapter 7 "MAC frame formats" */
13314 + if ((hdr->fc & WF_FC_PVERi) != 0) {
13315 + printk_ratelimited(KERN_INFO "rx: unsupported 802.11 protocol\n");
13319 + ftype = hdr->fc & WF_FC_FTYPEi;
13320 + fstype = hdr->fc & WF_FC_FSTYPEi;
13323 + /* check data frames first, for speed */
13324 + case WF_FTYPE_DATAi:
13325 + switch (fstype) {
13326 + case WF_FSTYPE_DATAONLYi:
13327 + if (acx_l_handle_dup(priv, hdr->seq))
13328 + break; /* a dup, simply discard it */
13331 + if (WF_FC_FROMTODSi == (hdr->fc & WF_FC_FROMTODSi)) {
13332 + result = acx_l_process_data_frame_wds(priv, rxbuf);
13337 + switch (priv->mode) {
13338 + case ACX_MODE_3_AP:
13339 + result = acx_l_process_data_frame_master(priv, rxbuf);
13341 + case ACX_MODE_0_ADHOC:
13342 + case ACX_MODE_2_STA:
13343 + result = acx_l_process_data_frame_client(priv, rxbuf);
13346 + case WF_FSTYPE_DATA_CFACKi:
13347 + case WF_FSTYPE_DATA_CFPOLLi:
13348 + case WF_FSTYPE_DATA_CFACK_CFPOLLi:
13349 + case WF_FSTYPE_CFPOLLi:
13350 + case WF_FSTYPE_CFACK_CFPOLLi:
13352 + acx_process_class_frame(priv, rxbuf, 3); */
13354 + case WF_FSTYPE_NULLi:
13355 + /* acx_l_process_NULL_frame(priv, rxbuf, 3); */
13357 + /* FIXME: same here, see above */
13358 + case WF_FSTYPE_CFACKi:
13363 + case WF_FTYPE_MGMTi:
13364 + result = acx_l_process_mgmt_frame(priv, rxbuf);
13366 + case WF_FTYPE_CTLi:
13367 + if (fstype == WF_FSTYPE_PSPOLLi)
13369 + /* this call is irrelevant, since
13370 + * acx_process_class_frame is a stub, so return
13371 + * immediately instead.
13372 + * return acx_process_class_frame(priv, rxbuf, 3); */
13378 + FN_EXIT1(result);
13383 +/***********************************************************************
13384 +** acx_l_process_rxbuf
13386 +** NB: used by USB code also
13389 +acx_l_process_rxbuf(wlandevice_t *priv, rxbuffer_t *rxbuf)
13391 + struct wlan_hdr *hdr;
13392 + unsigned int buf_len;
13393 + unsigned int qual;
13396 + hdr = acx_get_wlan_hdr(priv, rxbuf);
13397 + /* length of frame from control field to last byte of FCS */
13398 + buf_len = RXBUF_BYTES_RCVD(rxbuf);
13399 + fc = le16_to_cpu(hdr->fc);
13401 + if ( ((WF_FC_FSTYPE & fc) != WF_FSTYPE_BEACON)
13402 + || (acx_debug & L_XFER_BEACON)
13404 + acxlog(L_XFER|L_DATA, "rx: %s "
13405 + "time %u len %u signal %u SNR %u macstat %02X "
13406 + "phystat %02X phyrate %u status %u\n",
13407 + acx_get_packet_type_string(fc),
13408 + le32_to_cpu(rxbuf->time),
13410 + acx_signal_to_winlevel(rxbuf->phy_level),
13411 + acx_signal_to_winlevel(rxbuf->phy_snr),
13412 + rxbuf->mac_status,
13413 + rxbuf->phy_stat_baseband,
13414 + rxbuf->phy_plcp_signal,
13418 + if (unlikely(acx_debug & L_DATA)) {
13419 + printk("rx: 802.11 buf[%u]: ", buf_len);
13420 + acx_dump_bytes(hdr, buf_len);
13423 + /* FIXME: should check for Rx errors (rxbuf->mac_status?
13424 + * discard broken packets - but NOT for monitor!)
13425 + * and update Rx packet statistics here */
13427 + if (unlikely(priv->mode == ACX_MODE_MONITOR)) {
13428 + acx_l_rxmonitor(priv, rxbuf);
13429 + } else if (likely(buf_len >= WLAN_HDR_A3_LEN)) {
13430 + acx_l_rx_ieee802_11_frame(priv, rxbuf);
13432 + acxlog(L_DEBUG|L_XFER|L_DATA,
13433 + "rx: NOT receiving packet (%s): "
13434 + "size too small (%u)\n",
13435 + acx_get_packet_type_string(fc),
13439 + /* Now check Rx quality level, AFTER processing packet.
13440 + * I tried to figure out how to map these levels to dBm
13441 + * values, but for the life of me I really didn't
13442 + * manage to get it. Either these values are not meant to
13443 + * be expressed in dBm, or it's some pretty complicated
13444 + * calculation. */
13446 +#ifdef FROM_SCAN_SOURCE_ONLY
13447 + /* only consider packets originating from the MAC
13448 + * address of the device that's managing our BSSID.
13449 + * Disable it for now, since it removes information (levels
13450 + * from different peers) and slows the Rx path. */
13451 + if (priv->ap_client
13452 + && mac_is_equal(hdr->a2, priv->ap_client->address)) {
13454 + priv->wstats.qual.level = acx_signal_to_winlevel(rxbuf->phy_level);
13455 + priv->wstats.qual.noise = acx_signal_to_winlevel(rxbuf->phy_snr);
13456 +#ifndef OLD_QUALITY
13457 + qual = acx_signal_determine_quality(priv->wstats.qual.level,
13458 + priv->wstats.qual.noise);
13460 + qual = (priv->wstats.qual.noise <= 100) ?
13461 + 100 - priv->wstats.qual.noise : 0;
13463 + priv->wstats.qual.qual = qual;
13464 + priv->wstats.qual.updated = 7; /* all 3 indicators updated */
13465 +#ifdef FROM_SCAN_SOURCE_ONLY
13471 +/***********************************************************************
13472 +** acx_i_start_xmit
13474 +** Called by network core. Can be called outside of process context.
13477 +acx_i_start_xmit(struct sk_buff *skb, netdevice_t *dev)
13479 + wlandevice_t *priv = netdev_priv(dev);
13482 + unsigned long flags;
13483 + int txresult = NOT_OK;
13488 + if (unlikely(!skb)) {
13489 + /* indicate success */
13491 + goto end_no_unlock;
13493 + if (unlikely(!priv)) {
13494 + goto end_no_unlock;
13497 + acx_lock(priv, flags);
13499 + if (unlikely(!(priv->dev_state_mask & ACX_STATE_IFACE_UP))) {
13502 + if (unlikely(priv->mode == ACX_MODE_OFF)) {
13505 + if (unlikely(acx_queue_stopped(dev))) {
13506 + acxlog(L_DEBUG, "%s: called when queue stopped\n", __func__);
13509 + if (unlikely(ACX_STATUS_4_ASSOCIATED != priv->status)) {
13510 + acxlog(L_XFER, "trying to xmit, but not associated yet: "
13511 + "aborting...\n");
13512 + /* silently drop the packet, since we're not connected yet */
13514 + /* ...but indicate an error nevertheless */
13515 + priv->stats.tx_errors++;
13519 + tx = acx_l_alloc_tx(priv);
13520 + if (unlikely(!tx)) {
13521 + printk("%s: start_xmit: txdesc ring is full, dropping tx\n",
13523 + txresult = NOT_OK;
13527 + txbuf = acx_l_get_txbuf(priv, tx);
13529 + /* Card was removed */
13530 + txresult = NOT_OK;
13533 + len = acx_l_ether_to_txbuf(priv, txbuf, skb);
13535 + /* Error in packet conversion */
13536 + txresult = NOT_OK;
13539 + acx_l_tx_data(priv, tx, len);
13540 + dev->trans_start = jiffies;
13543 + priv->stats.tx_packets++;
13544 + priv->stats.tx_bytes += skb->len;
13547 + acx_unlock(priv, flags);
13550 + if ((txresult == OK) && skb)
13551 + dev_kfree_skb_any(skb);
13553 + FN_EXIT1(txresult);
13558 +/***********************************************************************
13559 +** acx_l_update_ratevector
13561 +** Updates priv->rate_supported[_len] according to rate_{basic,oper}
13564 +bitpos2ratebyte[] = {
13567 + DOT11RATEBYTE_5_5,
13568 + DOT11RATEBYTE_6_G,
13569 + DOT11RATEBYTE_9_G,
13570 + DOT11RATEBYTE_11,
13571 + DOT11RATEBYTE_12_G,
13572 + DOT11RATEBYTE_18_G,
13573 + DOT11RATEBYTE_22,
13574 + DOT11RATEBYTE_24_G,
13575 + DOT11RATEBYTE_36_G,
13576 + DOT11RATEBYTE_48_G,
13577 + DOT11RATEBYTE_54_G,
13581 +acx_l_update_ratevector(wlandevice_t *priv)
13583 + u16 bcfg = priv->rate_basic;
13584 + u16 ocfg = priv->rate_oper;
13585 + u8 *supp = priv->rate_supported;
13586 + const u8 *dot11 = bitpos2ratebyte;
13602 + priv->rate_supported_len = supp - priv->rate_supported;
13603 + if (acx_debug & L_ASSOC) {
13604 + printk("new ratevector: ");
13605 + acx_dump_bytes(priv->rate_supported, priv->rate_supported_len);
13611 +/*----------------------------------------------------------------
13612 +* acx_l_sta_list_init
13613 +*----------------------------------------------------------------*/
13615 +acx_l_sta_list_init(wlandevice_t *priv)
13618 + memset(priv->sta_hash_tab, 0, sizeof(priv->sta_hash_tab));
13619 + memset(priv->sta_list, 0, sizeof(priv->sta_list));
13624 +/*----------------------------------------------------------------
13625 +* acx_l_sta_list_get_from_hash
13626 +*----------------------------------------------------------------*/
13627 +static inline client_t*
13628 +acx_l_sta_list_get_from_hash(wlandevice_t *priv, const u8 *address)
13630 + return priv->sta_hash_tab[address[5] % VEC_SIZE(priv->sta_hash_tab)];
13634 +/*----------------------------------------------------------------
13635 +* acx_l_sta_list_get
13636 +*----------------------------------------------------------------*/
13638 +acx_l_sta_list_get(wlandevice_t *priv, const u8 *address)
13640 + client_t *client;
13642 + client = acx_l_sta_list_get_from_hash(priv, address);
13644 + if (mac_is_equal(address, client->address)) {
13645 + client->mtime = jiffies;
13648 + client = client->next;
13655 +/*----------------------------------------------------------------
13656 +* acx_l_sta_list_del
13657 +*----------------------------------------------------------------*/
13659 +acx_l_sta_list_del(wlandevice_t *priv, client_t *victim)
13661 + client_t *client, *next;
13663 + client = acx_l_sta_list_get_from_hash(priv, victim->address);
13665 + /* tricky. next = client on first iteration only,
13666 + ** on all other iters next = client->next */
13668 + if (next == victim) {
13669 + client->next = victim->next;
13671 + memset(victim, 0, sizeof(*victim));
13675 + next = client->next;
13680 +/*----------------------------------------------------------------
13681 +* acx_l_sta_list_alloc
13683 +* Never fails - will evict oldest client if needed
13684 +*----------------------------------------------------------------*/
13686 +acx_l_sta_list_alloc(wlandevice_t *priv)
13689 + unsigned long age, oldest_age;
13690 + client_t *client, *oldest;
13694 + oldest = &priv->sta_list[0];
13696 + for (i = 0; i < VEC_SIZE(priv->sta_list); i++) {
13697 + client = &priv->sta_list[i];
13699 + if (!client->used) {
13702 + age = jiffies - client->mtime;
13703 + if (oldest_age < age) {
13704 + oldest_age = age;
13709 + acx_l_sta_list_del(priv, oldest);
13712 + memset(client, 0, sizeof(*client));
13718 +/*----------------------------------------------------------------
13719 +* acx_l_sta_list_add
13721 +* Never fails - will evict oldest client if needed
13722 +*----------------------------------------------------------------*/
13723 +/* In case we will reimplement it differently... */
13724 +#define STA_LIST_ADD_CAN_FAIL 0
13727 +acx_l_sta_list_add(wlandevice_t *priv, const u8 *address)
13729 + client_t *client;
13734 + client = acx_l_sta_list_alloc(priv);
13736 + client->mtime = jiffies;
13737 + MAC_COPY(client->address, address);
13738 + client->used = CLIENT_EXIST_1;
13739 + client->auth_alg = WLAN_AUTH_ALG_SHAREDKEY;
13740 + client->auth_step = 1;
13741 + /* give some tentative peer rate values
13742 + ** (needed because peer may do auth without probing us first,
13743 + ** thus we'll have no idea of peer's ratevector yet).
13744 + ** Will be overwritten by scanning or assoc code */
13745 + client->rate_cap = priv->rate_basic;
13746 + client->rate_cfg = priv->rate_basic;
13747 + client->rate_cur = 1 << lowest_bit(priv->rate_basic);
13749 + index = address[5] % VEC_SIZE(priv->sta_hash_tab);
13750 + client->next = priv->sta_hash_tab[index];
13751 + priv->sta_hash_tab[index] = client;
13753 + acxlog_mac(L_ASSOC, "sta_list_add: sta=", address, "\n");
13760 +/*----------------------------------------------------------------
13761 +* acx_l_sta_list_get_or_add
13763 +* Never fails - will evict oldest client if needed
13764 +*----------------------------------------------------------------*/
13766 +acx_l_sta_list_get_or_add(wlandevice_t *priv, const u8 *address)
13768 + client_t *client = acx_l_sta_list_get(priv, address);
13770 + client = acx_l_sta_list_add(priv, address);
13775 +/***********************************************************************
13778 +** This function is called in many atomic regions, must not sleep
13780 +** This function does not need locking UNLESS you call it
13781 +** as acx_set_status(ACX_STATUS_4_ASSOCIATED), bacause this can
13782 +** wake queue. This can race with stop_queue elsewhere.
13783 +** See acx_stop_queue comment. */
13785 +acx_set_status(wlandevice_t *priv, u16 new_status)
13787 +#define QUEUE_OPEN_AFTER_ASSOC 1 /* this really seems to be needed now */
13788 + u16 old_status = priv->status;
13792 + acxlog(L_ASSOC, "%s(%d):%s\n",
13793 + __func__, new_status, acx_get_status_name(new_status));
13795 +#if WIRELESS_EXT > 13 /* wireless_send_event() and SIOCGIWSCAN */
13796 + /* wireless_send_event never sleeps */
13797 + if (ACX_STATUS_4_ASSOCIATED == new_status) {
13798 + union iwreq_data wrqu;
13800 + wrqu.data.length = 0;
13801 + wrqu.data.flags = 0;
13802 + wireless_send_event(priv->netdev, SIOCGIWSCAN, &wrqu, NULL);
13804 + wrqu.data.length = 0;
13805 + wrqu.data.flags = 0;
13806 + MAC_COPY(wrqu.ap_addr.sa_data, priv->bssid);
13807 + wrqu.ap_addr.sa_family = ARPHRD_ETHER;
13808 + wireless_send_event(priv->netdev, SIOCGIWAP, &wrqu, NULL);
13810 + union iwreq_data wrqu;
13812 + /* send event with empty BSSID to indicate we're not associated */
13813 + MAC_ZERO(wrqu.ap_addr.sa_data);
13814 + wrqu.ap_addr.sa_family = ARPHRD_ETHER;
13815 + wireless_send_event(priv->netdev, SIOCGIWAP, &wrqu, NULL);
13819 + priv->status = new_status;
13821 + switch (new_status) {
13822 + case ACX_STATUS_1_SCANNING:
13823 + priv->scan_retries = 0;
13824 + /* 1.0 s initial scan time */
13825 + acx_set_timer(priv, 1000000);
13827 + case ACX_STATUS_2_WAIT_AUTH:
13828 + case ACX_STATUS_3_AUTHENTICATED:
13829 + priv->auth_or_assoc_retries = 0;
13830 + acx_set_timer(priv, 1500000); /* 1.5 s */
13834 +#if QUEUE_OPEN_AFTER_ASSOC
13835 + if (new_status == ACX_STATUS_4_ASSOCIATED) {
13836 + if (old_status < ACX_STATUS_4_ASSOCIATED) {
13837 + /* ah, we're newly associated now,
13838 + * so let's indicate carrier */
13839 + acx_carrier_on(priv->netdev, "after association");
13840 + acx_wake_queue(priv->netdev, "after association");
13843 + /* not associated any more, so let's kill carrier */
13844 + if (old_status >= ACX_STATUS_4_ASSOCIATED) {
13845 + acx_carrier_off(priv->netdev, "after losing association");
13846 + acx_stop_queue(priv->netdev, "after losing association");
13854 +/*------------------------------------------------------------------------------
13857 + * Fires up periodically. Used to kick scan/auth/assoc if something goes wrong
13858 + *----------------------------------------------------------------------------*/
13860 +acx_i_timer(unsigned long address)
13862 + unsigned long flags;
13863 + wlandevice_t *priv = (wlandevice_t *)address;
13867 + acx_lock(priv, flags);
13869 + acxlog(L_DEBUG|L_ASSOC, "%s: priv->status=%d (%s)\n",
13870 + __func__, priv->status, acx_get_status_name(priv->status));
13872 + switch (priv->status) {
13873 + case ACX_STATUS_1_SCANNING:
13874 + /* was set to 0 by set_status() */
13875 + if (++priv->scan_retries < 7) {
13876 + acx_set_timer(priv, 1000000);
13877 + /* used to interrogate for scan status.
13878 + ** We rely on SCAN_COMPLETE IRQ instead */
13879 + acxlog(L_ASSOC, "continuing scan (%d sec)\n",
13880 + priv->scan_retries);
13882 + acxlog(L_ASSOC, "stopping scan\n");
13883 + /* send stop_scan cmd when we leave the interrupt context,
13884 + * and make a decision what to do next (COMPLETE_SCAN) */
13885 + acx_schedule_after_interrupt_task(priv,
13886 + ACX_AFTER_IRQ_CMD_STOP_SCAN + ACX_AFTER_IRQ_COMPLETE_SCAN);
13889 + case ACX_STATUS_2_WAIT_AUTH:
13890 + /* was set to 0 by set_status() */
13891 + if (++priv->auth_or_assoc_retries < 10) {
13892 + acxlog(L_ASSOC, "resend authen1 request (attempt %d)\n",
13893 + priv->auth_or_assoc_retries + 1);
13894 + acx_l_transmit_authen1(priv);
13896 + /* time exceeded: fall back to scanning mode */
13898 + "authen1 request reply timeout, giving up\n");
13899 + /* we are a STA, need to find AP anyhow */
13900 + acx_set_status(priv, ACX_STATUS_1_SCANNING);
13901 + acx_schedule_after_interrupt_task(priv, ACX_AFTER_IRQ_RESTART_SCAN);
13903 + /* used to be 1500000, but some other driver uses 2.5s */
13904 + acx_set_timer(priv, 2500000);
13906 + case ACX_STATUS_3_AUTHENTICATED:
13907 + /* was set to 0 by set_status() */
13908 + if (++priv->auth_or_assoc_retries < 10) {
13909 + acxlog(L_ASSOC, "resend assoc request (attempt %d)\n",
13910 + priv->auth_or_assoc_retries + 1);
13911 + acx_l_transmit_assoc_req(priv);
13913 + /* time exceeded: give up */
13915 + "association request reply timeout, giving up\n");
13916 + /* we are a STA, need to find AP anyhow */
13917 + acx_set_status(priv, ACX_STATUS_1_SCANNING);
13918 + acx_schedule_after_interrupt_task(priv, ACX_AFTER_IRQ_RESTART_SCAN);
13920 + acx_set_timer(priv, 2500000); /* see above */
13922 + case ACX_STATUS_4_ASSOCIATED:
13927 + acx_unlock(priv, flags);
13933 +/*------------------------------------------------------------------------------
13936 + * Sets the 802.11 state management timer's timeout.
13937 + *----------------------------------------------------------------------------*/
13939 +acx_set_timer(wlandevice_t *priv, int timeout_us)
13943 + acxlog(L_DEBUG|L_IRQ, "%s(%u ms)\n", __func__, timeout_us/1000);
13944 + if (!(priv->dev_state_mask & ACX_STATE_IFACE_UP)) {
13945 + printk("attempt to set the timer "
13946 + "when the card interface is not up!\n");
13950 + /* first check if the timer was already initialized, THEN modify it */
13951 + if (priv->mgmt_timer.function) {
13952 + mod_timer(&priv->mgmt_timer,
13953 + jiffies + (timeout_us * HZ / 1000000));
13960 +/*----------------------------------------------------------------
13961 +* acx_l_transmit_assocresp
13963 +* We are an AP here
13964 +*----------------------------------------------------------------*/
13966 +dot11ratebyte[] = {
13969 + DOT11RATEBYTE_5_5,
13970 + DOT11RATEBYTE_6_G,
13971 + DOT11RATEBYTE_9_G,
13972 + DOT11RATEBYTE_11,
13973 + DOT11RATEBYTE_12_G,
13974 + DOT11RATEBYTE_18_G,
13975 + DOT11RATEBYTE_22,
13976 + DOT11RATEBYTE_24_G,
13977 + DOT11RATEBYTE_36_G,
13978 + DOT11RATEBYTE_48_G,
13979 + DOT11RATEBYTE_54_G,
13983 +find_pos(const u8 *p, int size, u8 v)
13986 + for (i = 0; i < size; i++)
13989 + /* printk a message about strange byte? */
13994 +add_bits_to_ratemasks(u8* ratevec, int len, u16* brate, u16* orate)
13997 + int n = 1 << find_pos(dot11ratebyte,
13998 + sizeof(dot11ratebyte), *ratevec & 0x7f);
13999 + if (*ratevec & 0x80)
14007 +acx_l_transmit_assocresp(wlandevice_t *priv, const wlan_fr_assocreq_t *req)
14010 + struct wlan_hdr_mgmt *head;
14011 + struct assocresp_frame_body *body;
14014 + /* const u8 *sa; */
14020 + /* sa = req->hdr->a1; */
14021 + da = req->hdr->a2;
14022 + bssid = req->hdr->a3;
14024 + clt = acx_l_sta_list_get(priv, da);
14028 + /* Assoc without auth is a big no-no */
14029 + /* Let's be liberal: if already assoc'ed STA sends assoc req again,
14030 + ** we won't be rude */
14031 + if (clt->used != CLIENT_AUTHENTICATED_2
14032 + && clt->used != CLIENT_ASSOCIATED_3) {
14033 + acx_l_transmit_deauthen(priv, da, WLAN_MGMT_REASON_CLASS2_NONAUTH);
14037 + clt->used = CLIENT_ASSOCIATED_3;
14039 + if (clt->aid == 0) {
14040 + clt->aid = ++priv->aid;
14042 + clt->cap_info = ieee2host16(*(req->cap_info));
14043 + /* We cheat here a bit. We don't really care which rates are flagged
14044 + ** as basic by the client, so we stuff them in single ratemask */
14045 + clt->rate_cap = 0;
14046 + if (req->supp_rates)
14047 + add_bits_to_ratemasks(req->supp_rates->rates,
14048 + req->supp_rates->len, &clt->rate_cap, &clt->rate_cap);
14049 + if (req->ext_rates)
14050 + add_bits_to_ratemasks(req->ext_rates->rates,
14051 + req->ext_rates->len, &clt->rate_cap, &clt->rate_cap);
14052 + /* We can check that client supports all basic rates,
14053 + ** and deny assoc if not. But let's be liberal, right? ;) */
14054 + clt->rate_cfg = clt->rate_cap & priv->rate_oper;
14055 + if (!clt->rate_cfg) clt->rate_cfg = 1 << lowest_bit(priv->rate_oper);
14056 + clt->rate_cur = 1 << lowest_bit(clt->rate_cfg);
14057 + clt->fallback_count = clt->stepup_count = 0;
14058 + clt->ignore_count = 16;
14060 + tx = acx_l_alloc_tx(priv);
14063 + head = acx_l_get_txbuf(priv, tx);
14066 + body = (void*)(head + 1);
14068 + head->fc = WF_FSTYPE_ASSOCRESPi;
14069 + head->dur = req->hdr->dur;
14070 + MAC_COPY(head->da, da);
14071 + /* MAC_COPY(head->sa, sa); */
14072 + MAC_COPY(head->sa, priv->dev_addr);
14073 + MAC_COPY(head->bssid, bssid);
14074 + head->seq = req->hdr->seq;
14076 + body->cap_info = host2ieee16(priv->capabilities);
14077 + body->status = host2ieee16(0);
14078 + body->aid = host2ieee16(clt->aid);
14079 + p = wlan_fill_ie_rates((u8*)&body->rates, priv->rate_supported_len,
14080 + priv->rate_supported);
14081 + p = wlan_fill_ie_rates_ext(p, priv->rate_supported_len,
14082 + priv->rate_supported);
14084 + acx_l_tx_data(priv, tx, p - (u8*)head);
14089 + FN_EXIT1(NOT_OK);
14094 +/*----------------------------------------------------------------
14095 +* acx_l_transmit_reassocresp
14097 +You may be wondering, just like me, what a hell is ReAuth.
14098 +In practice it was seen sent by STA when STA feels like losing connection.
14102 +5.4.2.3 Reassociation
14104 +Association is sufficient for no-transition message delivery between
14105 +IEEE 802.11 stations. Additional functionality is needed to support
14106 +BSS-transition mobility. The additional required functionality
14107 +is provided by the reassociation service. Reassociation is a DSS.
14108 +The reassociation service is invoked to 'move' a current association
14109 +from one AP to another. This keeps the DS informed of the current
14110 +mapping between AP and STA as the station moves from BSS to BSS within
14111 +an ESS. Reassociation also enables changing association attributes
14112 +of an established association while the STA remains associated with
14113 +the same AP. Reassociation is always initiated by the mobile STA.
14115 +5.4.3.1 Authentication
14117 +A STA may be authenticated with many other STAs at any given instant.
14119 +5.4.3.1.1 Preauthentication
14121 +Because the authentication process could be time-consuming (depending
14122 +on the authentication protocol in use), the authentication service can
14123 +be invoked independently of the association service. Preauthentication
14124 +is typically done by a STA while it is already associated with an AP
14125 +(with which it previously authenticated). IEEE 802.11 does not require
14126 +that STAs preauthenticate with APs. However, authentication is required
14127 +before an association can be established. If the authentication is left
14128 +until reassociation time, this may impact the speed with which a STA can
14129 +reassociate between APs, limiting BSS-transition mobility performance.
14130 +The use of preauthentication takes the authentication service overhead
14131 +out of the time-critical reassociation process.
14133 +5.7.3 Reassociation
14135 +For a STA to reassociate, the reassociation service causes the following
14138 + Reassociation request
14140 +* Message type: Management
14141 +* Message subtype: Reassociation request
14142 +* Information items:
14143 + - IEEE address of the STA
14144 + - IEEE address of the AP with which the STA will reassociate
14145 + - IEEE address of the AP with which the STA is currently associated
14147 +* Direction of message: From STA to 'new' AP
14149 +The address of the current AP is included for efficiency. The inclusion
14150 +of the current AP address facilitates MAC reassociation to be independent
14151 +of the DS implementation.
14153 + Reassociation response
14154 +* Message type: Management
14155 +* Message subtype: Reassociation response
14156 +* Information items:
14157 + - Result of the requested reassociation. (success/failure)
14158 + - If the reassociation is successful, the response shall include the AID.
14159 +* Direction of message: From AP to STA
14161 +7.2.3.6 Reassociation Request frame format
14163 +The frame body of a management frame of subtype Reassociation Request
14164 +contains the information shown in Table 9.
14166 +Table 9 Reassociation Request frame body
14168 +1 Capability information
14170 +3 Current AP address
14174 +7.2.3.7 Reassociation Response frame format
14176 +The frame body of a management frame of subtype Reassociation Response
14177 +contains the information shown in Table 10.
14179 +Table 10 Reassociation Response frame body
14181 +1 Capability information
14183 +3 Association ID (AID)
14186 +*----------------------------------------------------------------*/
14188 +acx_l_transmit_reassocresp(wlandevice_t *priv, const wlan_fr_reassocreq_t *req)
14191 + struct wlan_hdr_mgmt *head;
14192 + struct reassocresp_frame_body *body;
14195 + /* const u8 *sa; */
14201 + /* sa = req->hdr->a1; */
14202 + da = req->hdr->a2;
14203 + bssid = req->hdr->a3;
14205 + /* Must be already authenticated, so it must be in the list */
14206 + clt = acx_l_sta_list_get(priv, da);
14210 + /* Assoc without auth is a big no-no */
14211 + /* Already assoc'ed STAs sending ReAssoc req are ok per 802.11 */
14212 + if (clt->used != CLIENT_AUTHENTICATED_2
14213 + && clt->used != CLIENT_ASSOCIATED_3) {
14214 + acx_l_transmit_deauthen(priv, da, WLAN_MGMT_REASON_CLASS2_NONAUTH);
14218 + clt->used = CLIENT_ASSOCIATED_3;
14219 + if (clt->aid == 0) {
14220 + clt->aid = ++priv->aid;
14222 + if (req->cap_info)
14223 + clt->cap_info = ieee2host16(*(req->cap_info));
14224 + /* We cheat here a bit. We don't really care which rates are flagged
14225 + ** as basic by the client, so we stuff them in single ratemask */
14226 + clt->rate_cap = 0;
14227 + if (req->supp_rates)
14228 + add_bits_to_ratemasks(req->supp_rates->rates,
14229 + req->supp_rates->len, &clt->rate_cap, &clt->rate_cap);
14230 + if (req->ext_rates)
14231 + add_bits_to_ratemasks(req->ext_rates->rates,
14232 + req->ext_rates->len, &clt->rate_cap, &clt->rate_cap);
14233 + /* We can check that client supports all basic rates,
14234 + ** and deny assoc if not. But let's be liberal, right? ;) */
14235 + clt->rate_cfg = clt->rate_cap & priv->rate_oper;
14236 + if (!clt->rate_cfg) clt->rate_cfg = 1 << lowest_bit(priv->rate_oper);
14237 + clt->rate_cur = 1 << lowest_bit(clt->rate_cfg);
14238 + clt->fallback_count = clt->stepup_count = 0;
14239 + clt->ignore_count = 16;
14241 + tx = acx_l_alloc_tx(priv);
14244 + head = acx_l_get_txbuf(priv, tx);
14247 + body = (void*)(head + 1);
14249 + head->fc = WF_FSTYPE_REASSOCRESPi;
14250 + head->dur = req->hdr->dur;
14251 + MAC_COPY(head->da, da);
14252 + /* MAC_COPY(head->sa, sa); */
14253 + MAC_COPY(head->sa, priv->dev_addr);
14254 + MAC_COPY(head->bssid, bssid);
14255 + head->seq = req->hdr->seq;
14257 + /* IEs: 1. caps */
14258 + body->cap_info = host2ieee16(priv->capabilities);
14259 + /* 2. status code */
14260 + body->status = host2ieee16(0);
14262 + body->aid = host2ieee16(clt->aid);
14263 + /* 4. supp rates */
14264 + p = wlan_fill_ie_rates((u8*)&body->rates, priv->rate_supported_len,
14265 + priv->rate_supported);
14266 + /* 5. ext supp rates */
14267 + p = wlan_fill_ie_rates_ext(p, priv->rate_supported_len,
14268 + priv->rate_supported);
14270 + acx_l_tx_data(priv, tx, p - (u8*)head);
14275 + FN_EXIT1(NOT_OK);
14280 +/*----------------------------------------------------------------
14281 +* acx_l_process_disassoc_from_sta
14282 +*----------------------------------------------------------------*/
14284 +acx_l_process_disassoc_from_sta(wlandevice_t *priv, const wlan_fr_disassoc_t *req)
14291 + ta = req->hdr->a2;
14292 + clt = acx_l_sta_list_get(priv, ta);
14296 + if (clt->used != CLIENT_ASSOCIATED_3
14297 + && clt->used != CLIENT_AUTHENTICATED_2) {
14298 + /* it's disassociating, but it's
14299 + ** not even authenticated! Let it know that */
14300 + acxlog_mac(L_ASSOC|L_XFER, "peer ", ta, "has sent disassoc "
14301 + "req but it is not even auth'ed! sending deauth\n");
14302 + acx_l_transmit_deauthen(priv, ta,
14303 + WLAN_MGMT_REASON_CLASS2_NONAUTH);
14304 + clt->used = CLIENT_EXIST_1;
14306 + /* mark it as auth'ed only */
14307 + clt->used = CLIENT_AUTHENTICATED_2;
14314 +/*----------------------------------------------------------------
14315 +* acx_l_process_deauthen_from_sta
14316 +*----------------------------------------------------------------*/
14318 +acx_l_process_deauth_from_sta(wlandevice_t *priv, const wlan_fr_deauthen_t *req)
14320 + const wlan_hdr_t *hdr;
14321 + client_t *client;
14327 + if (acx_debug & L_ASSOC) {
14328 + acx_print_mac("DEAUTHEN priv->addr=", priv->dev_addr, " ");
14329 + acx_print_mac("a1", hdr->a1, " ");
14330 + acx_print_mac("a2", hdr->a2, " ");
14331 + acx_print_mac("a3", hdr->a3, " ");
14332 + acx_print_mac("priv->bssid", priv->bssid, "\n");
14335 + if (!mac_is_equal(priv->dev_addr, hdr->a1)) {
14339 + acxlog_mac(L_DEBUG, "STA ", hdr->a2, " sent us deauthen packet\n");
14341 + client = acx_l_sta_list_get(priv, hdr->a2);
14345 + client->used = CLIENT_EXIST_1;
14351 +/*----------------------------------------------------------------
14352 +* acx_l_process_disassoc_from_ap
14353 +*----------------------------------------------------------------*/
14355 +acx_l_process_disassoc_from_ap(wlandevice_t *priv, const wlan_fr_disassoc_t *req)
14359 + if (!priv->ap_client) {
14360 + /* Hrm, we aren't assoc'ed yet anyhow... */
14363 + if (mac_is_equal(priv->dev_addr, req->hdr->a1)) {
14364 + acx_l_transmit_deauthen(priv, priv->bssid,
14365 + WLAN_MGMT_REASON_DEAUTH_LEAVING);
14366 + /* Start scan anew */
14367 + SET_BIT(priv->set_mask, GETSET_RESCAN);
14368 + acx_schedule_after_interrupt_task(priv, ACX_AFTER_IRQ_UPDATE_CARD_CFG);
14375 +/*----------------------------------------------------------------
14376 +* acx_l_process_deauth_from_ap
14377 +*----------------------------------------------------------------*/
14379 +acx_l_process_deauth_from_ap(wlandevice_t *priv, const wlan_fr_deauthen_t *req)
14383 + if (!priv->ap_client) {
14384 + /* Hrm, we aren't assoc'ed yet anyhow... */
14387 + /* Chk: is ta is verified to be from our AP? */
14388 + if (mac_is_equal(priv->dev_addr, req->hdr->a1)) {
14389 + acxlog(L_DEBUG, "AP sent us deauth packet\n");
14390 + /* not needed: acx_set_status(priv, ACX_STATUS_1_SCANNING) */
14391 + SET_BIT(priv->set_mask, GETSET_RESCAN);
14392 + acx_schedule_after_interrupt_task(priv, ACX_AFTER_IRQ_UPDATE_CARD_CFG);
14399 +/*------------------------------------------------------------------------------
14402 + * The end of the Rx path. Pulls data from a rxhostdesc into a socket
14403 + * buffer and feeds it to the network stack via netif_rx().
14406 + * rxdesc: the rxhostdesc to pull the data from
14407 + * priv: the acx100 private struct of the interface
14408 + *----------------------------------------------------------------------------*/
14410 +acx_l_rx(wlandevice_t *priv, rxbuffer_t *rxbuf)
14413 + if (likely(priv->dev_state_mask & ACX_STATE_IFACE_UP)) {
14414 + struct sk_buff *skb;
14415 + skb = acx_rxbuf_to_ether(priv, rxbuf);
14416 + if (likely(skb)) {
14418 + priv->netdev->last_rx = jiffies;
14419 + priv->stats.rx_packets++;
14420 + priv->stats.rx_bytes += skb->len;
14427 +/*----------------------------------------------------------------
14428 +* acx_l_process_data_frame_master
14429 +*----------------------------------------------------------------*/
14431 +acx_l_process_data_frame_master(wlandevice_t *priv, rxbuffer_t *rxbuf)
14433 + struct wlan_hdr *hdr;
14437 + int result = NOT_OK;
14441 + hdr = acx_get_wlan_hdr(priv, rxbuf);
14443 + switch (WF_FC_FROMTODSi & hdr->fc) {
14445 + case WF_FC_FROMDSi:
14446 + acxlog(L_DEBUG, "ap->sta or adhoc->adhoc data frame ignored\n");
14448 + case WF_FC_TODSi:
14450 + default: /* WF_FC_FROMTODSi */
14451 + acxlog(L_DEBUG, "wds data frame ignored (todo)\n");
14455 + /* check if it is our BSSID, if not, leave */
14456 + if (!mac_is_equal(priv->bssid, hdr->a1)) {
14460 + if (mac_is_equal(priv->dev_addr, hdr->a3)) {
14461 + /* this one is for us */
14462 + acx_l_rx(priv, rxbuf);
14464 + if (mac_is_bcast(hdr->a3)) {
14465 + /* this one is bcast, rx it too */
14466 + acx_l_rx(priv, rxbuf);
14468 + tx = acx_l_alloc_tx(priv);
14472 + /* repackage, tx, and hope it someday reaches its destination */
14473 + /* order is important, we do it in-place */
14474 + MAC_COPY(hdr->a1, hdr->a3);
14475 + MAC_COPY(hdr->a3, hdr->a2);
14476 + MAC_COPY(hdr->a2, priv->bssid);
14477 + /* To_DS = 0, From_DS = 1 */
14478 + hdr->fc = WF_FC_FROMDSi + WF_FTYPE_DATAi;
14480 + len = RXBUF_BYTES_RCVD(rxbuf);
14481 + txbuf = acx_l_get_txbuf(priv, tx);
14483 + memcpy(txbuf, &rxbuf->hdr_a3, len);
14484 + acx_l_tx_data(priv, tx, len);
14490 + FN_EXIT1(result);
14495 +/*----------------------------------------------------------------
14496 +* acx_l_process_data_frame_client
14497 +*----------------------------------------------------------------*/
14499 +acx_l_process_data_frame_client(wlandevice_t *priv, rxbuffer_t *rxbuf)
14501 + const u8 *da, *bssid;
14502 + const wlan_hdr_t *hdr;
14503 + netdevice_t *dev = priv->netdev;
14504 + int result = NOT_OK;
14508 + if (ACX_STATUS_4_ASSOCIATED != priv->status)
14511 + hdr = acx_get_wlan_hdr(priv, rxbuf);
14513 + switch (WF_FC_FROMTODSi & hdr->fc) {
14515 + if (priv->mode != ACX_MODE_0_ADHOC) {
14516 + acxlog(L_DEBUG, "adhoc->adhoc data frame ignored\n");
14521 + case WF_FC_FROMDSi:
14522 + if (priv->mode != ACX_MODE_2_STA) {
14523 + acxlog(L_DEBUG, "ap->sta data frame ignored\n");
14528 + case WF_FC_TODSi:
14529 + acxlog(L_DEBUG, "sta->ap data frame ignored\n");
14531 + default: /* WF_FC_FROMTODSi: wds->wds */
14532 + acxlog(L_DEBUG, "wds data frame ignored (todo)\n");
14538 + if (unlikely(acx_debug & L_DEBUG)) {
14539 + acx_print_mac("rx: da=", da, "");
14540 + acx_print_mac(" bssid=", bssid, "");
14541 + acx_print_mac(" priv->bssid=", priv->bssid, "");
14542 + acx_print_mac(" priv->addr=", priv->dev_addr, "\n");
14545 + /* promiscuous mode --> receive all packets */
14546 + if (unlikely(dev->flags & IFF_PROMISC))
14549 + /* FIRST, check if it is our BSSID */
14550 + if (!mac_is_equal(priv->bssid, bssid)) {
14551 + /* is not our BSSID, so bail out */
14555 + /* then, check if it is our address */
14556 + if (mac_is_equal(priv->dev_addr, da)) {
14560 + /* then, check if it is broadcast */
14561 + if (mac_is_bcast(da)) {
14565 + if (mac_is_mcast(da)) {
14566 + /* unconditionally receive all multicasts */
14567 + if (dev->flags & IFF_ALLMULTI)
14570 + /* FIXME: check against the list of
14571 + * multicast addresses that are configured
14572 + * for the interface (ifconfig) */
14573 + acxlog(L_XFER, "FIXME: multicast packet, need to check "
14574 + "against a list of multicast addresses "
14575 + "(to be created!); accepting packet for now\n");
14576 + /* for now, just accept it here */
14580 + acxlog(L_DEBUG, "rx: foreign packet, dropping\n");
14583 + /* receive packet */
14584 + acx_l_rx(priv, rxbuf);
14588 + FN_EXIT1(result);
14593 +/*----------------------------------------------------------------
14594 +* acx_l_process_mgmt_frame
14596 +* Theory of operation: mgmt packet gets parsed (to make it easy
14597 +* to access variable-sized IEs), results stored in 'parsed'.
14598 +* Then we react to the packet.
14599 +* NB: wlan_mgmt_decode_XXX are dev-independent (shoudnt have been named acx_XXX)
14600 +*----------------------------------------------------------------*/
14601 +typedef union parsed_mgmt_req {
14602 + wlan_fr_mgmt_t mgmt;
14603 + wlan_fr_assocreq_t assocreq;
14604 + wlan_fr_reassocreq_t reassocreq;
14605 + wlan_fr_assocresp_t assocresp;
14606 + wlan_fr_reassocresp_t reassocresp;
14607 + wlan_fr_beacon_t beacon;
14608 + wlan_fr_disassoc_t disassoc;
14609 + wlan_fr_authen_t authen;
14610 + wlan_fr_deauthen_t deauthen;
14611 + wlan_fr_proberesp_t proberesp;
14612 +} parsed_mgmt_req_t;
14614 +void BUG_excessive_stack_usage(void);
14617 +acx_l_process_mgmt_frame(wlandevice_t *priv, rxbuffer_t *rxbuf)
14619 + parsed_mgmt_req_t parsed; /* takes ~100 bytes of stack */
14621 + int adhoc, sta_scan, sta, ap;
14624 + if (sizeof(parsed) > 256)
14625 + BUG_excessive_stack_usage();
14629 + hdr = acx_get_wlan_hdr(priv, rxbuf);
14631 + /* Management frames never have these set */
14632 + if (WF_FC_FROMTODSi & hdr->fc) {
14633 + FN_EXIT1(NOT_OK);
14637 + len = RXBUF_BYTES_RCVD(rxbuf);
14638 + if (WF_FC_ISWEPi & hdr->fc)
14641 + adhoc = (priv->mode == ACX_MODE_0_ADHOC);
14642 + sta_scan = ((priv->mode == ACX_MODE_2_STA)
14643 + && (priv->status != ACX_STATUS_4_ASSOCIATED));
14644 + sta = ((priv->mode == ACX_MODE_2_STA)
14645 + && (priv->status == ACX_STATUS_4_ASSOCIATED));
14646 + ap = (priv->mode == ACX_MODE_3_AP);
14648 + switch (WF_FC_FSTYPEi & hdr->fc) {
14649 + /* beacons first, for speed */
14650 + case WF_FSTYPE_BEACONi:
14651 + memset(&parsed.beacon, 0, sizeof(parsed.beacon));
14652 + parsed.beacon.hdr = hdr;
14653 + parsed.beacon.len = len;
14654 + if (acx_debug & L_DATA) {
14655 + printk("beacon len:%d fc:%04X dur:%04X seq:%04X",
14656 + len, hdr->fc, hdr->dur, hdr->seq);
14657 + acx_print_mac(" a1:", hdr->a1, "");
14658 + acx_print_mac(" a2:", hdr->a2, "");
14659 + acx_print_mac(" a3:", hdr->a3, "\n");
14661 + wlan_mgmt_decode_beacon(&parsed.beacon);
14662 + /* beacon and probe response are very similar, so... */
14663 + acx_l_process_probe_response(priv, &parsed.beacon, rxbuf);
14665 + case WF_FSTYPE_ASSOCREQi:
14668 + memset(&parsed.assocreq, 0, sizeof(parsed.assocreq));
14669 + parsed.assocreq.hdr = hdr;
14670 + parsed.assocreq.len = len;
14671 + wlan_mgmt_decode_assocreq(&parsed.assocreq);
14672 + if (mac_is_equal(hdr->a1, priv->bssid)
14673 + && mac_is_equal(hdr->a3, priv->bssid)) {
14674 + acx_l_transmit_assocresp(priv, &parsed.assocreq);
14677 + case WF_FSTYPE_REASSOCREQi:
14680 + memset(&parsed.assocreq, 0, sizeof(parsed.assocreq));
14681 + parsed.assocreq.hdr = hdr;
14682 + parsed.assocreq.len = len;
14683 + wlan_mgmt_decode_assocreq(&parsed.assocreq);
14684 + /* reassocreq and assocreq are equivalent */
14685 + acx_l_transmit_reassocresp(priv, &parsed.reassocreq);
14687 + case WF_FSTYPE_ASSOCRESPi:
14690 + memset(&parsed.assocresp, 0, sizeof(parsed.assocresp));
14691 + parsed.assocresp.hdr = hdr;
14692 + parsed.assocresp.len = len;
14693 + wlan_mgmt_decode_assocresp(&parsed.assocresp);
14694 + acx_l_process_assocresp(priv, &parsed.assocresp);
14696 + case WF_FSTYPE_REASSOCRESPi:
14699 + memset(&parsed.assocresp, 0, sizeof(parsed.assocresp));
14700 + parsed.assocresp.hdr = hdr;
14701 + parsed.assocresp.len = len;
14702 + wlan_mgmt_decode_assocresp(&parsed.assocresp);
14703 + acx_l_process_reassocresp(priv, &parsed.reassocresp);
14705 + case WF_FSTYPE_PROBEREQi:
14706 + if (ap || adhoc) {
14707 + /* FIXME: since we're supposed to be an AP,
14708 + ** we need to return a Probe Response packet.
14709 + ** Currently firmware is doing it for us,
14710 + ** but firmware is buggy! See comment elsewhere --vda */
14713 + case WF_FSTYPE_PROBERESPi:
14714 + memset(&parsed.proberesp, 0, sizeof(parsed.proberesp));
14715 + parsed.proberesp.hdr = hdr;
14716 + parsed.proberesp.len = len;
14717 + wlan_mgmt_decode_proberesp(&parsed.proberesp);
14718 + acx_l_process_probe_response(priv, &parsed.proberesp, rxbuf);
14724 + case WF_FSTYPE_ATIMi:
14727 + case WF_FSTYPE_DISASSOCi:
14730 + memset(&parsed.disassoc, 0, sizeof(parsed.disassoc));
14731 + parsed.disassoc.hdr = hdr;
14732 + parsed.disassoc.len = len;
14733 + wlan_mgmt_decode_disassoc(&parsed.disassoc);
14735 + acx_l_process_disassoc_from_ap(priv, &parsed.disassoc);
14737 + acx_l_process_disassoc_from_sta(priv, &parsed.disassoc);
14739 + case WF_FSTYPE_AUTHENi:
14740 + if (!sta_scan && !ap)
14742 + memset(&parsed.authen, 0, sizeof(parsed.authen));
14743 + parsed.authen.hdr = hdr;
14744 + parsed.authen.len = len;
14745 + wlan_mgmt_decode_authen(&parsed.authen);
14746 + acx_l_process_authen(priv, &parsed.authen);
14748 + case WF_FSTYPE_DEAUTHENi:
14751 + memset(&parsed.deauthen, 0, sizeof(parsed.deauthen));
14752 + parsed.deauthen.hdr = hdr;
14753 + parsed.deauthen.len = len;
14754 + wlan_mgmt_decode_deauthen(&parsed.deauthen);
14756 + acx_l_process_deauth_from_ap(priv, &parsed.deauthen);
14758 + acx_l_process_deauth_from_sta(priv, &parsed.deauthen);
14768 +/*----------------------------------------------------------------
14769 +* acx_process_class_frame
14771 +* Called from IRQ context only
14772 +*----------------------------------------------------------------*/
14774 +acx_process_class_frame(wlandevice_t *priv, rxbuffer_t *rxbuf, int vala)
14781 +/*----------------------------------------------------------------
14782 +* acx_l_process_NULL_frame
14783 +*----------------------------------------------------------------*/
14784 +#ifdef BOGUS_ITS_NOT_A_NULL_FRAME_HANDLER_AT_ALL
14786 +acx_l_process_NULL_frame(wlandevice_t *priv, rxbuffer_t *rxbuf, int vala)
14788 + const signed char *esi;
14790 + const wlan_hdr_t *hdr;
14791 + const client_t *client;
14792 + int result = NOT_OK;
14794 + hdr = acx_get_wlan_hdr(priv, rxbuf);
14796 + switch (WF_FC_FROMTODSi & hdr->fc) {
14801 + case WF_FC_FROMDSi:
14805 + case WF_FC_TODSi:
14809 + default: /* WF_FC_FROMTODSi */
14810 + esi = hdr->a1; /* added by me! --vda */
14814 + if (esi[0x0] < 0) {
14819 + client = acx_l_sta_list_get(priv, ebx);
14823 +#ifdef IS_IT_BROKEN
14824 + acxlog(L_DEBUG|L_XFER, "<transmit_deauth 7>\n");
14825 + acx_l_transmit_deauthen(priv, ebx,
14826 + WLAN_MGMT_REASON_CLASS2_NONAUTH);
14828 + acxlog(L_DEBUG, "received NULL frame from unknown client! "
14829 + "We really shouldn't send deauthen here, right?\n");
14839 +/*----------------------------------------------------------------
14840 +* acx_l_process_probe_response
14841 +*----------------------------------------------------------------*/
14843 +acx_l_process_probe_response(wlandevice_t *priv, wlan_fr_proberesp_t *req,
14844 + const rxbuffer_t *rxbuf)
14846 + struct client *bss;
14853 + if (mac_is_equal(hdr->a3, priv->dev_addr)) {
14854 + acxlog(L_ASSOC, "huh, scan found our own MAC!?\n");
14855 + goto ok; /* just skip this one silently */
14858 + bss = acx_l_sta_list_get_or_add(priv, hdr->a2);
14860 + /* NB: be careful modifying bss data! It may be one
14861 + ** of already known clients (like our AP is we are a STA)
14862 + ** Thus do not blindly modify e.g. current ratemask! */
14864 + if (STA_LIST_ADD_CAN_FAIL && !bss) {
14865 + /* uh oh, we found more sites/stations than we can handle with
14866 + * our current setup: pull the emergency brake and stop scanning! */
14867 + acx_schedule_after_interrupt_task(priv, ACX_AFTER_IRQ_CMD_STOP_SCAN);
14868 + /* TODO: a nice comment what below call achieves --vda */
14869 + acx_set_status(priv, ACX_STATUS_2_WAIT_AUTH);
14872 + /* NB: get_or_add already filled bss->address = hdr->a2 */
14873 + MAC_COPY(bss->bssid, hdr->a3);
14875 + /* copy the ESSID element */
14876 + if (req->ssid && req->ssid->len <= IW_ESSID_MAX_SIZE) {
14877 + bss->essid_len = req->ssid->len;
14878 + memcpy(bss->essid, req->ssid->ssid, req->ssid->len);
14879 + bss->essid[req->ssid->len] = '\0';
14881 + /* Either no ESSID IE or oversized one */
14882 + printk("%s: received packet has bogus ESSID\n",
14883 + priv->netdev->name);
14886 + if (req->ds_parms)
14887 + bss->channel = req->ds_parms->curr_ch;
14888 + if (req->cap_info)
14889 + bss->cap_info = ieee2host16(*req->cap_info);
14891 + bss->sir = acx_signal_to_winlevel(rxbuf->phy_level);
14892 + bss->snr = acx_signal_to_winlevel(rxbuf->phy_snr);
14894 + bss->rate_cap = 0; /* operational mask */
14895 + bss->rate_bas = 0; /* basic mask */
14896 + if (req->supp_rates)
14897 + add_bits_to_ratemasks(req->supp_rates->rates,
14898 + req->supp_rates->len, &bss->rate_bas, &bss->rate_cap);
14899 + if (req->ext_rates)
14900 + add_bits_to_ratemasks(req->ext_rates->rates,
14901 + req->ext_rates->len, &bss->rate_bas, &bss->rate_cap);
14902 + /* Fix up any possible bogosity - code elsewhere
14903 + * is not expecting empty masks */
14904 + if (!bss->rate_cap)
14905 + bss->rate_cap = priv->rate_basic;
14906 + if (!bss->rate_bas)
14907 + bss->rate_bas = 1 << lowest_bit(bss->rate_cap);
14908 + if (!bss->rate_cur)
14909 + bss->rate_cur = 1 << lowest_bit(bss->rate_bas);
14911 + /* People moan about this being too noisy at L_ASSOC */
14913 + "found %s: ESSID='%s' ch=%d "
14914 + "BSSID="MACSTR" caps=0x%04X SIR=%d SNR=%d\n",
14915 + (bss->cap_info & WF_MGMT_CAP_IBSS) ? "Ad-Hoc peer" : "AP",
14916 + bss->essid, bss->channel, MAC(bss->bssid), bss->cap_info,
14917 + bss->sir, bss->snr);
14924 +/*----------------------------------------------------------------
14925 +* acx_l_process_assocresp
14926 +*----------------------------------------------------------------*/
14928 +acx_l_process_assocresp(wlandevice_t *priv, const wlan_fr_assocresp_t *req)
14930 + const wlan_hdr_t *hdr;
14936 + if ((ACX_MODE_2_STA == priv->mode)
14937 + && mac_is_equal(priv->dev_addr, hdr->a1)) {
14938 + u16 st = ieee2host16(*(req->status));
14939 + if (WLAN_MGMT_STATUS_SUCCESS == st) {
14940 + priv->aid = ieee2host16(*(req->aid));
14941 + /* tell the card we are associated when we are out of interrupt context */
14942 + acx_schedule_after_interrupt_task(priv, ACX_AFTER_IRQ_CMD_ASSOCIATE);
14945 + /* TODO: we shall delete peer from sta_list, and try other candidates... */
14947 + printk("%s: association FAILED: peer sent "
14948 + "response code %d (%s)\n",
14949 + priv->netdev->name, st, get_status_string(st));
14959 +/*----------------------------------------------------------------
14960 +* acx_l_process_reassocresp
14961 +*----------------------------------------------------------------*/
14963 +acx_l_process_reassocresp(wlandevice_t *priv, const wlan_fr_reassocresp_t *req)
14965 + const wlan_hdr_t *hdr;
14966 + int result = NOT_OK;
14972 + if (!mac_is_equal(priv->dev_addr, hdr->a1)) {
14975 + st = ieee2host16(*(req->status));
14976 + if (st == WLAN_MGMT_STATUS_SUCCESS) {
14977 + acx_set_status(priv, ACX_STATUS_4_ASSOCIATED);
14980 + printk("%s: reassociation FAILED: peer sent "
14981 + "response code %d (%s)\n",
14982 + priv->netdev->name, st, get_status_string(st));
14985 + FN_EXIT1(result);
14990 +/*----------------------------------------------------------------
14991 +* acx_l_process_authen
14993 +* Called only in STA_SCAN or AP mode
14994 +*----------------------------------------------------------------*/
14996 +acx_l_process_authen(wlandevice_t *priv, const wlan_fr_authen_t *req)
14998 + const wlan_hdr_t *hdr;
15000 + wlan_ie_challenge_t *chal;
15001 + u16 alg, seq, status;
15008 + if (acx_debug & L_ASSOC) {
15009 + acx_print_mac("AUTHEN priv->addr=", priv->dev_addr, " ");
15010 + acx_print_mac("a1=", hdr->a1, " ");
15011 + acx_print_mac("a2=", hdr->a2, " ");
15012 + acx_print_mac("a3=", hdr->a3, " ");
15013 + acx_print_mac("priv->bssid=", priv->bssid, "\n");
15016 + if (!mac_is_equal(priv->dev_addr, hdr->a1)
15017 + || !mac_is_equal(priv->bssid, hdr->a3)) {
15022 + alg = ieee2host16(*(req->auth_alg));
15023 + seq = ieee2host16(*(req->auth_seq));
15024 + status = ieee2host16(*(req->status));
15026 + ap = (priv->mode == ACX_MODE_3_AP);
15028 + if (priv->auth_alg <= 1) {
15029 + if (priv->auth_alg != alg) {
15030 + acxlog(L_ASSOC, "authentication algorithm mismatch: "
15031 + "want: %d, req: %d\n", priv->auth_alg, alg);
15036 + acxlog(L_ASSOC, "algorithm is ok\n");
15039 + clt = acx_l_sta_list_get_or_add(priv, hdr->a2);
15040 + if (STA_LIST_ADD_CAN_FAIL && !clt) {
15041 + acxlog(L_ASSOC, "could not allocate room for client\n");
15046 + clt = priv->ap_client;
15047 + if (!mac_is_equal(clt->address, hdr->a2)) {
15048 + printk("%s: malformed auth frame from AP?!\n",
15049 + priv->netdev->name);
15055 + /* now check which step in the authentication sequence we are
15056 + * currently in, and act accordingly */
15057 + acxlog(L_ASSOC, "acx_process_authen auth seq step %d\n", seq);
15062 + acx_l_transmit_authen2(priv, req, clt);
15067 + if (status == WLAN_MGMT_STATUS_SUCCESS) {
15068 + if (alg == WLAN_AUTH_ALG_OPENSYSTEM) {
15069 + acx_set_status(priv, ACX_STATUS_3_AUTHENTICATED);
15070 + acx_l_transmit_assoc_req(priv);
15072 + if (alg == WLAN_AUTH_ALG_SHAREDKEY) {
15073 + acx_l_transmit_authen3(priv, req);
15076 + printk("%s: auth FAILED: peer sent "
15077 + "response code %d (%s), "
15078 + "still waiting for authentication\n",
15079 + priv->netdev->name,
15080 + status, get_status_string(status));
15081 + acx_set_status(priv, ACX_STATUS_2_WAIT_AUTH);
15087 + if ((clt->auth_alg != WLAN_AUTH_ALG_SHAREDKEY)
15088 + || (alg != WLAN_AUTH_ALG_SHAREDKEY)
15089 + || (clt->auth_step != 2))
15091 + chal = req->challenge;
15093 + || memcmp(chal->challenge, clt->challenge_text, WLAN_CHALLENGE_LEN)
15094 + || (chal->eid != WLAN_EID_CHALLENGE)
15095 + || (chal->len != WLAN_CHALLENGE_LEN)
15098 + acx_l_transmit_authen4(priv, req);
15099 + MAC_COPY(clt->address, hdr->a2);
15100 + clt->used = CLIENT_AUTHENTICATED_2;
15101 + clt->auth_step = 4;
15102 + clt->seq = ieee2host16(hdr->seq);
15107 + /* ok, we're through: we're authenticated. Woohoo!! */
15108 + acx_set_status(priv, ACX_STATUS_3_AUTHENTICATED);
15109 + acxlog(L_ASSOC, "Authenticated!\n");
15110 + /* now that we're authenticated, request association */
15111 + acx_l_transmit_assoc_req(priv);
15116 + FN_EXIT1(result);
15121 +/*----------------------------------------------------------------
15122 +* acx_gen_challenge
15123 +*----------------------------------------------------------------*/
15125 +acx_gen_challenge(wlan_ie_challenge_t* d)
15128 + d->eid = WLAN_EID_CHALLENGE;
15129 + d->len = WLAN_CHALLENGE_LEN;
15130 + get_random_bytes(d->challenge, WLAN_CHALLENGE_LEN);
15135 +/*----------------------------------------------------------------
15136 +* acx_l_transmit_deauthen
15137 +*----------------------------------------------------------------*/
15139 +acx_l_transmit_deauthen(wlandevice_t *priv, const u8 *addr, u16 reason)
15142 + struct wlan_hdr_mgmt *head;
15143 + struct deauthen_frame_body *body;
15147 + tx = acx_l_alloc_tx(priv);
15150 + head = acx_l_get_txbuf(priv, tx);
15153 + body = (void*)(head + 1);
15155 + head->fc = (WF_FTYPE_MGMTi | WF_FSTYPE_DEAUTHENi);
15157 + MAC_COPY(head->da, addr);
15158 + MAC_COPY(head->sa, priv->dev_addr);
15159 + MAC_COPY(head->bssid, priv->bssid);
15162 + acxlog(L_DEBUG|L_ASSOC|L_XFER,
15163 + "sending deauthen to "MACSTR" for %d\n",
15164 + MAC(addr), reason);
15166 + body->reason = host2ieee16(reason);
15168 + /* body is fixed size here, but beware of cutting-and-pasting this -
15169 + ** do not use sizeof(*body) for variable sized mgmt packets! */
15170 + acx_l_tx_data(priv, tx, WLAN_HDR_A3_LEN + sizeof(*body));
15175 + FN_EXIT1(NOT_OK);
15180 +/*----------------------------------------------------------------
15181 +* acx_l_transmit_authen1
15182 +*----------------------------------------------------------------*/
15184 +acx_l_transmit_authen1(wlandevice_t *priv)
15187 + struct wlan_hdr_mgmt *head;
15188 + struct auth_frame_body *body;
15192 + acxlog(L_ASSOC, "Sending authentication1 request, "
15193 + "awaiting response!\n");
15195 + tx = acx_l_alloc_tx(priv);
15198 + head = acx_l_get_txbuf(priv, tx);
15201 + body = (void*)(head + 1);
15203 + head->fc = WF_FSTYPE_AUTHENi;
15204 + head->dur = host2ieee16(0x8000);
15205 + MAC_COPY(head->da, priv->bssid);
15206 + MAC_COPY(head->sa, priv->dev_addr);
15207 + MAC_COPY(head->bssid, priv->bssid);
15210 + body->auth_alg = host2ieee16(priv->auth_alg);
15211 + body->auth_seq = host2ieee16(1);
15212 + body->status = host2ieee16(0);
15214 + acx_l_tx_data(priv, tx, WLAN_HDR_A3_LEN + 2 + 2 + 2);
15219 + FN_EXIT1(NOT_OK);
15224 +/*----------------------------------------------------------------
15225 +* acx_l_transmit_authen2
15226 +*----------------------------------------------------------------*/
15228 +acx_l_transmit_authen2(wlandevice_t *priv, const wlan_fr_authen_t *req,
15232 + struct wlan_hdr_mgmt *head;
15233 + struct auth_frame_body *body;
15234 + unsigned int packet_len;
15241 + MAC_COPY(clt->address, req->hdr->a2);
15243 + clt->ps = ((WF_FC_PWRMGTi & req->hdr->fc) != 0);
15245 + clt->auth_alg = ieee2host16(*(req->auth_alg));
15246 + clt->auth_step = 2;
15247 + clt->seq = ieee2host16(req->hdr->seq);
15249 + tx = acx_l_alloc_tx(priv);
15252 + head = acx_l_get_txbuf(priv, tx);
15255 + body = (void*)(head + 1);
15257 + head->fc = WF_FSTYPE_AUTHENi; /* 0xb0 */
15258 + head->dur = req->hdr->dur;
15259 + MAC_COPY(head->da, req->hdr->a2);
15260 + /* MAC_COPY(head->sa, req->hdr->a1); */
15261 + MAC_COPY(head->sa, priv->dev_addr);
15262 + MAC_COPY(head->bssid, req->hdr->a3);
15263 + head->seq = req->hdr->seq;
15265 + /* already in IEEE format, no endianness conversion */
15266 + body->auth_alg = *(req->auth_alg);
15267 + body->auth_seq = host2ieee16(2);
15268 + body->status = host2ieee16(0);
15270 + packet_len = WLAN_HDR_A3_LEN + 2 + 2 + 2;
15271 + if (ieee2host16(*(req->auth_alg)) == WLAN_AUTH_ALG_OPENSYSTEM) {
15272 + clt->used = CLIENT_AUTHENTICATED_2;
15273 + } else { /* shared key */
15274 + acx_gen_challenge(&body->challenge);
15275 + memcpy(&clt->challenge_text, body->challenge.challenge, WLAN_CHALLENGE_LEN);
15276 + packet_len += 2 + 2 + 2 + 1+1+WLAN_CHALLENGE_LEN;
15279 + acxlog_mac(L_ASSOC|L_XFER,
15280 + "transmit_auth2: BSSID=", head->bssid, "\n");
15282 + acx_l_tx_data(priv, tx, packet_len);
15287 + FN_EXIT1(NOT_OK);
15292 +/*----------------------------------------------------------------
15293 +* acx_l_transmit_authen3
15294 +*----------------------------------------------------------------*/
15296 +acx_l_transmit_authen3(wlandevice_t *priv, const wlan_fr_authen_t *req)
15299 + struct wlan_hdr_mgmt *head;
15300 + struct auth_frame_body *body;
15301 + unsigned int packet_len;
15305 + tx = acx_l_alloc_tx(priv);
15308 + head = acx_l_get_txbuf(priv, tx);
15311 + body = (void*)(head + 1);
15313 + head->fc = WF_FC_ISWEPi + WF_FSTYPE_AUTHENi;
15314 + /* FIXME: is this needed?? authen4 does it...
15315 + head->dur = req->hdr->dur;
15316 + head->seq = req->hdr->seq;
15318 + MAC_COPY(head->da, priv->bssid);
15319 + MAC_COPY(head->sa, priv->dev_addr);
15320 + MAC_COPY(head->bssid, priv->bssid);
15322 + /* already in IEEE format, no endianness conversion */
15323 + body->auth_alg = *(req->auth_alg);
15324 + body->auth_seq = host2ieee16(3);
15325 + body->status = host2ieee16(0);
15326 + memcpy(&body->challenge, req->challenge, req->challenge->len + 2);
15327 + packet_len = WLAN_HDR_A3_LEN + 8 + req->challenge->len;
15329 + acxlog(L_ASSOC|L_XFER, "transmit_authen3!\n");
15331 + acx_l_tx_data(priv, tx, packet_len);
15338 +/*----------------------------------------------------------------
15339 +* acx_l_transmit_authen4
15340 +*----------------------------------------------------------------*/
15342 +acx_l_transmit_authen4(wlandevice_t *priv, const wlan_fr_authen_t *req)
15345 + struct wlan_hdr_mgmt *head;
15346 + struct auth_frame_body *body;
15350 + tx = acx_l_alloc_tx(priv);
15353 + head = acx_l_get_txbuf(priv, tx);
15356 + body = (void*)(head + 1);
15358 + head->fc = WF_FSTYPE_AUTHENi; /* 0xb0 */
15359 + head->dur = req->hdr->dur;
15360 + MAC_COPY(head->da, req->hdr->a2);
15361 + /* MAC_COPY(head->sa, req->hdr->a1); */
15362 + MAC_COPY(head->sa, priv->dev_addr);
15363 + MAC_COPY(head->bssid, req->hdr->a3);
15364 + head->seq = req->hdr->seq;
15366 + /* already in IEEE format, no endianness conversion */
15367 + body->auth_alg = *(req->auth_alg);
15368 + body->auth_seq = host2ieee16(4);
15369 + body->status = host2ieee16(0);
15371 + acx_l_tx_data(priv, tx, WLAN_HDR_A3_LEN + 2 + 2 + 2);
15378 +/*----------------------------------------------------------------
15379 +* acx_l_transmit_assoc_req
15381 +* priv->ap_client is a current candidate AP here
15382 +*----------------------------------------------------------------*/
15384 +acx_l_transmit_assoc_req(wlandevice_t *priv)
15387 + struct wlan_hdr_mgmt *head;
15388 + u8 *body, *p, *prate;
15389 + unsigned int packet_len;
15394 + acxlog(L_ASSOC, "sending association request, "
15395 + "awaiting response. NOT ASSOCIATED YET\n");
15396 + tx = acx_l_alloc_tx(priv);
15399 + head = acx_l_get_txbuf(priv, tx);
15402 + body = (void*)(head + 1);
15404 + head->fc = WF_FSTYPE_ASSOCREQi;
15405 + head->dur = host2ieee16(0x8000);
15406 + MAC_COPY(head->da, priv->bssid);
15407 + MAC_COPY(head->sa, priv->dev_addr);
15408 + MAC_COPY(head->bssid, priv->bssid);
15412 + /* now start filling the AssocReq frame body */
15414 + /* since this assoc request will most likely only get
15415 + * sent in the STA to AP case (and not when Ad-Hoc IBSS),
15416 + * the cap combination indicated here will thus be
15417 + * WF_MGMT_CAP_ESSi *always* (no IBSS ever)
15418 + * The specs are more than non-obvious on all that:
15420 + * 802.11 7.3.1.4 Capability Information field
15421 + ** APs set the ESS subfield to 1 and the IBSS subfield to 0 within
15422 + ** Beacon or Probe Response management frames. STAs within an IBSS
15423 + ** set the ESS subfield to 0 and the IBSS subfield to 1 in transmitted
15424 + ** Beacon or Probe Response management frames
15426 + ** APs set the Privacy subfield to 1 within transmitted Beacon,
15427 + ** Probe Response, Association Response, and Reassociation Response
15428 + ** if WEP is required for all data type frames within the BSS.
15429 + ** STAs within an IBSS set the Privacy subfield to 1 in Beacon
15430 + ** or Probe Response management frames if WEP is required
15431 + ** for all data type frames within the IBSS */
15433 + /* note that returning 0 will be refused by several APs...
15434 + * (so this indicates that you're probably supposed to
15435 + * "confirm" the ESS mode) */
15436 + cap = WF_MGMT_CAP_ESSi;
15438 + /* this one used to be a check on wep_restricted,
15439 + * but more likely it's wep_enabled instead */
15440 + if (priv->wep_enabled)
15441 + SET_BIT(cap, WF_MGMT_CAP_PRIVACYi);
15443 + /* Probably we can just set these always, because our hw is
15444 + ** capable of shortpre and PBCC --vda */
15445 + /* only ask for short preamble if the peer station supports it */
15446 + if (priv->ap_client->cap_info & WF_MGMT_CAP_SHORT)
15447 + SET_BIT(cap, WF_MGMT_CAP_SHORTi);
15448 + /* only ask for PBCC support if the peer station supports it */
15449 + if (priv->ap_client->cap_info & WF_MGMT_CAP_PBCC)
15450 + SET_BIT(cap, WF_MGMT_CAP_PBCCi);
15452 + /* IEs: 1. caps */
15453 + *(u16*)p = cap; p += 2;
15454 + /* 2. listen interval */
15455 + *(u16*)p = host2ieee16(priv->listen_interval); p += 2;
15457 + p = wlan_fill_ie_ssid(p,
15458 + strlen(priv->essid_for_assoc), priv->essid_for_assoc);
15459 + /* 4. supp rates */
15461 + p = wlan_fill_ie_rates(p,
15462 + priv->rate_supported_len, priv->rate_supported);
15463 + /* 5. ext supp rates */
15464 + p = wlan_fill_ie_rates_ext(p,
15465 + priv->rate_supported_len, priv->rate_supported);
15467 + if (acx_debug & L_DEBUG) {
15468 + printk("association: rates element\n");
15469 + acx_dump_bytes(prate, p - prate);
15472 + /* calculate lengths */
15473 + packet_len = WLAN_HDR_A3_LEN + (p - body);
15475 + acxlog(L_ASSOC, "association: requesting caps 0x%04X, ESSID '%s'\n",
15476 + cap, priv->essid_for_assoc);
15478 + acx_l_tx_data(priv, tx, packet_len);
15482 + FN_EXIT1(NOT_OK);
15487 +/*----------------------------------------------------------------
15488 +* acx_l_transmit_disassoc
15490 +* FIXME: looks like incomplete implementation of a helper:
15491 +* acx_l_transmit_disassoc(priv, clt) - kick this client (we're an AP)
15492 +* acx_l_transmit_disassoc(priv, NULL) - leave BSSID (we're a STA)
15493 +*----------------------------------------------------------------*/
15496 +acx_l_transmit_disassoc(wlandevice_t *priv, client_t *clt)
15499 + struct wlan_hdr_mgmt *head;
15500 + struct disassoc_frame_body *body;
15503 +/* if (clt != NULL) { */
15504 + tx = acx_l_alloc_tx(priv);
15507 + head = acx_l_get_txbuf(priv, tx);
15510 + body = (void*)(head + 1);
15512 +/* clt->used = CLIENT_AUTHENTICATED_2; - not (yet?) associated */
15514 + head->fc = WF_FSTYPE_DISASSOCi;
15516 + /* huh? It muchly depends on whether we're STA or AP...
15517 + ** sta->ap: da=bssid, sa=own, bssid=bssid
15518 + ** ap->sta: da=sta, sa=bssid, bssid=bssid. FIXME! */
15519 + MAC_COPY(head->da, priv->bssid);
15520 + MAC_COPY(head->sa, priv->dev_addr);
15521 + MAC_COPY(head->bssid, priv->dev_addr);
15524 + /* "Class 3 frame received from nonassociated station." */
15525 + body->reason = host2ieee16(7);
15527 + /* fixed size struct, ok to sizeof */
15528 + acx_l_tx_data(priv, tx, WLAN_HDR_A3_LEN + sizeof(*body));
15533 + FN_EXIT1(NOT_OK);
15539 +/*----------------------------------------------------------------
15540 +* acx_s_complete_scan
15542 +* Called either from after_interrupt_task() if:
15543 +* 1) there was Scan_Complete IRQ, or
15544 +* 2) scanning expired in timer()
15545 +* We need to decide which ESS or IBSS to join.
15546 +* Iterates thru priv->sta_list:
15547 +* if priv->ap is not bcast, will join only specified
15548 +* ESS or IBSS with this bssid
15549 +* checks peers' caps for ESS/IBSS bit
15550 +* checks peers' SSID, allows exact match or hidden SSID
15551 +* If station to join is chosen:
15552 +* points priv->ap_client to the chosen struct client
15553 +* sets priv->essid_for_assoc for future assoc attempt
15554 +* Auth/assoc is not yet performed
15555 +* Returns OK if there is no need to restart scan
15556 +*----------------------------------------------------------------*/
15558 +acx_s_complete_scan(wlandevice_t *priv)
15560 + struct client *bss;
15561 + unsigned long flags;
15564 + int idx_found = -1;
15569 + switch (priv->mode) {
15570 + case ACX_MODE_0_ADHOC:
15571 + needed_cap = WF_MGMT_CAP_IBSS; /* 2, we require Ad-Hoc */
15573 + case ACX_MODE_2_STA:
15574 + needed_cap = WF_MGMT_CAP_ESS; /* 1, we require Managed */
15577 + printk("acx: driver bug: mode=%d in complete_scan()\n", priv->mode);
15582 + acx_lock(priv, flags);
15584 + /* TODO: sta_iterator hiding implementation would be nice here... */
15586 + for (i = 0; i < VEC_SIZE(priv->sta_list); i++) {
15587 + bss = &priv->sta_list[i];
15588 + if (!bss->used) continue;
15590 + acxlog(L_ASSOC, "Scan Table: SSID='%s' CH=%d SIR=%d SNR=%d\n",
15591 + bss->essid, bss->channel, bss->sir, bss->snr);
15593 + if (!mac_is_bcast(priv->ap))
15594 + if (!mac_is_equal(bss->bssid, priv->ap))
15595 + continue; /* keep looking */
15597 + /* broken peer with no mode flags set? */
15598 + if (unlikely(!(bss->cap_info & (WF_MGMT_CAP_ESS | WF_MGMT_CAP_IBSS)))) {
15599 + printk("%s: strange peer "MACSTR" found with "
15600 + "neither ESS (AP) nor IBSS (Ad-Hoc) "
15601 + "capability - skipped\n",
15602 + priv->netdev->name, MAC(bss->address));
15605 + acxlog(L_ASSOC, "peer_cap 0x%04X, needed_cap 0x%04X\n",
15606 + bss->cap_info, needed_cap);
15608 + /* does peer station support what we need? */
15609 + if ((bss->cap_info & needed_cap) != needed_cap)
15610 + continue; /* keep looking */
15612 + /* strange peer with NO basic rates?! */
15613 + if (unlikely(!bss->rate_bas)) {
15614 + printk("%s: strange peer "MACSTR" with empty rate set "
15616 + priv->netdev->name, MAC(bss->address));
15620 + /* do we support all basic rates of this peer? */
15621 + if ((bss->rate_bas & priv->rate_oper) != bss->rate_bas) {
15622 +/* we probably need to have all rates as operational rates,
15623 + even in case of an 11M-only configuration */
15624 +#ifdef THIS_IS_TROUBLESOME
15625 + printk("%s: peer "MACSTR": incompatible basic rates "
15626 + "(AP requests 0x%04X, we have 0x%04X) "
15628 + priv->netdev->name, MAC(bss->address),
15629 + bss->rate_bas, priv->rate_oper);
15632 + printk("%s: peer "MACSTR": incompatible basic rates "
15633 + "(AP requests 0x%04X, we have 0x%04X). "
15634 + "Considering anyway...\n",
15635 + priv->netdev->name, MAC(bss->address),
15636 + bss->rate_bas, priv->rate_oper);
15640 + if ( !(priv->reg_dom_chanmask & (1<<(bss->channel-1))) ) {
15641 + printk("%s: warning: peer "MACSTR" is on channel %d "
15642 + "outside of channel range of current "
15643 + "regulatory domain - couldn't join "
15644 + "even if other settings match. "
15645 + "You might want to adapt your config\n",
15646 + priv->netdev->name, MAC(bss->address),
15648 + continue; /* keep looking */
15651 + if (!priv->essid_active || !strcmp(bss->essid, priv->essid)) {
15653 + "found station with matching ESSID! ('%s' "
15654 + "station, '%s' config)\n",
15656 + (priv->essid_active) ? priv->essid : "[any]");
15657 + /* TODO: continue looking for peer with better SNR */
15658 + bss->used = CLIENT_JOIN_CANDIDATE;
15661 + /* stop searching if this station is
15662 + * on the current channel, otherwise
15663 + * keep looking for an even better match */
15664 + if (bss->channel == priv->channel)
15667 + if (!bss->essid[0]
15668 + || ((' ' == bss->essid[0]) && !bss->essid[1])
15670 + /* hmm, station with empty or single-space SSID:
15671 + * using hidden SSID broadcast?
15673 + /* This behaviour is broken: which AP from zillion
15674 + ** of APs with hidden SSID you'd try?
15675 + ** We should use Probe requests to get Probe responses
15676 + ** and check for real SSID (are those never hidden?) */
15677 + bss->used = CLIENT_JOIN_CANDIDATE;
15678 + if (idx_found == -1)
15680 + acxlog(L_ASSOC, "found station with empty or "
15681 + "single-space (hidden) SSID, considering "
15682 + "for assoc attempt\n");
15683 + /* ...and keep looking for better matches */
15685 + acxlog(L_ASSOC, "ESSID doesn't match! ('%s' "
15686 + "station, '%s' config)\n",
15688 + (priv->essid_active) ? priv->essid : "[any]");
15692 + /* TODO: iterate thru join candidates instead */
15693 + /* TODO: rescan if not associated within some timeout */
15694 + if (idx_found != -1) {
15696 + size_t essid_len;
15698 + bss = &priv->sta_list[idx_found];
15699 + priv->ap_client = bss;
15701 + if (bss->essid[0] == '\0') {
15702 + /* if the ESSID of the station we found is empty
15703 + * (no broadcast), then use user configured ESSID
15705 + essid_src = priv->essid;
15706 + essid_len = priv->essid_len;
15708 + essid_src = bss->essid;
15709 + essid_len = strlen(bss->essid);
15712 + acx_update_capabilities(priv);
15714 + memcpy(priv->essid_for_assoc, essid_src, essid_len);
15715 + priv->essid_for_assoc[essid_len] = '\0';
15716 + priv->channel = bss->channel;
15717 + MAC_COPY(priv->bssid, bss->bssid);
15719 + bss->rate_cfg = (bss->rate_cap & priv->rate_oper);
15720 + bss->rate_cur = 1 << lowest_bit(bss->rate_cfg);
15721 + bss->rate_100 = acx_rate111to100(bss->rate_cur);
15723 + acxlog_mac(L_ASSOC,
15724 + "matching station found: ", priv->bssid, ", joining\n");
15726 + /* TODO: do we need to switch to the peer's channel first? */
15728 + if (ACX_MODE_0_ADHOC == priv->mode) {
15729 + acx_set_status(priv, ACX_STATUS_4_ASSOCIATED);
15731 + acx_l_transmit_authen1(priv);
15732 + acx_set_status(priv, ACX_STATUS_2_WAIT_AUTH);
15734 + } else { /* idx_found == -1 */
15735 + /* uh oh, no station found in range */
15736 + if (ACX_MODE_0_ADHOC == priv->mode) {
15737 + printk("%s: no matching station found in range, "
15738 + "generating our own IBSS instead\n",
15739 + priv->netdev->name);
15740 + /* we do it hostap way: */
15741 + MAC_COPY(priv->bssid, priv->dev_addr);
15742 + priv->bssid[0] |= 0x02; /* 'local assigned addr' bit */
15743 + /* add IBSS bit to our caps... */
15744 + acx_update_capabilities(priv);
15745 + acx_set_status(priv, ACX_STATUS_4_ASSOCIATED);
15746 + /* In order to cmd_join be called below */
15749 + /* we shall scan again, AP can be
15750 + ** just temporarily powered off */
15752 + "no matching station found in range yet\n");
15753 + acx_set_status(priv, ACX_STATUS_1_SCANNING);
15758 + acx_unlock(priv, flags);
15760 + if (idx_found != -1) {
15761 + if (ACX_MODE_0_ADHOC == priv->mode) {
15762 + /* need to update channel in beacon template */
15763 + SET_BIT(priv->set_mask, SET_TEMPLATES);
15764 + if (ACX_STATE_IFACE_UP & priv->dev_state_mask)
15765 + acx_s_update_card_settings(priv, 0, 0);
15767 + /* Inform firmware on our decision to start or join BSS */
15768 + acx_s_cmd_join_bssid(priv, priv->bssid);
15772 + FN_EXIT1(result);
15777 +/***********************************************************************
15780 +** Loads a firmware image
15783 +** 0 unable to load file
15784 +** pointer to firmware success
15786 +#if USE_FW_LOADER_26
15788 +acx_s_read_fw(struct device *dev, const char *file, u32 *size)
15790 +#undef acx_s_read_fw
15792 +acx_s_read_fw(const char *file, u32 *size)
15795 + firmware_image_t *res;
15797 +#if USE_FW_LOADER_LEGACY
15798 + mm_segment_t orgfs;
15799 + unsigned long page;
15801 + struct file *inf;
15807 +#if USE_FW_LOADER_26
15808 + const struct firmware *fw_entry;
15811 + acxlog(L_DEBUG, "requesting firmware image '%s'\n", file);
15812 + if (!request_firmware(&fw_entry, file, dev)) {
15814 + if (fw_entry->size >= 8)
15815 + *size = 8 + le32_to_cpu(*(u32 *)(fw_entry->data + 4));
15816 + if (fw_entry->size != *size) {
15817 + printk("acx: firmware size does not match "
15818 + "firmware header: %d != %d, "
15819 + "aborting fw upload\n",
15820 + (int) fw_entry->size, (int) *size);
15821 + goto release_ret;
15823 + res = vmalloc(*size);
15825 + printk("acx: no memory for firmware "
15826 + "(%u bytes)\n", *size);
15827 + goto release_ret;
15829 + memcpy(res, fw_entry->data, fw_entry->size);
15831 + release_firmware(fw_entry);
15834 + printk("acx: firmware image '%s' was not provided. "
15835 + "Check your hotplug scripts\n", file);
15838 +#if USE_FW_LOADER_LEGACY
15839 + printk("acx: firmware upload via firmware_dir module parameter "
15840 + "is deprecated. Switch to using hotplug\n");
15843 + orgfs = get_fs(); /* store original fs */
15844 + set_fs(KERNEL_DS);
15846 + /* Read in whole file then check the size */
15847 + page = __get_free_page(GFP_KERNEL);
15848 + if (unlikely(0 == page)) {
15849 + printk("acx: no memory for firmware upload\n");
15853 + filename = kmalloc(PATH_MAX, GFP_KERNEL);
15854 + if (unlikely(!filename)) {
15855 + printk("acx: no memory for firmware upload\n");
15858 + if (!firmware_dir) {
15859 + firmware_dir = "/usr/share/acx";
15860 + acxlog(L_DEBUG, "no firmware directory specified "
15861 + "via module parameter firmware_dir, "
15862 + "using default %s\n", firmware_dir);
15864 + snprintf(filename, PATH_MAX, "%s/%s", firmware_dir, file);
15865 + acxlog(L_DEBUG, "reading firmware image '%s'\n", filename);
15867 + buffer = (char*)page;
15869 + /* Note that file must be given as absolute path:
15870 + * a relative path works on first loading,
15871 + * but any subsequent firmware loading during card
15872 + * eject/insert will fail, most likely since the first
15873 + * module loading happens in user space (and thus
15874 + * filp_open can figure out the absolute path from a
15875 + * relative path) whereas the card reinsert processing
15876 + * probably happens in kernel space where you don't have
15877 + * a current directory to be able to figure out an
15878 + * absolute path from a relative path... */
15879 + inf = filp_open(filename, O_RDONLY, 0);
15881 + if (OK != IS_ERR(inf)) {
15884 + switch (-PTR_ERR(inf)) {
15885 + case 2: err = "file not found";
15888 + err = "unknown error";
15891 + printk("acx: error %ld trying to open file '%s': %s\n",
15892 + -PTR_ERR(inf), file, err);
15896 + if (unlikely((NULL == inf->f_op) || (NULL == inf->f_op->read))) {
15897 + printk("acx: %s does not have a read method?!\n", file);
15903 + retval = inf->f_op->read(inf, buffer, PAGE_SIZE, &inf->f_pos);
15905 + if (unlikely(0 > retval)) {
15906 + printk("acx: error %d reading file '%s'\n",
15910 + } else if (0 == retval) {
15911 + if (0 == offset) {
15912 + printk("acx: firmware image file "
15913 + "'%s' is empty?!\n", file);
15915 + } else if (0 < retval) {
15916 + /* allocate result buffer here if needed,
15917 + * since we don't want to waste resources/time
15918 + * (in case file opening/reading fails)
15919 + * by doing allocation in front of the loop instead. */
15920 + if (NULL == res) {
15921 + *size = 8 + le32_to_cpu(*(u32 *)(4 + buffer));
15923 + res = vmalloc(*size);
15924 + if (NULL == res) {
15925 + printk("acx: unable to "
15926 + "allocate %u bytes for "
15927 + "firmware module upload\n",
15931 + acxlog(L_DEBUG, "allocated %u bytes "
15932 + "for firmware module loading\n",
15935 + if ((unlikely(offset + retval > *size))) {
15936 + printk("acx: ERROR: allocation "
15937 + "was less than firmware image size?!\n");
15940 + memcpy((u8*)res + offset, buffer, retval);
15941 + offset += retval;
15943 + } while (0 < retval);
15946 + retval = filp_close(inf, NULL);
15948 + if (unlikely(retval)) {
15949 + printk("acx: error %d closing file '%s'\n", -retval, file);
15952 + if (unlikely((NULL != res) && (offset != le32_to_cpu(res->size) + 8))) {
15953 + printk("acx: firmware is reporting a different size "
15954 + "(0x%08X; 0x%08X was read)\n",
15955 + le32_to_cpu(res->size) + 8, offset);
15966 + /* checksum will be verified in write_fw, so don't bother here */
15971 +#ifdef POWER_SAVE_80211
15972 +/*----------------------------------------------------------------
15973 +* acx_s_activate_power_save_mode
15974 +*----------------------------------------------------------------*/
15976 +acx_s_activate_power_save_mode(wlandevice_t *priv)
15978 + acx100_ie_powermgmt_t pm;
15982 + acx_s_interrogate(priv, &pm, ACX1xx_IE_POWER_MGMT);
15983 + if (pm.wakeup_cfg != 0x81)
15986 + pm.wakeup_cfg = 0;
15988 + pm.hangover_period = 0;
15989 + acx_s_configure(priv, &pm, ACX1xx_IE_POWER_MGMT);
15996 +/***********************************************************************
15997 +** acx_s_set_wepkey
16000 +acx100_s_set_wepkey(wlandevice_t *priv)
16002 + ie_dot11WEPDefaultKey_t dk;
16005 + for (i = 0; i < DOT11_MAX_DEFAULT_WEP_KEYS; i++) {
16006 + if (priv->wep_keys[i].size != 0) {
16007 + acxlog(L_INIT, "setting WEP key: %d with "
16008 + "total size: %d\n", i, (int) priv->wep_keys[i].size);
16010 + dk.keySize = priv->wep_keys[i].size;
16011 + dk.defaultKeyNum = i;
16012 + memcpy(dk.key, priv->wep_keys[i].key, dk.keySize);
16013 + acx_s_configure(priv, &dk, ACX100_IE_DOT11_WEP_DEFAULT_KEY_WRITE);
16019 +acx111_s_set_wepkey(wlandevice_t *priv)
16021 + acx111WEPDefaultKey_t dk;
16024 + for (i = 0; i < DOT11_MAX_DEFAULT_WEP_KEYS; i++) {
16025 + if (priv->wep_keys[i].size != 0) {
16026 + acxlog(L_INIT, "setting WEP key: %d with "
16027 + "total size: %d\n", i, (int) priv->wep_keys[i].size);
16028 + memset(&dk, 0, sizeof(dk));
16029 + dk.action = cpu_to_le16(1); /* "add key"; yes, that's a 16bit value */
16030 + dk.keySize = priv->wep_keys[i].size;
16032 + /* are these two lines necessary? */
16033 + dk.type = 0; /* default WEP key */
16034 + dk.index = 0; /* ignored when setting default key */
16036 + dk.defaultKeyNum = i;
16037 + memcpy(dk.key, priv->wep_keys[i].key, dk.keySize);
16038 + acx_s_issue_cmd(priv, ACX1xx_CMD_WEP_MGMT, &dk, sizeof(dk));
16044 +acx_s_set_wepkey(wlandevice_t *priv)
16046 + if (IS_ACX111(priv))
16047 + acx111_s_set_wepkey(priv);
16049 + acx100_s_set_wepkey(priv);
16053 +/***********************************************************************
16054 +** acx100_s_init_wep
16056 +** FIXME: this should probably be moved into the new card settings
16057 +** management, but since we're also modifying the memory map layout here
16058 +** due to the WEP key space we want, we should take care...
16061 +acx100_s_init_wep(wlandevice_t *priv)
16064 + acx100_cmd_wep_mgmt_t wep_mgmt; size = 37 bytes */
16065 + acx100_ie_wep_options_t options;
16066 + ie_dot11WEPDefaultKeyID_t dk;
16067 + acx_ie_memmap_t pt;
16068 + int res = NOT_OK;
16072 + if (OK != acx_s_interrogate(priv, &pt, ACX1xx_IE_MEMORY_MAP)) {
16076 + acxlog(L_DEBUG, "CodeEnd:%X\n", pt.CodeEnd);
16078 + pt.WEPCacheStart = cpu_to_le32(le32_to_cpu(pt.CodeEnd) + 0x4);
16079 + pt.WEPCacheEnd = cpu_to_le32(le32_to_cpu(pt.CodeEnd) + 0x4);
16081 + if (OK != acx_s_configure(priv, &pt, ACX1xx_IE_MEMORY_MAP)) {
16085 + /* let's choose maximum setting: 4 default keys, plus 10 other keys: */
16086 + options.NumKeys = cpu_to_le16(DOT11_MAX_DEFAULT_WEP_KEYS + 10);
16087 + options.WEPOption = 0x00;
16089 + acxlog(L_ASSOC, "%s: writing WEP options\n", __func__);
16090 + acx_s_configure(priv, &options, ACX100_IE_WEP_OPTIONS);
16092 + acx100_s_set_wepkey(priv);
16094 + if (priv->wep_keys[priv->wep_current_index].size != 0) {
16095 + acxlog(L_ASSOC, "setting active default WEP key number: %d\n",
16096 + priv->wep_current_index);
16097 + dk.KeyID = priv->wep_current_index;
16098 + acx_s_configure(priv, &dk, ACX1xx_IE_DOT11_WEP_DEFAULT_KEY_SET); /* 0x1010 */
16100 + /* FIXME!!! wep_key_struct is filled nowhere! But priv
16101 + * is initialized to 0, and we don't REALLY need those keys either */
16102 +/* for (i = 0; i < 10; i++) {
16103 + if (priv->wep_key_struct[i].len != 0) {
16104 + MAC_COPY(wep_mgmt.MacAddr, priv->wep_key_struct[i].addr);
16105 + wep_mgmt.KeySize = cpu_to_le16(priv->wep_key_struct[i].len);
16106 + memcpy(&wep_mgmt.Key, priv->wep_key_struct[i].key, le16_to_cpu(wep_mgmt.KeySize));
16107 + wep_mgmt.Action = cpu_to_le16(1);
16108 + acxlog(L_ASSOC, "writing WEP key %d (len %d)\n", i, le16_to_cpu(wep_mgmt.KeySize));
16109 + if (OK == acx_s_issue_cmd(priv, ACX1xx_CMD_WEP_MGMT, &wep_mgmt, sizeof(wep_mgmt))) {
16110 + priv->wep_key_struct[i].index = i;
16115 + /* now retrieve the updated WEPCacheEnd pointer... */
16116 + if (OK != acx_s_interrogate(priv, &pt, ACX1xx_IE_MEMORY_MAP)) {
16117 + printk("%s: ACX1xx_IE_MEMORY_MAP read #2 FAILED\n",
16118 + priv->netdev->name);
16121 + /* ...and tell it to start allocating templates at that location */
16122 + /* (no endianness conversion needed) */
16123 + pt.PacketTemplateStart = pt.WEPCacheEnd;
16125 + if (OK != acx_s_configure(priv, &pt, ACX1xx_IE_MEMORY_MAP)) {
16126 + printk("%s: ACX1xx_IE_MEMORY_MAP write #2 FAILED\n",
16127 + priv->netdev->name);
16138 +/***********************************************************************
16141 +acx_s_init_max_null_data_template(wlandevice_t *priv)
16143 + struct acx_template_nullframe b;
16147 + memset(&b, 0, sizeof(b));
16148 + b.size = cpu_to_le16(sizeof(b) - 2);
16149 + result = acx_s_issue_cmd(priv, ACX1xx_CMD_CONFIG_NULL_DATA, &b, sizeof(b));
16150 + FN_EXIT1(result);
16155 +/***********************************************************************
16156 +** acx_s_init_max_beacon_template
16159 +acx_s_init_max_beacon_template(wlandevice_t *priv)
16161 + struct acx_template_beacon b;
16165 + memset(&b, 0, sizeof(b));
16166 + b.size = cpu_to_le16(sizeof(b) - 2);
16167 + result = acx_s_issue_cmd(priv, ACX1xx_CMD_CONFIG_BEACON, &b, sizeof(b));
16169 + FN_EXIT1(result);
16173 +/***********************************************************************
16174 +** acx_s_init_max_tim_template
16177 +acx_s_init_max_tim_template(wlandevice_t *priv)
16179 + acx_template_tim_t t;
16181 + memset(&t, 0, sizeof(t));
16182 + t.size = cpu_to_le16(sizeof(t) - 2);
16183 + return acx_s_issue_cmd(priv, ACX1xx_CMD_CONFIG_TIM, &t, sizeof(t));
16187 +/***********************************************************************
16188 +** acx_s_init_max_probe_response_template
16191 +acx_s_init_max_probe_response_template(wlandevice_t *priv)
16193 + struct acx_template_proberesp pr;
16195 + memset(&pr, 0, sizeof(pr));
16196 + pr.size = cpu_to_le16(sizeof(pr) - 2);
16198 + return acx_s_issue_cmd(priv, ACX1xx_CMD_CONFIG_PROBE_RESPONSE, &pr, sizeof(pr));
16202 +/***********************************************************************
16203 +** acx_s_init_max_probe_request_template
16206 +acx_s_init_max_probe_request_template(wlandevice_t *priv)
16209 + acx100_template_probereq_t p100;
16210 + acx111_template_probereq_t p111;
16215 + memset(&pr, 0, sizeof(pr));
16216 + pr.p100.size = cpu_to_le16(sizeof(pr) - 2);
16217 + res = acx_s_issue_cmd(priv, ACX1xx_CMD_CONFIG_PROBE_REQUEST, &pr, sizeof(pr));
16223 +/***********************************************************************
16224 +** acx_s_set_tim_template
16226 +** In full blown driver we will regularly update partial virtual bitmap
16227 +** by calling this function
16228 +** (it can be done by irq handler on each DTIM irq or by timer...)
16230 +[802.11 7.3.2.6] TIM information element:
16234 + indicates how many beacons (including this) appear before next DTIM
16235 + (0=this one is a DTIM)
16237 + number of beacons between successive DTIMs
16238 + (0=reserved, 1=all TIMs are DTIMs, 2=every other, etc)
16239 +3 1 Bitmap Control
16240 + bit0: Traffic Indicator bit associated with Assoc ID 0 (Bcast AID?)
16241 + set to 1 in TIM elements with a value of 0 in the DTIM Count field
16242 + when one or more broadcast or multicast frames are buffered at the AP.
16243 + bit1-7: Bitmap Offset (logically Bitmap_Offset = Bitmap_Control & 0xFE).
16244 +4 n Partial Virtual Bitmap
16245 + Visible part of traffic-indication bitmap.
16246 + Full bitmap consists of 2008 bits (251 octets) such that bit number N
16247 + (0<=N<=2007) in the bitmap corresponds to bit number (N mod 8)
16248 + in octet number N/8 where the low-order bit of each octet is bit0,
16249 + and the high order bit is bit7.
16250 + Each set bit in virtual bitmap corresponds to traffic buffered by AP
16251 + for a specific station (with corresponding AID?).
16252 + Partial Virtual Bitmap shows a part of bitmap which has non-zero.
16253 + Bitmap Offset is a number of skipped zero octets (see above).
16254 + 'Missing' octets at the tail are also assumed to be zero.
16255 + Example: Length=6, Bitmap_Offset=2, Partial_Virtual_Bitmap=55 55 55
16256 + This means that traffic-indication bitmap is:
16257 + 00000000 00000000 01010101 01010101 01010101 00000000 00000000...
16258 + (is bit0 in the map is always 0 and real value is in Bitmap Control bit0?)
16261 +acx_s_set_tim_template(wlandevice_t *priv)
16263 +/* For now, configure smallish test bitmap, all zero ("no pending data") */
16264 + enum { bitmap_size = 5 };
16266 + acx_template_tim_t t;
16271 + memset(&t, 0, sizeof(t));
16272 + t.size = 5 + bitmap_size; /* eid+len+count+period+bmap_ctrl + bmap */
16273 + t.tim_eid = WLAN_EID_TIM;
16274 + t.len = 3 + bitmap_size; /* count+period+bmap_ctrl + bmap */
16275 + result = acx_s_issue_cmd(priv, ACX1xx_CMD_CONFIG_TIM, &t, sizeof(t));
16276 + FN_EXIT1(result);
16281 +/***********************************************************************
16282 +** acx_fill_beacon_or_proberesp_template
16284 +** For frame format info, please see 802.11-1999.pdf item 7.2.3.9 and below!!
16286 +** NB: we use the fact that
16287 +** struct acx_template_proberesp and struct acx_template_beacon are the same
16288 +** (well, almost...)
16290 +** [802.11] Beacon's body consist of these IEs:
16292 +** 2 Beacon interval
16293 +** 3 Capability information
16295 +** 5 Supported rates (up to 8 rates)
16296 +** 6 FH Parameter Set (frequency-hopping PHYs only)
16297 +** 7 DS Parameter Set (direct sequence PHYs only)
16298 +** 8 CF Parameter Set (only if PCF is supported)
16299 +** 9 IBSS Parameter Set (ad-hoc only)
16302 +** 10 TIM (AP only) (see 802.11 7.3.2.6)
16303 +** 11 Country Information (802.11d)
16304 +** 12 FH Parameters (802.11d)
16305 +** 13 FH Pattern Table (802.11d)
16306 +** ... (?!! did not yet find relevant PDF file... --vda)
16307 +** 19 ERP Information (extended rate PHYs)
16308 +** 20 Extended Supported Rates (if more than 8 rates)
16310 +** Proberesp only:
16311 +** 10 Country information (802.11d)
16312 +** 11 FH Parameters (802.11d)
16313 +** 12 FH Pattern Table (802.11d)
16314 +** 13-n Requested information elements (802.11d)
16316 +** 18 ERP Information (extended rate PHYs)
16317 +** 19 Extended Supported Rates (if more than 8 rates)
16320 +acx_fill_beacon_or_proberesp_template(wlandevice_t *priv,
16321 + struct acx_template_beacon *templ,
16322 + u16 fc /* in host order! */)
16329 + memset(templ, 0, sizeof(*templ));
16330 + MAC_BCAST(templ->da);
16331 + MAC_COPY(templ->sa, priv->dev_addr);
16332 + MAC_COPY(templ->bssid, priv->bssid);
16334 + templ->beacon_interval = cpu_to_le16(priv->beacon_interval);
16335 + acx_update_capabilities(priv);
16336 + templ->cap = cpu_to_le16(priv->capabilities);
16338 + p = templ->variable;
16339 + p = wlan_fill_ie_ssid(p, priv->essid_len, priv->essid);
16340 + p = wlan_fill_ie_rates(p, priv->rate_supported_len, priv->rate_supported);
16341 + p = wlan_fill_ie_ds_parms(p, priv->channel);
16342 + /* NB: should go AFTER tim, but acx seem to keep tim last always */
16343 + p = wlan_fill_ie_rates_ext(p, priv->rate_supported_len, priv->rate_supported);
16345 + switch (priv->mode) {
16346 + case ACX_MODE_0_ADHOC:
16347 + /* ATIM window */
16348 + p = wlan_fill_ie_ibss_parms(p, 0); break;
16349 + case ACX_MODE_3_AP:
16350 + /* TIM IE is set up as separate template */
16354 + len = p - (u8*)templ;
16355 + templ->fc = cpu_to_le16(WF_FTYPE_MGMT | fc);
16356 + /* - 2: do not count 'u16 size' field */
16357 + templ->size = cpu_to_le16(len - 2);
16364 +/***********************************************************************
16365 +** acx_s_set_beacon_template
16368 +acx_s_set_beacon_template(wlandevice_t *priv)
16370 + struct acx_template_beacon bcn;
16375 + len = acx_fill_beacon_or_proberesp_template(priv, &bcn, WF_FSTYPE_BEACON);
16376 + result = acx_s_issue_cmd(priv, ACX1xx_CMD_CONFIG_BEACON, &bcn, len);
16378 + FN_EXIT1(result);
16383 +/***********************************************************************
16384 +** acx_s_set_probe_response_template
16387 +acx_s_set_probe_response_template(wlandevice_t *priv)
16389 + struct acx_template_proberesp pr;
16394 + len = acx_fill_beacon_or_proberesp_template(priv, &pr, WF_FSTYPE_PROBERESP);
16395 + result = acx_s_issue_cmd(priv, ACX1xx_CMD_CONFIG_PROBE_RESPONSE, &pr, len);
16397 + FN_EXIT1(result);
16402 +/***********************************************************************
16403 +** acx100_s_init_packet_templates()
16405 +** NOTE: order is very important here, to have a correct memory layout!
16406 +** init templates: max Probe Request (station mode), max NULL data,
16407 +** max Beacon, max TIM, max Probe Response.
16410 +acx100_s_init_packet_templates(wlandevice_t *priv)
16412 + acx_ie_memmap_t mm;
16413 + int result = NOT_OK;
16417 + acxlog(L_DEBUG, "sizeof(memmap)=%d bytes\n", (int)sizeof(mm));
16419 + /* acx100 still do not emit probe requests, thus this call
16420 + ** is sourt of not needed. But we want it to work someday */
16421 + if (OK != acx_s_init_max_probe_request_template(priv))
16424 +#ifdef NOT_WORKING_YET
16425 + /* FIXME: creating the NULL data template breaks
16426 + * communication right now, needs further testing.
16427 + * Also, need to set the template once we're joining a network. */
16428 + if (OK != acx_s_init_max_null_data_template(priv))
16432 + if (OK != acx_s_init_max_beacon_template(priv))
16435 + if (OK != acx_s_init_max_tim_template(priv))
16438 + if (OK != acx_s_init_max_probe_response_template(priv))
16441 + if (OK != acx_s_set_tim_template(priv))
16444 + if (OK != acx_s_interrogate(priv, &mm, ACX1xx_IE_MEMORY_MAP)) {
16448 + mm.QueueStart = cpu_to_le32(le32_to_cpu(mm.PacketTemplateEnd) + 4);
16449 + if (OK != acx_s_configure(priv, &mm, ACX1xx_IE_MEMORY_MAP)) {
16457 + acxlog(L_DEBUG|L_INIT,
16458 + /* "cb=0x%X\n" */
16459 + "pACXMemoryMap:\n"
16460 + ".CodeStart=0x%X\n"
16461 + ".CodeEnd=0x%X\n"
16462 + ".WEPCacheStart=0x%X\n"
16463 + ".WEPCacheEnd=0x%X\n"
16464 + ".PacketTemplateStart=0x%X\n"
16465 + ".PacketTemplateEnd=0x%X\n",
16467 + le32_to_cpu(mm.CodeStart),
16468 + le32_to_cpu(mm.CodeEnd),
16469 + le32_to_cpu(mm.WEPCacheStart),
16470 + le32_to_cpu(mm.WEPCacheEnd),
16471 + le32_to_cpu(mm.PacketTemplateStart),
16472 + le32_to_cpu(mm.PacketTemplateEnd));
16475 + FN_EXIT1(result);
16480 +acx111_s_init_packet_templates(wlandevice_t *priv)
16482 + int result = NOT_OK;
16486 + acxlog(L_DEBUG|L_INIT, "initializing max packet templates\n");
16488 + if (OK != acx_s_init_max_probe_request_template(priv))
16491 + if (OK != acx_s_init_max_null_data_template(priv))
16494 + if (OK != acx_s_init_max_beacon_template(priv))
16497 + if (OK != acx_s_init_max_tim_template(priv))
16500 + if (OK != acx_s_init_max_probe_response_template(priv))
16503 + /* the other templates will be set later (acx_start) */
16505 + if (OK != acx_s_set_tim_template(priv))
16512 + printk("%s: acx111_init_packet_templates() FAILED\n", priv->netdev->name);
16515 + FN_EXIT1(result);
16520 +/***********************************************************************
16523 +acx100_s_set_probe_request_template(wlandevice_t *priv)
16525 + struct acx100_template_probereq probereq;
16532 + memset(&probereq, 0, sizeof(probereq));
16534 + probereq.fc = WF_FTYPE_MGMTi | WF_FSTYPE_PROBEREQi;
16535 + MAC_BCAST(probereq.da);
16536 + MAC_COPY(probereq.sa, priv->dev_addr);
16537 + MAC_BCAST(probereq.bssid);
16539 + probereq.beacon_interval = cpu_to_le16(priv->beacon_interval);
16540 + acx_update_capabilities(priv);
16541 + probereq.cap = cpu_to_le16(priv->capabilities);
16543 + p = probereq.variable;
16544 + acxlog(L_ASSOC, "SSID='%s' len=%d\n", priv->essid, priv->essid_len);
16545 + p = wlan_fill_ie_ssid(p, priv->essid_len, priv->essid);
16546 + p = wlan_fill_ie_rates(p, priv->rate_supported_len, priv->rate_supported);
16547 + /* FIXME: should these be here or AFTER ds_parms? */
16548 + p = wlan_fill_ie_rates_ext(p, priv->rate_supported_len, priv->rate_supported);
16549 + /* HUH?? who said it must be here? I've found nothing in 802.11! --vda*/
16550 + /* p = wlan_fill_ie_ds_parms(p, priv->channel); */
16551 + frame_len = p - (char*)&probereq;
16552 + probereq.size = frame_len - 2;
16554 + res = acx_s_issue_cmd(priv, ACX1xx_CMD_CONFIG_PROBE_REQUEST, &probereq, frame_len);
16560 +acx111_s_set_probe_request_template(wlandevice_t *priv)
16562 + struct acx111_template_probereq probereq;
16569 + memset(&probereq, 0, sizeof(probereq));
16571 + probereq.fc = WF_FTYPE_MGMTi | WF_FSTYPE_PROBEREQi;
16572 + MAC_BCAST(probereq.da);
16573 + MAC_COPY(probereq.sa, priv->dev_addr);
16574 + MAC_BCAST(probereq.bssid);
16576 + p = probereq.variable;
16577 + p = wlan_fill_ie_ssid(p, priv->essid_len, priv->essid);
16578 + p = wlan_fill_ie_rates(p, priv->rate_supported_len, priv->rate_supported);
16579 + p = wlan_fill_ie_rates_ext(p, priv->rate_supported_len, priv->rate_supported);
16580 + frame_len = p - (char*)&probereq;
16581 + probereq.size = frame_len - 2;
16583 + res = acx_s_issue_cmd(priv, ACX1xx_CMD_CONFIG_PROBE_REQUEST, &probereq, frame_len);
16589 +acx_s_set_probe_request_template(wlandevice_t *priv)
16591 + if (IS_ACX111(priv)) {
16592 + return acx111_s_set_probe_request_template(priv);
16594 + return acx100_s_set_probe_request_template(priv);
16599 +/***********************************************************************
16600 +** acx_s_update_card_settings
16602 +** Applies accumulated changes in various priv->xxxx members
16603 +** Called by ioctl commit handler, acx_start, acx_set_defaults,
16604 +** acx_s_after_interrupt_task (if IRQ_CMD_UPDATE_CARD_CFG),
16607 +acx111_s_sens_radio_16_17(wlandevice_t *priv)
16609 + u32 feature1, feature2;
16611 + if ((priv->sensitivity < 1) || (priv->sensitivity > 3)) {
16612 + printk("%s: invalid sensitivity setting (1..3), "
16613 + "setting to 1\n", priv->netdev->name);
16614 + priv->sensitivity = 1;
16616 + acx111_s_get_feature_config(priv, &feature1, &feature2);
16617 + CLEAR_BIT(feature1, FEATURE1_LOW_RX|FEATURE1_EXTRA_LOW_RX);
16618 + if (priv->sensitivity > 1)
16619 + SET_BIT(feature1, FEATURE1_LOW_RX);
16620 + if (priv->sensitivity > 2)
16621 + SET_BIT(feature1, FEATURE1_EXTRA_LOW_RX);
16622 + acx111_s_feature_set(priv, feature1, feature2);
16626 +acx_s_update_card_settings(wlandevice_t *priv, int get_all, int set_all)
16628 + unsigned long flags;
16629 + unsigned int start_scan = 0;
16635 + SET_BIT(priv->get_mask, GETSET_ALL);
16637 + SET_BIT(priv->set_mask, GETSET_ALL);
16638 + /* Why not just set masks to 0xffffffff? We can get rid of GETSET_ALL */
16640 + acxlog(L_INIT, "get_mask 0x%08X, set_mask 0x%08X\n",
16641 + priv->get_mask, priv->set_mask);
16643 + /* Track dependencies betweed various settings */
16645 + if (priv->set_mask & (GETSET_MODE|GETSET_RESCAN|GETSET_WEP)) {
16646 + acxlog(L_INIT, "important setting has been changed. "
16647 + "Need to update packet templates, too\n");
16648 + SET_BIT(priv->set_mask, SET_TEMPLATES);
16650 + if (priv->set_mask & (GETSET_CHANNEL|GETSET_ALL)) {
16651 + /* This will actually tune RX/TX to the channel */
16652 + SET_BIT(priv->set_mask, GETSET_RX|GETSET_TX);
16653 + switch (priv->mode) {
16654 + case ACX_MODE_0_ADHOC:
16655 + case ACX_MODE_3_AP:
16656 + /* Beacons contain channel# - update them */
16657 + SET_BIT(priv->set_mask, SET_TEMPLATES);
16659 + switch (priv->mode) {
16660 + case ACX_MODE_0_ADHOC:
16661 + case ACX_MODE_2_STA:
16666 + /* Apply settings */
16668 +#ifdef WHY_SHOULD_WE_BOTHER /* imagine we were just powered off */
16669 + /* send a disassoc request in case it's required */
16670 + if (priv->set_mask & (GETSET_MODE|GETSET_RESCAN|GETSET_CHANNEL|GETSET_WEP|GETSET_ALL)) {
16671 + if (ACX_MODE_2_STA == priv->mode) {
16672 + if (ACX_STATUS_4_ASSOCIATED == priv->status) {
16673 + acxlog(L_ASSOC, "we were ASSOCIATED - "
16674 + "sending disassoc request\n");
16675 + acx_lock(priv, flags);
16676 + acx_l_transmit_disassoc(priv, NULL);
16677 + /* FIXME: deauth? */
16678 + acx_unlock(priv, flags);
16680 + /* need to reset some other stuff as well */
16681 + acxlog(L_DEBUG, "resetting bssid\n");
16682 + MAC_ZERO(priv->bssid);
16683 + SET_BIT(priv->set_mask, SET_TEMPLATES|SET_STA_LIST);
16684 + /* FIXME: should start scanning */
16690 + if (priv->get_mask & (GETSET_STATION_ID|GETSET_ALL)) {
16691 + u8 stationID[4 + ACX1xx_IE_DOT11_STATION_ID_LEN];
16694 + acx_s_interrogate(priv, stationID, ACX1xx_IE_DOT11_STATION_ID);
16695 + paddr = &stationID[4];
16696 + for (i = 0; i < ETH_ALEN; i++) {
16697 + /* we copy the MAC address (reversed in
16698 + * the card) to the netdevice's MAC
16699 + * address, and on ifup it will be
16700 + * copied into iwpriv->dev_addr */
16701 + priv->netdev->dev_addr[ETH_ALEN - 1 - i] = paddr[i];
16703 + CLEAR_BIT(priv->get_mask, GETSET_STATION_ID);
16706 + if (priv->get_mask & (GETSET_SENSITIVITY|GETSET_ALL)) {
16707 + if ((RADIO_RFMD_11 == priv->radio_type)
16708 + || (RADIO_MAXIM_0D == priv->radio_type)
16709 + || (RADIO_RALINK_15 == priv->radio_type)) {
16710 + acx_s_read_phy_reg(priv, 0x30, &priv->sensitivity);
16712 + acxlog(L_INIT, "don't know how to get sensitivity "
16713 + "for radio type 0x%02X\n", priv->radio_type);
16714 + priv->sensitivity = 0;
16716 + acxlog(L_INIT, "got sensitivity value %u\n", priv->sensitivity);
16718 + CLEAR_BIT(priv->get_mask, GETSET_SENSITIVITY);
16721 + if (priv->get_mask & (GETSET_ANTENNA|GETSET_ALL)) {
16722 + u8 antenna[4 + ACX1xx_IE_DOT11_CURRENT_ANTENNA_LEN];
16724 + memset(antenna, 0, sizeof(antenna));
16725 + acx_s_interrogate(priv, antenna, ACX1xx_IE_DOT11_CURRENT_ANTENNA);
16726 + priv->antenna = antenna[4];
16727 + acxlog(L_INIT, "got antenna value 0x%02X\n", priv->antenna);
16728 + CLEAR_BIT(priv->get_mask, GETSET_ANTENNA);
16731 + if (priv->get_mask & (GETSET_ED_THRESH|GETSET_ALL)) {
16732 + if (IS_ACX100(priv)) {
16733 + u8 ed_threshold[4 + ACX100_IE_DOT11_ED_THRESHOLD_LEN];
16735 + memset(ed_threshold, 0, sizeof(ed_threshold));
16736 + acx_s_interrogate(priv, ed_threshold, ACX100_IE_DOT11_ED_THRESHOLD);
16737 + priv->ed_threshold = ed_threshold[4];
16739 + acxlog(L_INIT, "acx111 doesn't support ED\n");
16740 + priv->ed_threshold = 0;
16742 + acxlog(L_INIT, "got Energy Detect (ED) threshold %u\n", priv->ed_threshold);
16743 + CLEAR_BIT(priv->get_mask, GETSET_ED_THRESH);
16746 + if (priv->get_mask & (GETSET_CCA|GETSET_ALL)) {
16747 + if (IS_ACX100(priv)) {
16748 + u8 cca[4 + ACX1xx_IE_DOT11_CURRENT_CCA_MODE_LEN];
16750 + memset(cca, 0, sizeof(priv->cca));
16751 + acx_s_interrogate(priv, cca, ACX1xx_IE_DOT11_CURRENT_CCA_MODE);
16752 + priv->cca = cca[4];
16754 + acxlog(L_INIT, "acx111 doesn't support CCA\n");
16757 + acxlog(L_INIT, "got Channel Clear Assessment (CCA) value %u\n", priv->cca);
16758 + CLEAR_BIT(priv->get_mask, GETSET_CCA);
16761 + if (priv->get_mask & (GETSET_REG_DOMAIN|GETSET_ALL)) {
16762 + acx_ie_generic_t dom;
16764 + acx_s_interrogate(priv, &dom, ACX1xx_IE_DOT11_CURRENT_REG_DOMAIN);
16765 + priv->reg_dom_id = dom.m.bytes[0];
16766 + /* FIXME: should also set chanmask somehow */
16767 + acxlog(L_INIT, "got regulatory domain 0x%02X\n", priv->reg_dom_id);
16768 + CLEAR_BIT(priv->get_mask, GETSET_REG_DOMAIN);
16771 + if (priv->set_mask & (GETSET_STATION_ID|GETSET_ALL)) {
16772 + u8 stationID[4 + ACX1xx_IE_DOT11_STATION_ID_LEN];
16775 + paddr = &stationID[4];
16776 + for (i = 0; i < ETH_ALEN; i++) {
16777 + /* copy the MAC address we obtained when we noticed
16778 + * that the ethernet iface's MAC changed
16779 + * to the card (reversed in
16781 + paddr[i] = priv->dev_addr[ETH_ALEN - 1 - i];
16783 + acx_s_configure(priv, &stationID, ACX1xx_IE_DOT11_STATION_ID);
16784 + CLEAR_BIT(priv->set_mask, GETSET_STATION_ID);
16787 + if (priv->set_mask & (SET_TEMPLATES|GETSET_ALL)) {
16788 + acxlog(L_INIT, "updating packet templates\n");
16789 + /* Doesn't work for acx100, do it only for acx111 for now */
16790 + if (IS_ACX111(priv)) {
16791 + switch (priv->mode) {
16792 + case ACX_MODE_0_ADHOC:
16793 + case ACX_MODE_2_STA:
16794 + acx_s_set_probe_request_template(priv);
16797 + switch (priv->mode) {
16798 + case ACX_MODE_0_ADHOC:
16799 + case ACX_MODE_3_AP:
16800 + /* FIXME: why only for AP? STA need probe req templates... */
16801 + acx_s_set_beacon_template(priv);
16802 + acx_s_set_tim_template(priv);
16803 + /* BTW acx111 firmware would not send probe responses
16804 + ** if probe request does not have all basic rates flagged
16805 + ** by 0x80! Thus firmware does not conform to 802.11,
16806 + ** it should ignore 0x80 bit in ratevector from STA.
16807 + ** We can 'fix' it by not using this template and
16808 + ** sending probe responses by hand. TODO --vda */
16809 + acx_s_set_probe_response_template(priv);
16811 + /* Needed if generated frames are to be emitted at different tx rate now */
16812 + acxlog(L_IRQ, "redoing cmd_join_bssid() after template cfg\n");
16813 + acx_s_cmd_join_bssid(priv, priv->bssid);
16814 + CLEAR_BIT(priv->set_mask, SET_TEMPLATES);
16816 + if (priv->set_mask & (SET_STA_LIST|GETSET_ALL)) {
16817 + acx_lock(priv, flags);
16818 + acx_l_sta_list_init(priv);
16819 + CLEAR_BIT(priv->set_mask, SET_STA_LIST);
16820 + acx_unlock(priv, flags);
16822 + if (priv->set_mask & (SET_RATE_FALLBACK|GETSET_ALL)) {
16823 + u8 rate[4 + ACX1xx_IE_RATE_FALLBACK_LEN];
16825 + /* configure to not do fallbacks when not in auto rate mode */
16826 + rate[4] = (priv->rate_auto) ? /* priv->txrate_fallback_retries */ 1 : 0;
16827 + acxlog(L_INIT, "updating Tx fallback to %u retries\n", rate[4]);
16828 + acx_s_configure(priv, &rate, ACX1xx_IE_RATE_FALLBACK);
16829 + CLEAR_BIT(priv->set_mask, SET_RATE_FALLBACK);
16831 + if (priv->set_mask & (GETSET_TXPOWER|GETSET_ALL)) {
16832 + acxlog(L_INIT, "updating transmit power: %u dBm\n",
16833 + priv->tx_level_dbm);
16834 + acx_s_set_tx_level(priv, priv->tx_level_dbm);
16835 + CLEAR_BIT(priv->set_mask, GETSET_TXPOWER);
16838 + if (priv->set_mask & (GETSET_SENSITIVITY|GETSET_ALL)) {
16839 + acxlog(L_INIT, "updating sensitivity value: %u\n",
16840 + priv->sensitivity);
16841 + switch (priv->radio_type) {
16842 + case RADIO_RFMD_11:
16843 + case RADIO_MAXIM_0D:
16844 + case RADIO_RALINK_15:
16845 + acx_s_write_phy_reg(priv, 0x30, priv->sensitivity);
16847 + case RADIO_RADIA_16:
16848 + case RADIO_UNKNOWN_17:
16849 + acx111_s_sens_radio_16_17(priv);
16852 + acxlog(L_INIT, "don't know how to modify sensitivity "
16853 + "for radio type 0x%02X\n", priv->radio_type);
16855 + CLEAR_BIT(priv->set_mask, GETSET_SENSITIVITY);
16858 + if (priv->set_mask & (GETSET_ANTENNA|GETSET_ALL)) {
16860 + u8 antenna[4 + ACX1xx_IE_DOT11_CURRENT_ANTENNA_LEN];
16862 + memset(antenna, 0, sizeof(antenna));
16863 + antenna[4] = priv->antenna;
16864 + acxlog(L_INIT, "updating antenna value: 0x%02X\n",
16866 + acx_s_configure(priv, &antenna, ACX1xx_IE_DOT11_CURRENT_ANTENNA);
16867 + CLEAR_BIT(priv->set_mask, GETSET_ANTENNA);
16870 + if (priv->set_mask & (GETSET_ED_THRESH|GETSET_ALL)) {
16871 + /* ed_threshold */
16872 + acxlog(L_INIT, "updating Energy Detect (ED) threshold: %u\n",
16873 + priv->ed_threshold);
16874 + if (IS_ACX100(priv)) {
16875 + u8 ed_threshold[4 + ACX100_IE_DOT11_ED_THRESHOLD_LEN];
16877 + memset(ed_threshold, 0, sizeof(ed_threshold));
16878 + ed_threshold[4] = priv->ed_threshold;
16879 + acx_s_configure(priv, &ed_threshold, ACX100_IE_DOT11_ED_THRESHOLD);
16882 + acxlog(L_INIT, "acx111 doesn't support ED!\n");
16883 + CLEAR_BIT(priv->set_mask, GETSET_ED_THRESH);
16886 + if (priv->set_mask & (GETSET_CCA|GETSET_ALL)) {
16888 + acxlog(L_INIT, "updating Channel Clear Assessment "
16889 + "(CCA) value: 0x%02X\n", priv->cca);
16890 + if (IS_ACX100(priv)) {
16891 + u8 cca[4 + ACX1xx_IE_DOT11_CURRENT_CCA_MODE_LEN];
16893 + memset(cca, 0, sizeof(cca));
16894 + cca[4] = priv->cca;
16895 + acx_s_configure(priv, &cca, ACX1xx_IE_DOT11_CURRENT_CCA_MODE);
16898 + acxlog(L_INIT, "acx111 doesn't support CCA!\n");
16899 + CLEAR_BIT(priv->set_mask, GETSET_CCA);
16902 + if (priv->set_mask & (GETSET_LED_POWER|GETSET_ALL)) {
16904 + acxlog(L_INIT, "updating power LED status: %u\n", priv->led_power);
16906 + acx_lock(priv, flags);
16907 + if (IS_PCI(priv))
16908 + acx_l_power_led(priv, priv->led_power);
16909 + CLEAR_BIT(priv->set_mask, GETSET_LED_POWER);
16910 + acx_unlock(priv, flags);
16913 +/* this seems to cause Tx lockup after some random time (Tx error 0x20),
16914 + * so let's disable it for now until further investigation */
16915 +/* Maybe fixed now after locking is fixed. Need to retest */
16916 +#ifdef POWER_SAVE_80211
16917 + if (priv->set_mask & (GETSET_POWER_80211|GETSET_ALL)) {
16918 + acx100_ie_powermgmt_t pm;
16920 + /* change 802.11 power save mode settings */
16921 + acxlog(L_INIT, "updating 802.11 power save mode settings: "
16922 + "wakeup_cfg 0x%02X, listen interval %u, "
16923 + "options 0x%02X, hangover period %u, "
16924 + "enhanced_ps_transition_time %d\n",
16925 + priv->ps_wakeup_cfg, priv->ps_listen_interval,
16926 + priv->ps_options, priv->ps_hangover_period,
16927 + priv->ps_enhanced_transition_time);
16928 + acx_s_interrogate(priv, &pm, ACX100_IE_POWER_MGMT);
16929 + acxlog(L_INIT, "Previous PS mode settings: wakeup_cfg 0x%02X, "
16930 + "listen interval %u, options 0x%02X, "
16931 + "hangover period %u, "
16932 + "enhanced_ps_transition_time %d\n",
16933 + pm.wakeup_cfg, pm.listen_interval, pm.options,
16934 + pm.hangover_period, pm.enhanced_ps_transition_time);
16935 + pm.wakeup_cfg = priv->ps_wakeup_cfg;
16936 + pm.listen_interval = priv->ps_listen_interval;
16937 + pm.options = priv->ps_options;
16938 + pm.hangover_period = priv->ps_hangover_period;
16939 + pm.enhanced_ps_transition_time = cpu_to_le16(priv->ps_enhanced_transition_time);
16940 + acx_s_configure(priv, &pm, ACX100_IE_POWER_MGMT);
16941 + acx_s_interrogate(priv, &pm, ACX100_IE_POWER_MGMT);
16942 + acxlog(L_INIT, "wakeup_cfg: 0x%02X\n", pm.wakeup_cfg);
16943 + acx_s_msleep(40);
16944 + acx_s_interrogate(priv, &pm, ACX100_IE_POWER_MGMT);
16945 + acxlog(L_INIT, "power save mode change %s\n",
16946 + (pm.wakeup_cfg & PS_CFG_PENDING) ? "FAILED" : "was successful");
16947 + /* FIXME: maybe verify via PS_CFG_PENDING bit here
16948 + * that power save mode change was successful. */
16949 + /* FIXME: we shouldn't trigger a scan immediately after
16950 + * fiddling with power save mode (since the firmware is sending
16951 + * a NULL frame then). Does this need locking?? */
16952 + CLEAR_BIT(priv->set_mask, GETSET_POWER_80211);
16956 + if (priv->set_mask & (GETSET_CHANNEL|GETSET_ALL)) {
16958 + acxlog(L_INIT, "updating channel to: %u\n", priv->channel);
16959 + CLEAR_BIT(priv->set_mask, GETSET_CHANNEL);
16962 + if (priv->set_mask & (GETSET_TX|GETSET_ALL)) {
16964 + acxlog(L_INIT, "updating: %s Tx\n",
16965 + priv->tx_disabled ? "disable" : "enable");
16966 + if (priv->tx_disabled)
16967 + acx_s_issue_cmd(priv, ACX1xx_CMD_DISABLE_TX, NULL, 0);
16969 + /* FIXME: this used to be 1, but since we don't transfer a parameter... */
16971 + acx_s_issue_cmd(priv, ACX1xx_CMD_ENABLE_TX, &(priv->channel), 1);
16972 + CLEAR_BIT(priv->set_mask, GETSET_TX);
16975 + if (priv->set_mask & (GETSET_RX|GETSET_ALL)) {
16977 + acxlog(L_INIT, "updating: enable Rx on channel: %u\n",
16979 + acx_s_issue_cmd(priv, ACX1xx_CMD_ENABLE_RX, &(priv->channel), 1);
16980 + CLEAR_BIT(priv->set_mask, GETSET_RX);
16983 + if (priv->set_mask & (GETSET_RETRY|GETSET_ALL)) {
16984 + u8 short_retry[4 + ACX1xx_IE_DOT11_SHORT_RETRY_LIMIT_LEN];
16985 + u8 long_retry[4 + ACX1xx_IE_DOT11_LONG_RETRY_LIMIT_LEN];
16987 + acxlog(L_INIT, "updating short retry limit: %u, long retry limit: %u\n",
16988 + priv->short_retry, priv->long_retry);
16989 + short_retry[0x4] = priv->short_retry;
16990 + long_retry[0x4] = priv->long_retry;
16991 + acx_s_configure(priv, &short_retry, ACX1xx_IE_DOT11_SHORT_RETRY_LIMIT);
16992 + acx_s_configure(priv, &long_retry, ACX1xx_IE_DOT11_LONG_RETRY_LIMIT);
16993 + CLEAR_BIT(priv->set_mask, GETSET_RETRY);
16996 + if (priv->set_mask & (SET_MSDU_LIFETIME|GETSET_ALL)) {
16997 + u8 xmt_msdu_lifetime[4 + ACX1xx_IE_DOT11_MAX_XMIT_MSDU_LIFETIME_LEN];
16999 + acxlog(L_INIT, "updating tx MSDU lifetime: %u\n",
17000 + priv->msdu_lifetime);
17001 + *(u32 *)&xmt_msdu_lifetime[4] = cpu_to_le32((u32)priv->msdu_lifetime);
17002 + acx_s_configure(priv, &xmt_msdu_lifetime, ACX1xx_IE_DOT11_MAX_XMIT_MSDU_LIFETIME);
17003 + CLEAR_BIT(priv->set_mask, SET_MSDU_LIFETIME);
17006 + if (priv->set_mask & (GETSET_REG_DOMAIN|GETSET_ALL)) {
17008 + acx_ie_generic_t dom;
17011 + acxlog(L_INIT, "updating regulatory domain: 0x%02X\n",
17012 + priv->reg_dom_id);
17013 + for (i = 0; i < sizeof(reg_domain_ids); i++)
17014 + if (reg_domain_ids[i] == priv->reg_dom_id)
17017 + if (sizeof(reg_domain_ids) == i) {
17018 + acxlog(L_INIT, "Invalid or unsupported regulatory "
17019 + "domain 0x%02X specified, falling back to "
17020 + "FCC (USA)! Please report if this sounds "
17021 + "fishy!\n", priv->reg_dom_id);
17023 + priv->reg_dom_id = reg_domain_ids[i];
17026 + priv->reg_dom_chanmask = reg_domain_channel_masks[i];
17027 + dom.m.bytes[0] = priv->reg_dom_id;
17028 + acx_s_configure(priv, &dom, ACX1xx_IE_DOT11_CURRENT_REG_DOMAIN);
17030 + mask = (1 << (priv->channel - 1));
17031 + if (!(priv->reg_dom_chanmask & mask)) {
17032 + /* hmm, need to adjust our channel to reside within domain */
17034 + for (i = 1; i <= 14; i++) {
17035 + if (priv->reg_dom_chanmask & mask) {
17036 + printk("%s: adjusting "
17037 + "selected channel from %d "
17038 + "to %d due to new regulatory "
17039 + "domain\n", priv->netdev->name,
17040 + priv->channel, i);
17041 + priv->channel = i;
17047 + CLEAR_BIT(priv->set_mask, GETSET_REG_DOMAIN);
17050 + if (priv->set_mask & (GETSET_MODE|GETSET_ALL)) {
17051 + priv->netdev->type = ARPHRD_ETHER;
17053 + switch (priv->mode) {
17054 + case ACX_MODE_3_AP:
17056 + acx_lock(priv, flags);
17057 + acx_l_sta_list_init(priv);
17059 + priv->ap_client = NULL;
17060 + MAC_COPY(priv->bssid, priv->dev_addr);
17061 + /* this basically says "we're connected" */
17062 + acx_set_status(priv, ACX_STATUS_4_ASSOCIATED);
17063 + acx_unlock(priv, flags);
17065 + acx111_s_feature_off(priv, 0, FEATURE2_NO_TXCRYPT|FEATURE2_SNIFFER);
17066 + /* start sending beacons */
17067 + acx_s_cmd_join_bssid(priv, priv->bssid);
17069 + case ACX_MODE_MONITOR:
17070 + /* priv->netdev->type = ARPHRD_ETHER; */
17071 + /* priv->netdev->type = ARPHRD_IEEE80211; */
17072 + priv->netdev->type = ARPHRD_IEEE80211_PRISM;
17073 + acx111_s_feature_on(priv, 0, FEATURE2_NO_TXCRYPT|FEATURE2_SNIFFER);
17074 + /* this stops beacons */
17075 + acx_s_cmd_join_bssid(priv, priv->bssid);
17076 + /* this basically says "we're connected" */
17077 + acx_set_status(priv, ACX_STATUS_4_ASSOCIATED);
17078 + SET_BIT(priv->set_mask, SET_RXCONFIG|SET_WEP_OPTIONS);
17080 + case ACX_MODE_0_ADHOC:
17081 + case ACX_MODE_2_STA:
17082 + acx111_s_feature_off(priv, 0, FEATURE2_NO_TXCRYPT|FEATURE2_SNIFFER);
17084 + priv->ap_client = NULL;
17085 + /* we want to start looking for peer or AP */
17088 + case ACX_MODE_OFF:
17089 + /* TODO: disable RX/TX, stop any scanning activity etc: */
17090 + /* priv->tx_disabled = 1; */
17091 + /* SET_BIT(priv->set_mask, GETSET_RX|GETSET_TX); */
17093 + /* This stops beacons (invalid macmode...) */
17094 + acx_s_cmd_join_bssid(priv, priv->bssid);
17095 + acx_set_status(priv, ACX_STATUS_0_STOPPED);
17098 + CLEAR_BIT(priv->set_mask, GETSET_MODE);
17101 + if (priv->set_mask & (SET_RXCONFIG|GETSET_ALL)) {
17102 + acx_s_initialize_rx_config(priv);
17103 + CLEAR_BIT(priv->set_mask, SET_RXCONFIG);
17106 + if (priv->set_mask & (GETSET_RESCAN|GETSET_ALL)) {
17107 + switch (priv->mode) {
17108 + case ACX_MODE_0_ADHOC:
17109 + case ACX_MODE_2_STA:
17113 + CLEAR_BIT(priv->set_mask, GETSET_RESCAN);
17116 + if (priv->set_mask & (GETSET_WEP|GETSET_ALL)) {
17119 + ie_dot11WEPDefaultKeyID_t dkey;
17122 + u16 type ACX_PACKED;
17123 + u16 len ACX_PACKED;
17124 + u8 val ACX_PACKED;
17127 + acxlog(L_INIT, "updating WEP key settings\n");
17129 + acx_s_set_wepkey(priv);
17131 + dkey.KeyID = priv->wep_current_index;
17132 + acxlog(L_INIT, "setting WEP key %u as default\n", dkey.KeyID);
17133 + acx_s_configure(priv, &dkey, ACX1xx_IE_DOT11_WEP_DEFAULT_KEY_SET);
17135 + keyindic.val = 3;
17136 + acx_s_configure(priv, &keyindic, ACX111_IE_KEY_CHOOSE);
17139 + CLEAR_BIT(priv->set_mask, GETSET_WEP);
17142 + if (priv->set_mask & (SET_WEP_OPTIONS|GETSET_ALL)) {
17143 + acx100_ie_wep_options_t options;
17145 + if (IS_ACX111(priv)) {
17146 + acxlog(L_DEBUG, "setting WEP Options for acx111 is not supported\n");
17148 + acxlog(L_INIT, "setting WEP Options\n");
17150 + /* let's choose maximum setting: 4 default keys,
17151 + * plus 10 other keys: */
17152 + options.NumKeys = cpu_to_le16(DOT11_MAX_DEFAULT_WEP_KEYS + 10);
17153 + /* don't decrypt default key only,
17154 + * don't override decryption: */
17155 + options.WEPOption = 0;
17156 + if (priv->mode == ACX_MODE_MONITOR) {
17157 + /* don't decrypt default key only,
17158 + * override decryption mechanism: */
17159 + options.WEPOption = 2;
17162 + acx_s_configure(priv, &options, ACX100_IE_WEP_OPTIONS);
17164 + CLEAR_BIT(priv->set_mask, SET_WEP_OPTIONS);
17167 + /* Rescan was requested */
17168 + if (start_scan) {
17169 + switch (priv->mode) {
17170 + case ACX_MODE_0_ADHOC:
17171 + case ACX_MODE_2_STA:
17172 + /* We can avoid clearing list if join code
17173 + ** will be a bit more clever about not picking
17174 + ** 'bad' AP over and over again */
17175 + acx_lock(priv, flags);
17176 + priv->ap_client = NULL;
17177 + acx_l_sta_list_init(priv);
17178 + acx_set_status(priv, ACX_STATUS_1_SCANNING);
17179 + acx_unlock(priv, flags);
17181 + acx_s_cmd_start_scan(priv);
17185 + /* debug, rate, and nick don't need any handling */
17186 + /* what about sniffing mode?? */
17188 + acxlog(L_INIT, "get_mask 0x%08X, set_mask 0x%08X - after update\n",
17189 + priv->get_mask, priv->set_mask);
17196 +/***********************************************************************
17199 +acx_s_initialize_rx_config(wlandevice_t *priv)
17202 + u16 id ACX_PACKED;
17203 + u16 len ACX_PACKED;
17204 + u16 rx_cfg1 ACX_PACKED;
17205 + u16 rx_cfg2 ACX_PACKED;
17208 + switch (priv->mode) {
17209 + case ACX_MODE_OFF:
17210 + priv->rx_config_1 = (u16) (0
17211 + /* | RX_CFG1_INCLUDE_RXBUF_HDR */
17212 + /* | RX_CFG1_FILTER_SSID */
17213 + /* | RX_CFG1_FILTER_BCAST */
17214 + /* | RX_CFG1_RCV_MC_ADDR1 */
17215 + /* | RX_CFG1_RCV_MC_ADDR0 */
17216 + /* | RX_CFG1_FILTER_ALL_MULTI */
17217 + /* | RX_CFG1_FILTER_BSSID */
17218 + /* | RX_CFG1_FILTER_MAC */
17219 + /* | RX_CFG1_RCV_PROMISCUOUS */
17220 + /* | RX_CFG1_INCLUDE_FCS */
17221 + /* | RX_CFG1_INCLUDE_PHY_HDR */
17223 + priv->rx_config_2 = (u16) (0
17224 + /*| RX_CFG2_RCV_ASSOC_REQ */
17225 + /*| RX_CFG2_RCV_AUTH_FRAMES */
17226 + /*| RX_CFG2_RCV_BEACON_FRAMES */
17227 + /*| RX_CFG2_RCV_CONTENTION_FREE */
17228 + /*| RX_CFG2_RCV_CTRL_FRAMES */
17229 + /*| RX_CFG2_RCV_DATA_FRAMES */
17230 + /*| RX_CFG2_RCV_BROKEN_FRAMES */
17231 + /*| RX_CFG2_RCV_MGMT_FRAMES */
17232 + /*| RX_CFG2_RCV_PROBE_REQ */
17233 + /*| RX_CFG2_RCV_PROBE_RESP */
17234 + /*| RX_CFG2_RCV_ACK_FRAMES */
17235 + /*| RX_CFG2_RCV_OTHER */
17238 + case ACX_MODE_MONITOR:
17239 + priv->rx_config_1 = (u16) (0
17240 + /* | RX_CFG1_INCLUDE_RXBUF_HDR */
17241 + /* | RX_CFG1_FILTER_SSID */
17242 + /* | RX_CFG1_FILTER_BCAST */
17243 + /* | RX_CFG1_RCV_MC_ADDR1 */
17244 + /* | RX_CFG1_RCV_MC_ADDR0 */
17245 + /* | RX_CFG1_FILTER_ALL_MULTI */
17246 + /* | RX_CFG1_FILTER_BSSID */
17247 + /* | RX_CFG1_FILTER_MAC */
17248 + | RX_CFG1_RCV_PROMISCUOUS
17249 + /* | RX_CFG1_INCLUDE_FCS */
17250 + /* | RX_CFG1_INCLUDE_PHY_HDR */
17252 + priv->rx_config_2 = (u16) (0
17253 + | RX_CFG2_RCV_ASSOC_REQ
17254 + | RX_CFG2_RCV_AUTH_FRAMES
17255 + | RX_CFG2_RCV_BEACON_FRAMES
17256 + | RX_CFG2_RCV_CONTENTION_FREE
17257 + | RX_CFG2_RCV_CTRL_FRAMES
17258 + | RX_CFG2_RCV_DATA_FRAMES
17259 + | RX_CFG2_RCV_BROKEN_FRAMES
17260 + | RX_CFG2_RCV_MGMT_FRAMES
17261 + | RX_CFG2_RCV_PROBE_REQ
17262 + | RX_CFG2_RCV_PROBE_RESP
17263 + | RX_CFG2_RCV_ACK_FRAMES
17264 + | RX_CFG2_RCV_OTHER
17268 + priv->rx_config_1 = (u16) (0
17269 + /* | RX_CFG1_INCLUDE_RXBUF_HDR */
17270 + /* | RX_CFG1_FILTER_SSID */
17271 + /* | RX_CFG1_FILTER_BCAST */
17272 + /* | RX_CFG1_RCV_MC_ADDR1 */
17273 + /* | RX_CFG1_RCV_MC_ADDR0 */
17274 + /* | RX_CFG1_FILTER_ALL_MULTI */
17275 + /* | RX_CFG1_FILTER_BSSID */
17276 + | RX_CFG1_FILTER_MAC
17277 + /* | RX_CFG1_RCV_PROMISCUOUS */
17278 + /* | RX_CFG1_INCLUDE_FCS */
17279 + /* | RX_CFG1_INCLUDE_PHY_HDR */
17281 + priv->rx_config_2 = (u16) (0
17282 + | RX_CFG2_RCV_ASSOC_REQ
17283 + | RX_CFG2_RCV_AUTH_FRAMES
17284 + | RX_CFG2_RCV_BEACON_FRAMES
17285 + | RX_CFG2_RCV_CONTENTION_FREE
17286 + | RX_CFG2_RCV_CTRL_FRAMES
17287 + | RX_CFG2_RCV_DATA_FRAMES
17288 + /*| RX_CFG2_RCV_BROKEN_FRAMES */
17289 + | RX_CFG2_RCV_MGMT_FRAMES
17290 + | RX_CFG2_RCV_PROBE_REQ
17291 + | RX_CFG2_RCV_PROBE_RESP
17292 + /*| RX_CFG2_RCV_ACK_FRAMES */
17293 + | RX_CFG2_RCV_OTHER
17298 + if (IS_ACX100(priv))
17299 + /* only ACX100 supports that */
17301 + priv->rx_config_1 |= RX_CFG1_INCLUDE_RXBUF_HDR;
17303 + acxlog(L_INIT, "setting RXconfig to %04X:%04X\n",
17304 + priv->rx_config_1, priv->rx_config_2);
17305 + cfg.rx_cfg1 = cpu_to_le16(priv->rx_config_1);
17306 + cfg.rx_cfg2 = cpu_to_le16(priv->rx_config_2);
17307 + acx_s_configure(priv, &cfg, ACX1xx_IE_RXCONFIG);
17311 +/***********************************************************************
17312 +** acx_e_after_interrupt_task
17315 +acx_s_recalib_radio(wlandevice_t *priv)
17317 + if (IS_ACX111(priv)) {
17318 + acx111_cmd_radiocalib_t cal;
17320 + printk("%s: recalibrating radio\n", priv->netdev->name);
17321 + /* automatic recalibration, choose all methods: */
17322 + cal.methods = cpu_to_le32(0x8000000f);
17323 + /* automatic recalibration every 60 seconds (value in TUs)
17324 + * FIXME: what is the firmware default here?? */
17325 + cal.interval = cpu_to_le32(58594);
17326 + return acx_s_issue_cmd_timeo(priv, ACX111_CMD_RADIOCALIB,
17327 + &cal, sizeof(cal), CMD_TIMEOUT_MS(100));
17329 + if (/* (OK == acx_s_issue_cmd(priv, ACX1xx_CMD_DISABLE_TX, NULL, 0)) &&
17330 + (OK == acx_s_issue_cmd(priv, ACX1xx_CMD_DISABLE_RX, NULL, 0)) && */
17331 + (OK == acx_s_issue_cmd(priv, ACX1xx_CMD_ENABLE_TX, &(priv->channel), 1)) &&
17332 + (OK == acx_s_issue_cmd(priv, ACX1xx_CMD_ENABLE_RX, &(priv->channel), 1)) )
17339 +acx_s_after_interrupt_recalib(wlandevice_t *priv)
17343 + /* this helps with ACX100 at least;
17344 + * hopefully ACX111 also does a
17345 + * recalibration here */
17347 + /* clear flag beforehand, since we want to make sure
17348 + * it's cleared; then only set it again on specific circumstances */
17349 + CLEAR_BIT(priv->after_interrupt_jobs, ACX_AFTER_IRQ_CMD_RADIO_RECALIB);
17351 + /* better wait a bit between recalibrations to
17352 + * prevent overheating due to torturing the card
17353 + * into working too long despite high temperature
17354 + * (just a safety measure) */
17355 + if (priv->recalib_time_last_success
17356 + && time_before(jiffies, priv->recalib_time_last_success
17357 + + RECALIB_PAUSE * 60 * HZ)) {
17358 + priv->recalib_msg_ratelimit++;
17359 + if (priv->recalib_msg_ratelimit <= 5)
17360 + printk("%s: less than " STRING(RECALIB_PAUSE)
17361 + " minutes since last radio recalibration, "
17362 + "not recalibrating (maybe card is too hot?)\n",
17363 + priv->netdev->name);
17364 + if (priv->recalib_msg_ratelimit == 5)
17365 + printk("disabling above message\n");
17369 + priv->recalib_msg_ratelimit = 0;
17371 + /* note that commands sometimes fail (card busy),
17372 + * so only clear flag if we were fully successful */
17373 + res = acx_s_recalib_radio(priv);
17375 + printk("%s: successfully recalibrated radio\n",
17376 + priv->netdev->name);
17377 + priv->recalib_time_last_success = jiffies;
17378 + priv->recalib_failure_count = 0;
17380 + /* failed: resubmit, but only limited
17381 + * amount of times within some time range
17382 + * to prevent endless loop */
17384 + priv->recalib_time_last_success = 0; /* we failed */
17386 + /* if some time passed between last
17387 + * attempts, then reset failure retry counter
17388 + * to be able to do next recalib attempt */
17389 + if (time_after(jiffies, priv->recalib_time_last_attempt + HZ))
17390 + priv->recalib_failure_count = 0;
17392 + if (++priv->recalib_failure_count <= 5) {
17393 + priv->recalib_time_last_attempt = jiffies;
17394 + acx_schedule_after_interrupt_task(priv, ACX_AFTER_IRQ_CMD_RADIO_RECALIB);
17400 +acx_e_after_interrupt_task(void *data)
17402 + netdevice_t *dev = (netdevice_t *) data;
17403 + wlandevice_t *priv = netdev_priv(dev);
17407 + acx_sem_lock(priv);
17409 + if (!priv->after_interrupt_jobs)
17410 + goto end; /* no jobs to do */
17412 +#if TX_CLEANUP_IN_SOFTIRQ
17413 + if (priv->after_interrupt_jobs & ACX_AFTER_IRQ_TX_CLEANUP) {
17414 + acx_lock(priv, flags);
17415 + acx_l_clean_tx_desc(priv);
17416 + CLEAR_BIT(priv->after_interrupt_jobs, ACX_AFTER_IRQ_TX_CLEANUP);
17417 + acx_unlock(priv, flags);
17420 + /* we see lotsa tx errors */
17421 + if (priv->after_interrupt_jobs & ACX_AFTER_IRQ_CMD_RADIO_RECALIB) {
17422 + acx_s_after_interrupt_recalib(priv);
17425 + /* a poor interrupt code wanted to do update_card_settings() */
17426 + if (priv->after_interrupt_jobs & ACX_AFTER_IRQ_UPDATE_CARD_CFG) {
17427 + if (ACX_STATE_IFACE_UP & priv->dev_state_mask)
17428 + acx_s_update_card_settings(priv, 0, 0);
17429 + CLEAR_BIT(priv->after_interrupt_jobs, ACX_AFTER_IRQ_UPDATE_CARD_CFG);
17432 + /* 1) we detected that no Scan_Complete IRQ came from fw, or
17433 + ** 2) we found too many STAs */
17434 + if (priv->after_interrupt_jobs & ACX_AFTER_IRQ_CMD_STOP_SCAN) {
17435 + acxlog(L_IRQ, "sending a stop scan cmd...\n");
17436 + acx_s_issue_cmd(priv, ACX1xx_CMD_STOP_SCAN, NULL, 0);
17437 + /* HACK: set the IRQ bit, since we won't get a
17438 + * scan complete IRQ any more on ACX111 (works on ACX100!),
17439 + * since _we_, not a fw, have stopped the scan */
17440 + SET_BIT(priv->irq_status, HOST_INT_SCAN_COMPLETE);
17441 + CLEAR_BIT(priv->after_interrupt_jobs, ACX_AFTER_IRQ_CMD_STOP_SCAN);
17444 + /* either fw sent Scan_Complete or we detected that
17445 + ** no Scan_Complete IRQ came from fw. Finish scanning,
17446 + ** pick join partner if any */
17447 + if (priv->after_interrupt_jobs & ACX_AFTER_IRQ_COMPLETE_SCAN) {
17448 + if (priv->status == ACX_STATUS_1_SCANNING) {
17449 + if (OK != acx_s_complete_scan(priv)) {
17450 + SET_BIT(priv->after_interrupt_jobs,
17451 + ACX_AFTER_IRQ_RESTART_SCAN);
17454 + /* + scan kills current join status - restore it
17455 + ** (do we need it for STA?) */
17456 + /* + does it happen only with active scans?
17457 + ** active and passive scans? ALL scans including
17458 + ** background one? */
17459 + /* + was not verified that everything is restored
17460 + ** (but at least we start to emit beacons again) */
17461 + switch (priv->mode) {
17462 + case ACX_MODE_0_ADHOC:
17463 + case ACX_MODE_3_AP:
17464 + acxlog(L_IRQ, "redoing cmd_join_bssid() after scan\n");
17465 + acx_s_cmd_join_bssid(priv, priv->bssid);
17468 + CLEAR_BIT(priv->after_interrupt_jobs, ACX_AFTER_IRQ_COMPLETE_SCAN);
17471 + /* STA auth or assoc timed out, start over again */
17472 + if (priv->after_interrupt_jobs & ACX_AFTER_IRQ_RESTART_SCAN) {
17473 + acxlog(L_IRQ, "sending a start_scan cmd...\n");
17474 + acx_s_cmd_start_scan(priv);
17475 + CLEAR_BIT(priv->after_interrupt_jobs, ACX_AFTER_IRQ_RESTART_SCAN);
17478 + /* whee, we got positive assoc response! 8) */
17479 + if (priv->after_interrupt_jobs & ACX_AFTER_IRQ_CMD_ASSOCIATE) {
17480 + acx_ie_generic_t pdr;
17481 + /* tiny race window exists, checking that we still a STA */
17482 + switch (priv->mode) {
17483 + case ACX_MODE_2_STA:
17484 + pdr.m.aid = cpu_to_le16(priv->aid);
17485 + acx_s_configure(priv, &pdr, ACX1xx_IE_ASSOC_ID);
17486 + acx_set_status(priv, ACX_STATUS_4_ASSOCIATED);
17487 + acxlog(L_ASSOC|L_DEBUG, "ASSOCIATED!\n");
17488 + CLEAR_BIT(priv->after_interrupt_jobs, ACX_AFTER_IRQ_CMD_ASSOCIATE);
17492 + acx_sem_unlock(priv);
17497 +/***********************************************************************
17498 +** acx_schedule_after_interrupt_task
17500 +** Schedule the call of the after_interrupt method after leaving
17501 +** the interrupt context.
17504 +acx_schedule_after_interrupt_task(wlandevice_t *priv, unsigned int set_flag)
17506 + SET_BIT(priv->after_interrupt_jobs, set_flag);
17507 + SCHEDULE_WORK(&priv->after_interrupt_task);
17511 +/***********************************************************************
17514 +acx_init_task_scheduler(wlandevice_t *priv)
17516 + /* configure task scheduler */
17517 + INIT_WORK(&priv->after_interrupt_task, acx_e_after_interrupt_task,
17522 +/***********************************************************************
17526 +acx_s_start(wlandevice_t *priv)
17531 + * Ok, now we do everything that can possibly be done with ioctl
17532 + * calls to make sure that when it was called before the card
17533 + * was up we get the changes asked for
17536 + SET_BIT(priv->set_mask, SET_TEMPLATES|SET_STA_LIST|GETSET_WEP
17537 + |GETSET_TXPOWER|GETSET_ANTENNA|GETSET_ED_THRESH|GETSET_CCA
17538 + |GETSET_REG_DOMAIN|GETSET_MODE|GETSET_CHANNEL
17539 + |GETSET_TX|GETSET_RX);
17541 + acxlog(L_INIT, "updating initial settings on iface activation...\n");
17542 + acx_s_update_card_settings(priv, 0, 0);
17548 +/***********************************************************************
17549 +** acx_update_capabilities
17552 +acx_update_capabilities(wlandevice_t *priv)
17556 + switch (priv->mode) {
17557 + case ACX_MODE_3_AP:
17558 + SET_BIT(cap, WF_MGMT_CAP_ESS); break;
17559 + case ACX_MODE_0_ADHOC:
17560 + SET_BIT(cap, WF_MGMT_CAP_IBSS); break;
17561 + /* other types of stations do not emit beacons */
17564 + if (priv->wep_restricted) {
17565 + SET_BIT(cap, WF_MGMT_CAP_PRIVACY);
17567 + if (priv->capab_short) {
17568 + SET_BIT(cap, WF_MGMT_CAP_SHORT);
17570 + if (priv->capab_pbcc) {
17571 + SET_BIT(cap, WF_MGMT_CAP_PBCC);
17573 + if (priv->capab_agility) {
17574 + SET_BIT(cap, WF_MGMT_CAP_AGILITY);
17576 + acxlog(L_DEBUG, "caps updated from 0x%04X to 0x%04X\n",
17577 + priv->capabilities, cap);
17578 + priv->capabilities = cap;
17582 +/***********************************************************************
17583 +** FIXME: check whether this function is indeed acx111 only,
17584 +** rename ALL relevant definitions to indicate actual card scope!
17587 +acx111_s_read_configoption(wlandevice_t *priv)
17589 + acx111_ie_configoption_t co, co2;
17593 + if (OK != acx_s_interrogate(priv, &co, ACX111_IE_CONFIG_OPTIONS) ) {
17596 + if (!(acx_debug & L_DEBUG))
17599 + memcpy(&co2.configoption_fixed, &co.configoption_fixed,
17600 + sizeof(co.configoption_fixed));
17602 + pEle = (u8 *)&co.configoption_fixed + sizeof(co.configoption_fixed) - 4;
17604 + co2.antennas.type = pEle[0];
17605 + co2.antennas.len = pEle[1];
17606 + printk("AntennaID:%02X Len:%02X Data:",
17607 + co2.antennas.type, co2.antennas.len);
17608 + for (i = 0; i < pEle[1]; i++) {
17609 + co2.antennas.list[i] = pEle[i+2];
17610 + printk("%02X ", pEle[i+2]);
17614 + pEle += pEle[1] + 2;
17615 + co2.power_levels.type = pEle[0];
17616 + co2.power_levels.len = pEle[1];
17617 + printk("PowerLevelID:%02X Len:%02X Data:",
17618 + co2.power_levels.type, co2.power_levels.len);
17619 + for (i = 0; i < pEle[1]*2; i++) {
17620 + co2.power_levels.list[i] = pEle[i+2];
17621 + printk("%02X ", pEle[i+2]);
17625 + pEle += pEle[1]*2 + 2;
17626 + co2.data_rates.type = pEle[0];
17627 + co2.data_rates.len = pEle[1];
17628 + printk("DataRatesID:%02X Len:%02X Data:",
17629 + co2.data_rates.type, co2.data_rates.len);
17630 + for (i = 0; i < pEle[1]; i++) {
17631 + co2.data_rates.list[i] = pEle[i+2];
17632 + printk("%02X ", pEle[i+2]);
17636 + pEle += pEle[1] + 2;
17637 + co2.domains.type = pEle[0];
17638 + co2.domains.len = pEle[1];
17639 + printk("DomainID:%02X Len:%02X Data:",
17640 + co2.domains.type, co2.domains.len);
17641 + for (i = 0; i < pEle[1]; i++) {
17642 + co2.domains.list[i] = pEle[i+2];
17643 + printk("%02X ", pEle[i+2]);
17647 + pEle += pEle[1] + 2;
17648 + co2.product_id.type = pEle[0];
17649 + co2.product_id.len = pEle[1];
17650 + for (i = 0; i < pEle[1]; i++) {
17651 + co2.product_id.list[i] = pEle[i+2];
17653 + printk("ProductID:%02X Len:%02X Data:%.*s\n",
17654 + co2.product_id.type, co2.product_id.len,
17655 + co2.product_id.len, (char *)co2.product_id.list);
17657 + pEle += pEle[1] + 2;
17658 + co2.manufacturer.type = pEle[0];
17659 + co2.manufacturer.len = pEle[1];
17660 + for (i = 0; i < pEle[1]; i++) {
17661 + co2.manufacturer.list[i] = pEle[i+2];
17663 + printk("ManufacturerID:%02X Len:%02X Data:%.*s\n",
17664 + co2.manufacturer.type, co2.manufacturer.len,
17665 + co2.manufacturer.len, (char *)co2.manufacturer.list);
17667 + printk("EEPROM part:\n");
17668 + for (i=0; i<58; i++) {
17669 + printk("%02X =======> 0x%02X\n",
17670 + i, (u8 *)co.configoption_fixed.NVSv[i-2]);
17677 +/***********************************************************************
17680 +acx_e_init_module(void)
17684 + acx_struct_size_check();
17686 + printk("acx: this driver is still EXPERIMENTAL\n"
17687 + "acx: reading README file and/or Craig's HOWTO is "
17688 + "recommended, visit http://acx100.sf.net in case "
17689 + "of further questions/discussion\n");
17691 +#if defined(CONFIG_ACX_CFI)
17692 + r1 = acxcfi_e_init_module();
17693 +#elif defined(CONFIG_ACX_PCI)
17694 + r1 = acxpci_e_init_module();
17695 +#elif defined(CONFIG_ACX_USB)
17696 + r1 = acxusb_e_init_module();
17700 + if (r1) /* both failed! */
17702 + /* return success if at least one succeeded */
17706 +static void __exit
17707 +acx_e_cleanup_module(void)
17709 +#if defined(CONFIG_ACX_PCI)
17710 + acxcfi_e_cleanup_module();
17711 +#elif defined(CONFIG_ACX_PCI)
17712 + acxpci_e_cleanup_module();
17713 +#elif defined(CONFIG_ACX_USB)
17714 + acxusb_e_cleanup_module();
17718 +module_init(acx_e_init_module)
17719 +module_exit(acx_e_cleanup_module)
17720 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
17721 --- linux-2.6.14-omap2/drivers/net/wireless/tiacx/conv.c 1970-01-01 02:00:00.000000000 +0200
17722 +++ linux-h6300-omap2-2.6.14.3/drivers/net/wireless/tiacx/conv.c 2005-09-28 23:54:23.000000000 +0300
17724 +/***********************************************************************
17725 +** Copyright (C) 2003 ACX100 Open Source Project
17727 +** The contents of this file are subject to the Mozilla Public
17728 +** License Version 1.1 (the "License"); you may not use this file
17729 +** except in compliance with the License. You may obtain a copy of
17730 +** the License at http://www.mozilla.org/MPL/
17732 +** Software distributed under the License is distributed on an "AS
17733 +** IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
17734 +** implied. See the License for the specific language governing
17735 +** rights and limitations under the License.
17737 +** Alternatively, the contents of this file may be used under the
17738 +** terms of the GNU Public License version 2 (the "GPL"), in which
17739 +** case the provisions of the GPL are applicable instead of the
17740 +** above. If you wish to allow the use of your version of this file
17741 +** only under the terms of the GPL and not to allow others to use
17742 +** your version of this file under the MPL, indicate your decision
17743 +** by deleting the provisions above and replace them with the notice
17744 +** and other provisions required by the GPL. If you do not delete
17745 +** the provisions above, a recipient may use your version of this
17746 +** file under either the MPL or the GPL.
17747 +** ---------------------------------------------------------------------
17748 +** Inquiries regarding the ACX100 Open Source Project can be
17749 +** made directly to:
17751 +** acx100-users@lists.sf.net
17752 +** http://acx100.sf.net
17753 +** ---------------------------------------------------------------------
17756 +#include <linux/config.h>
17757 +#include <linux/version.h>
17758 +#include <linux/skbuff.h>
17759 +#include <linux/if_arp.h>
17760 +#include <linux/etherdevice.h>
17761 +#include <linux/wireless.h>
17762 +#if WIRELESS_EXT >= 13
17763 +#include <net/iw_handler.h>
17769 +/*----------------------------------------------------------------
17772 +* Searches the 802.1h Selective Translation Table for a given
17776 +* prottype protocol number (in host order) to search for.
17779 +* 1 - if the table is empty or a match is found.
17780 +* 0 - if the table is non-empty and a match is not found.
17783 +* Based largely on p80211conv.c of the linux-wlan-ng project
17784 +*----------------------------------------------------------------*/
17786 +proto_is_stt(unsigned int proto)
17788 + /* Always return found for now. This is the behavior used by the */
17789 + /* Zoom Win95 driver when 802.1h mode is selected */
17790 + /* TODO: If necessary, add an actual search we'll probably
17791 + need this to match the CMAC's way of doing things.
17792 + Need to do some testing to confirm.
17795 + if (proto == 0x80f3) /* APPLETALK */
17799 +/* return ((prottype == ETH_P_AARP) || (prottype == ETH_P_IPX)); */
17804 +static inline void
17805 +store_llc_snap(struct wlan_llc *llc)
17807 + llc->dsap = 0xaa; /* SNAP, see IEEE 802 */
17808 + llc->ssap = 0xaa;
17812 +llc_is_snap(const struct wlan_llc *llc)
17814 + return (llc->dsap == 0xaa)
17815 + && (llc->ssap == 0xaa)
17816 + && (llc->ctl == 0x03);
17818 +static inline void
17819 +store_oui_rfc1042(struct wlan_snap *snap)
17821 + snap->oui[0] = 0;
17822 + snap->oui[1] = 0;
17823 + snap->oui[2] = 0;
17826 +oui_is_rfc1042(const struct wlan_snap *snap)
17828 + return (snap->oui[0] == 0)
17829 + && (snap->oui[1] == 0)
17830 + && (snap->oui[2] == 0);
17832 +static inline void
17833 +store_oui_8021h(struct wlan_snap *snap)
17835 + snap->oui[0] = 0;
17836 + snap->oui[1] = 0;
17837 + snap->oui[2] = 0xf8;
17840 +oui_is_8021h(const struct wlan_snap *snap)
17842 + return (snap->oui[0] == 0)
17843 + && (snap->oui[1] == 0)
17844 + && (snap->oui[2] == 0xf8);
17848 +/*----------------------------------------------------------------
17849 +* acx_l_ether_to_txbuf
17851 +* Uses the contents of the ether frame to build the elements of
17852 +* the 802.11 frame.
17854 +* We don't actually set up the frame header here. That's the
17855 +* MAC's job. We're only handling conversion of DIXII or 802.3+LLC
17856 +* frames to something that works with 802.11.
17859 +* Based largely on p80211conv.c of the linux-wlan-ng project
17860 +*----------------------------------------------------------------*/
17862 +acx_l_ether_to_txbuf(wlandevice_t *priv, void *txbuf, const struct sk_buff *skb)
17864 + struct wlan_hdr_a3 *w_hdr;
17865 + struct wlan_ethhdr *e_hdr;
17866 + struct wlan_llc *e_llc;
17867 + struct wlan_snap *e_snap;
17868 + const u8 *a1, *a3;
17869 + int header_len, payload_len;
17871 + /* protocol type or data length, depending on whether
17872 + * DIX or 802.3 ethernet format */
17878 + if (unlikely(!skb->len)) {
17879 + acxlog(L_DEBUG, "zero-length skb!\n");
17883 + w_hdr = (struct wlan_hdr_a3*)txbuf;
17885 + switch (priv->mode) {
17886 + case ACX_MODE_MONITOR:
17887 + /* NB: one day we might want to play with DESC_CTL2_FCS
17888 + ** Will need to stop doing "- WLAN_FCS_LEN" here then */
17889 + if (skb->len >= WLAN_A4FR_MAXLEN_WEP_FCS - WLAN_FCS_LEN) {
17890 + printk("%s: can't tx oversized frame (%d bytes)\n",
17891 + priv->netdev->name, skb->len);
17894 + memcpy(w_hdr, skb->data, skb->len);
17895 + result = skb->len;
17899 + /* step 1: classify ether frame, DIX or 802.3? */
17900 + e_hdr = (wlan_ethhdr_t *)skb->data;
17901 + proto = ntohs(e_hdr->type);
17902 + if (proto <= 1500) {
17903 + acxlog(L_DEBUG, "tx: 802.3 len: %d\n", skb->len);
17904 + /* codes <= 1500 reserved for 802.3 lengths */
17905 + /* it's 802.3, pass ether payload unchanged, */
17906 + /* trim off ethernet header and copy payload to txdesc */
17907 + header_len = WLAN_HDR_A3_LEN;
17909 + /* it's DIXII, time for some conversion */
17910 + /* Create 802.11 packet. Header also contains llc and snap. */
17912 + acxlog(L_DEBUG, "tx: DIXII len: %d\n", skb->len);
17914 + /* size of header is 802.11 header + llc + snap */
17915 + header_len = WLAN_HDR_A3_LEN + sizeof(wlan_llc_t) + sizeof(wlan_snap_t);
17916 + /* llc is located behind the 802.11 header */
17917 + e_llc = (wlan_llc_t*)(w_hdr + 1);
17918 + /* snap is located behind the llc */
17919 + e_snap = (wlan_snap_t*)(e_llc + 1);
17921 + /* setup the LLC header */
17922 + store_llc_snap(e_llc);
17924 + /* setup the SNAP header */
17925 + e_snap->type = htons(proto);
17926 + if (proto_is_stt(proto)) {
17927 + store_oui_8021h(e_snap);
17929 + store_oui_rfc1042(e_snap);
17932 + /* trim off ethernet header and copy payload to txbuf */
17933 + payload_len = skb->len - sizeof(wlan_ethhdr_t);
17934 + /* TODO: can we just let acx DMA payload from skb instead? */
17935 + memcpy((u8*)txbuf + header_len, skb->data + sizeof(wlan_ethhdr_t), payload_len);
17936 + payload_len += header_len;
17937 + result = payload_len;
17939 + /* Set up the 802.11 header */
17940 + switch (priv->mode) {
17941 + case ACX_MODE_0_ADHOC:
17942 + fc = (WF_FTYPE_DATAi | WF_FSTYPE_DATAONLYi);
17943 + a1 = e_hdr->daddr;
17944 + a3 = priv->bssid;
17946 + case ACX_MODE_2_STA:
17947 + fc = (WF_FTYPE_DATAi | WF_FSTYPE_DATAONLYi | WF_FC_TODSi);
17948 + a1 = priv->bssid;
17949 + a3 = e_hdr->daddr;
17951 + case ACX_MODE_3_AP:
17952 + fc = (WF_FTYPE_DATAi | WF_FSTYPE_DATAONLYi | WF_FC_FROMDSi);
17953 + a1 = e_hdr->daddr;
17954 + a3 = e_hdr->saddr;
17957 + printk("%s: error - converting eth to wlan in unknown mode\n",
17958 + priv->netdev->name);
17962 + if (priv->wep_enabled)
17963 + SET_BIT(fc, WF_FC_ISWEPi);
17967 + MAC_COPY(w_hdr->a1, a1);
17968 + MAC_COPY(w_hdr->a2, priv->dev_addr);
17969 + MAC_COPY(w_hdr->a3, a3);
17972 +#ifdef DEBUG_CONVERT
17973 + if (acx_debug & L_DATA) {
17974 + printk("original eth frame [%d]: ", skb->len);
17975 + acx_dump_bytes(skb->data, skb->len);
17976 + printk("802.11 frame [%d]: ", payload_len);
17977 + acx_dump_bytes(w_hdr, payload_len);
17982 + FN_EXIT1(result);
17987 +/*----------------------------------------------------------------
17988 +* acx_rxbuf_to_ether
17990 +* Uses the contents of a received 802.11 frame to build an ether
17993 +* This function extracts the src and dest address from the 802.11
17994 +* frame to use in the construction of the eth frame.
17996 +* Based largely on p80211conv.c of the linux-wlan-ng project
17997 +*----------------------------------------------------------------*/
17999 +acx_rxbuf_to_ether(wlandevice_t *priv, rxbuffer_t *rxbuf)
18001 + struct wlan_hdr *w_hdr;
18002 + struct wlan_ethhdr *e_hdr;
18003 + struct wlan_llc *e_llc;
18004 + struct wlan_snap *e_snap;
18005 + struct sk_buff *skb;
18008 + const u8 *e_payload;
18009 + int buflen, payload_length;
18010 + unsigned int payload_offset, mtu;
18015 + /* This looks complex because it must handle possible
18016 + ** phy header in rxbuff */
18017 + w_hdr = acx_get_wlan_hdr(priv, rxbuf);
18018 + payload_offset = WLAN_HDR_A3_LEN; /* it is relative to w_hdr */
18019 + payload_length = RXBUF_BYTES_USED(rxbuf) /* entire rxbuff... */
18020 + - ((u8*)w_hdr - (u8*)rxbuf) /* minus space before 802.11 frame */
18021 + - WLAN_HDR_A3_LEN; /* minus 802.11 header */
18023 + /* setup some vars for convenience */
18025 + switch (WF_FC_FROMTODSi & fc) {
18027 + daddr = w_hdr->a1;
18028 + saddr = w_hdr->a2;
18030 + case WF_FC_FROMDSi:
18031 + daddr = w_hdr->a1;
18032 + saddr = w_hdr->a3;
18034 + case WF_FC_TODSi:
18035 + daddr = w_hdr->a3;
18036 + saddr = w_hdr->a2;
18038 + default: /* WF_FC_FROMTODSi */
18039 + payload_offset += (WLAN_HDR_A4_LEN - WLAN_HDR_A3_LEN);
18040 + payload_length -= (WLAN_HDR_A4_LEN - WLAN_HDR_A3_LEN);
18041 + daddr = w_hdr->a3;
18042 + saddr = w_hdr->a4;
18045 + if ((WF_FC_ISWEPi & fc) && IS_ACX100(priv)) {
18046 + /* chop off the IV+ICV WEP header and footer */
18047 + acxlog(L_DATA|L_DEBUG, "rx: WEP packet, "
18048 + "chopping off IV and ICV\n");
18049 + payload_offset += WLAN_WEP_IV_LEN;
18050 + payload_length -= WLAN_WEP_IV_LEN + WLAN_WEP_ICV_LEN;
18053 + if (unlikely(payload_length < 0)) {
18054 + printk("%s: rx frame too short, ignored\n", priv->netdev->name);
18058 + e_hdr = (wlan_ethhdr_t*) ((u8*) w_hdr + payload_offset);
18059 + e_llc = (wlan_llc_t*) e_hdr;
18060 + e_snap = (wlan_snap_t*) (e_llc + 1);
18061 + e_payload = (u8*) (e_snap + 1);
18062 + mtu = priv->netdev->mtu;
18064 + acxlog(L_DATA, "rx: payload_offset %d, payload_length %d\n",
18065 + payload_offset, payload_length);
18066 + acxlog(L_XFER|L_DATA,
18067 + "rx: frame info: llc=%02X%02X%02X "
18068 + "snap.oui=%02X%02X%02X snap.type=%04X\n",
18069 + e_llc->dsap, e_llc->ssap, e_llc->ctl,
18070 + e_snap->oui[0], e_snap->oui[1], e_snap->oui[2],
18071 + ntohs(e_snap->type));
18073 + /* Test for the various encodings */
18074 + if ((payload_length >= sizeof(wlan_ethhdr_t))
18075 + && ((e_llc->dsap != 0xaa) || (e_llc->ssap != 0xaa))
18076 + && ( (mac_is_equal(daddr, e_hdr->daddr))
18077 + || (mac_is_equal(saddr, e_hdr->saddr))
18080 + /* 802.3 Encapsulated: */
18081 + /* wlan frame body contains complete eth frame (header+body) */
18082 + acxlog(L_DEBUG|L_DATA, "rx: 802.3 ENCAP len=%d\n", payload_length);
18084 + if (unlikely(payload_length > (mtu + ETH_HLEN))) {
18085 + printk("%s: rx: ENCAP frame too large (%d > %d)\n",
18086 + priv->netdev->name,
18087 + payload_length, mtu + ETH_HLEN);
18091 + /* allocate space and setup host buffer */
18092 + buflen = payload_length;
18093 + /* Attempt to align IP header (14 bytes eth header + 2 = 16) */
18094 + skb = dev_alloc_skb(buflen + 2);
18095 + if (unlikely(!skb))
18097 + skb_reserve(skb, 2);
18098 + skb_put(skb, buflen); /* make room */
18100 + /* now copy the data from the 80211 frame */
18101 + memcpy(skb->data, e_hdr, payload_length);
18103 + } else if ( (payload_length >= sizeof(wlan_llc_t)+sizeof(wlan_snap_t))
18104 + && llc_is_snap(e_llc) ) {
18105 + /* wlan frame body contains: AA AA 03 ... (it's a SNAP) */
18107 + if ( !oui_is_rfc1042(e_snap)
18108 + || (proto_is_stt(ieee2host16(e_snap->type)) /* && (ethconv == WLAN_ETHCONV_8021h) */)) {
18109 + acxlog(L_DEBUG|L_DATA, "rx: SNAP+RFC1042 len=%d\n", payload_length);
18110 + /* wlan frame body contains: AA AA 03 !(00 00 00) ... -or- */
18111 + /* wlan frame body contains: AA AA 03 00 00 00 0x80f3 ... */
18112 + /* build eth hdr, type = len, copy AA AA 03... as eth body */
18113 + /* it's a SNAP + RFC1042 frame && protocol is in STT */
18115 + if (unlikely(payload_length > mtu)) {
18116 + printk("%s: rx: SNAP frame too large (%d > %d)\n",
18117 + priv->netdev->name,
18118 + payload_length, mtu);
18122 + /* allocate space and setup host buffer */
18123 + buflen = payload_length + ETH_HLEN;
18124 + skb = dev_alloc_skb(buflen + 2);
18125 + if (unlikely(!skb))
18127 + skb_reserve(skb, 2);
18128 + skb_put(skb, buflen); /* make room */
18130 + /* create 802.3 header */
18131 + e_hdr = (wlan_ethhdr_t*) skb->data;
18132 + MAC_COPY(e_hdr->daddr, daddr);
18133 + MAC_COPY(e_hdr->saddr, saddr);
18134 + e_hdr->type = htons(payload_length);
18136 + /* Now copy the data from the 80211 frame.
18137 + Make room in front for the eth header, and keep the
18138 + llc and snap from the 802.11 payload */
18139 + memcpy(skb->data + ETH_HLEN,
18140 + e_llc, payload_length);
18143 + /* wlan frame body contains: AA AA 03 00 00 00 [type] [tail] */
18144 + /* build eth hdr, type=[type], copy [tail] as eth body */
18145 + acxlog(L_DEBUG|L_DATA, "rx: 802.1h/RFC1042 len=%d\n",
18147 + /* it's an 802.1h frame (an RFC1042 && protocol is not in STT) */
18148 + /* build a DIXII + RFC894 */
18150 + payload_length -= sizeof(wlan_llc_t) + sizeof(wlan_snap_t);
18151 + if (unlikely(payload_length > mtu)) {
18152 + printk("%s: rx: DIXII frame too large (%d > %d)\n",
18153 + priv->netdev->name,
18154 + payload_length, mtu);
18158 + /* allocate space and setup host buffer */
18159 + buflen = payload_length + ETH_HLEN;
18160 + skb = dev_alloc_skb(buflen + 2);
18161 + if (unlikely(!skb))
18163 + skb_reserve(skb, 2);
18164 + skb_put(skb, buflen); /* make room */
18166 + /* create 802.3 header */
18167 + e_hdr = (wlan_ethhdr_t *) skb->data;
18168 + MAC_COPY(e_hdr->daddr, daddr);
18169 + MAC_COPY(e_hdr->saddr, saddr);
18170 + e_hdr->type = e_snap->type;
18172 + /* Now copy the data from the 80211 frame.
18173 + Make room in front for the eth header, and cut off the
18174 + llc and snap from the 802.11 payload */
18175 + memcpy(skb->data + ETH_HLEN,
18176 + e_payload, payload_length);
18180 + acxlog(L_DEBUG|L_DATA, "rx: NON-ENCAP len=%d\n", payload_length);
18181 + /* build eth hdr, type=len, copy wlan body as eth body */
18182 + /* any NON-ENCAP */
18183 + /* it's a generic 80211+LLC or IPX 'Raw 802.3' */
18184 + /* build an 802.3 frame */
18186 + if (unlikely(payload_length > mtu)) {
18187 + printk("%s: rx: OTHER frame too large (%d > %d)\n",
18188 + priv->netdev->name, payload_length, mtu);
18192 + /* allocate space and setup host buffer */
18193 + buflen = payload_length + ETH_HLEN;
18194 + skb = dev_alloc_skb(buflen + 2);
18195 + if (unlikely(!skb))
18197 + skb_reserve(skb, 2);
18198 + skb_put(skb, buflen); /* make room */
18200 + /* set up the 802.3 header */
18201 + e_hdr = (wlan_ethhdr_t *) skb->data;
18202 + MAC_COPY(e_hdr->daddr, daddr);
18203 + MAC_COPY(e_hdr->saddr, saddr);
18204 + e_hdr->type = htons(payload_length);
18206 + /* now copy the data from the 80211 frame */
18207 + memcpy(skb->data + ETH_HLEN, e_llc, payload_length);
18210 + skb->dev = priv->netdev;
18211 + skb->protocol = eth_type_trans(skb, priv->netdev);
18213 +#ifdef DEBUG_CONVERT
18214 + if (acx_debug & L_DATA) {
18215 + printk("p802.11 frame [%d]: ", RXBUF_BYTES_RCVD(rxbuf));
18216 + acx_dump_bytes(w_hdr, RXBUF_BYTES_RCVD(rxbuf));
18217 + printk("eth frame [%d]: ", skb->len);
18218 + acx_dump_bytes(skb->data, skb->len);
18226 + printk("%s: rx: no memory for skb (%d bytes)\n",
18227 + priv->netdev->name, buflen + 2);
18229 + FN_EXIT1((int)NULL);
18232 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
18233 --- linux-2.6.14-omap2/drivers/net/wireless/tiacx/ioctl.c 1970-01-01 02:00:00.000000000 +0200
18234 +++ linux-h6300-omap2-2.6.14.3/drivers/net/wireless/tiacx/ioctl.c 2005-09-28 23:54:23.000000000 +0300
18236 +/***********************************************************************
18237 +** Copyright (C) 2003 ACX100 Open Source Project
18239 +** The contents of this file are subject to the Mozilla Public
18240 +** License Version 1.1 (the "License"); you may not use this file
18241 +** except in compliance with the License. You may obtain a copy of
18242 +** the License at http://www.mozilla.org/MPL/
18244 +** Software distributed under the License is distributed on an "AS
18245 +** IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
18246 +** implied. See the License for the specific language governing
18247 +** rights and limitations under the License.
18249 +** Alternatively, the contents of this file may be used under the
18250 +** terms of the GNU Public License version 2 (the "GPL"), in which
18251 +** case the provisions of the GPL are applicable instead of the
18252 +** above. If you wish to allow the use of your version of this file
18253 +** only under the terms of the GPL and not to allow others to use
18254 +** your version of this file under the MPL, indicate your decision
18255 +** by deleting the provisions above and replace them with the notice
18256 +** and other provisions required by the GPL. If you do not delete
18257 +** the provisions above, a recipient may use your version of this
18258 +** file under either the MPL or the GPL.
18259 +** ---------------------------------------------------------------------
18260 +** Inquiries regarding the ACX100 Open Source Project can be
18261 +** made directly to:
18263 +** acx100-users@lists.sf.net
18264 +** http://acx100.sf.net
18265 +** ---------------------------------------------------------------------
18268 +#include <linux/config.h>
18269 +#include <linux/version.h>
18270 +#include <linux/kernel.h>
18271 +#include <linux/types.h>
18272 +#include <asm/io.h>
18273 +#include <asm/uaccess.h> /* required for 2.4.x kernels; verify_write() */
18275 +#include <linux/if_arp.h>
18276 +#include <linux/wireless.h>
18277 +#if WIRELESS_EXT >= 13
18278 +#include <net/iw_handler.h>
18279 +#endif /* WE >= 13 */
18284 +/*================================================================*/
18286 +/* if you plan to reorder something, make sure to reorder all other places
18287 + * accordingly! */
18288 +/* someone broke SET/GET convention: SETs must have even position, GETs odd */
18289 +#define ACX100_IOCTL SIOCIWFIRSTPRIV
18291 + ACX100_IOCTL_DEBUG = ACX100_IOCTL,
18292 + ACX100_IOCTL_GET__________UNUSED1,
18293 + ACX100_IOCTL_SET_PLED,
18294 + ACX100_IOCTL_GET_PLED,
18295 + ACX100_IOCTL_SET_RATES,
18296 + ACX100_IOCTL_LIST_DOM,
18297 + ACX100_IOCTL_SET_DOM,
18298 + ACX100_IOCTL_GET_DOM,
18299 + ACX100_IOCTL_SET_SCAN_PARAMS,
18300 + ACX100_IOCTL_GET_SCAN_PARAMS,
18301 + ACX100_IOCTL_SET_PREAMB,
18302 + ACX100_IOCTL_GET_PREAMB,
18303 + ACX100_IOCTL_SET_ANT,
18304 + ACX100_IOCTL_GET_ANT,
18305 + ACX100_IOCTL_RX_ANT,
18306 + ACX100_IOCTL_TX_ANT,
18307 + ACX100_IOCTL_SET_PHY_AMP_BIAS,
18308 + ACX100_IOCTL_GET_PHY_CHAN_BUSY,
18309 + ACX100_IOCTL_SET_ED,
18310 + ACX100_IOCTL_GET__________UNUSED3,
18311 + ACX100_IOCTL_SET_CCA,
18312 + ACX100_IOCTL_GET__________UNUSED4,
18313 + ACX100_IOCTL_MONITOR,
18314 + ACX100_IOCTL_TEST,
18315 + ACX100_IOCTL_DBG_SET_MASKS,
18316 + ACX111_IOCTL_INFO,
18317 + ACX100_IOCTL_DBG_SET_IO,
18318 + ACX100_IOCTL_DBG_GET_IO
18321 +/* channel frequencies
18322 + * TODO: Currently, every other 802.11 driver keeps its own copy of this. In
18323 + * the long run this should be integrated into ieee802_11.h or wireless.h or
18324 + * whatever IEEE802.11x framework evolves */
18325 +static const u16 acx_channel_freq[] = {
18326 + 2412, 2417, 2422, 2427, 2432, 2437, 2442,
18327 + 2447, 2452, 2457, 2462, 2467, 2472, 2484,
18330 +static const struct iw_priv_args acx_ioctl_private_args[] = {
18332 +{ cmd : ACX100_IOCTL_DEBUG,
18333 + set_args : IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
18335 + name : "SetDebug" },
18337 +{ cmd : ACX100_IOCTL_SET_PLED,
18338 + set_args : IW_PRIV_TYPE_BYTE | 2,
18340 + name : "SetLEDPower" },
18341 +{ cmd : ACX100_IOCTL_GET_PLED,
18343 + get_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 2,
18344 + name : "GetLEDPower" },
18345 +{ cmd : ACX100_IOCTL_SET_RATES,
18346 + set_args : IW_PRIV_TYPE_CHAR | 256,
18348 + name : "SetRates" },
18349 +{ cmd : ACX100_IOCTL_LIST_DOM,
18352 + name : "ListRegDomain" },
18353 +{ cmd : ACX100_IOCTL_SET_DOM,
18354 + set_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
18356 + name : "SetRegDomain" },
18357 +{ cmd : ACX100_IOCTL_GET_DOM,
18359 + get_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
18360 + name : "GetRegDomain" },
18361 +{ cmd : ACX100_IOCTL_SET_SCAN_PARAMS,
18362 + set_args : IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 4,
18364 + name : "SetScanParams" },
18365 +{ cmd : ACX100_IOCTL_GET_SCAN_PARAMS,
18367 + get_args : IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 4,
18368 + name : "GetScanParams" },
18369 +{ cmd : ACX100_IOCTL_SET_PREAMB,
18370 + set_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
18372 + name : "SetSPreamble" },
18373 +{ cmd : ACX100_IOCTL_GET_PREAMB,
18375 + get_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
18376 + name : "GetSPreamble" },
18377 +{ cmd : ACX100_IOCTL_SET_ANT,
18378 + set_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
18380 + name : "SetAntenna" },
18381 +{ cmd : ACX100_IOCTL_GET_ANT,
18384 + name : "GetAntenna" },
18385 +{ cmd : ACX100_IOCTL_RX_ANT,
18386 + set_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
18388 + name : "SetRxAnt" },
18389 +{ cmd : ACX100_IOCTL_TX_ANT,
18390 + set_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
18392 + name : "SetTxAnt" },
18393 +{ cmd : ACX100_IOCTL_SET_PHY_AMP_BIAS,
18394 + set_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
18396 + name : "SetPhyAmpBias"},
18397 +{ cmd : ACX100_IOCTL_GET_PHY_CHAN_BUSY,
18400 + name : "GetPhyChanBusy" },
18401 +{ cmd : ACX100_IOCTL_SET_ED,
18402 + set_args : IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
18404 + name : "SetED" },
18405 +{ cmd : ACX100_IOCTL_SET_CCA,
18406 + set_args : IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
18408 + name : "SetCCA" },
18409 +{ cmd : ACX100_IOCTL_MONITOR,
18410 + set_args : IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2,
18412 + name : "monitor" },
18413 +{ cmd : ACX100_IOCTL_TEST,
18417 +{ cmd : ACX100_IOCTL_DBG_SET_MASKS,
18418 + set_args : IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2,
18420 + name : "DbgSetMasks" },
18421 +{ cmd : ACX111_IOCTL_INFO,
18424 + name : "GetAcx111Info" },
18425 +{ cmd : ACX100_IOCTL_DBG_SET_IO,
18426 + set_args : IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 4,
18428 + name : "DbgSetIO" },
18429 +{ cmd : ACX100_IOCTL_DBG_GET_IO,
18430 + set_args : IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3,
18432 + name : "DbgGetIO" },
18436 +/*------------------------------------------------------------------------------
18437 + * acx_ioctl_commit
18438 + *----------------------------------------------------------------------------*/
18440 +acx_ioctl_commit(struct net_device *dev,
18441 + struct iw_request_info *info,
18442 + void *zwrq, char *extra)
18444 + wlandevice_t *priv = netdev_priv(dev);
18448 + acx_sem_lock(priv);
18449 + if (ACX_STATE_IFACE_UP & priv->dev_state_mask)
18450 + acx_s_update_card_settings(priv, 0, 0);
18451 + acx_sem_unlock(priv);
18458 +/***********************************************************************
18461 +acx_ioctl_get_name(
18462 + struct net_device *dev,
18463 + struct iw_request_info *info,
18467 + wlandevice_t *priv = netdev_priv(dev);
18468 + static const char * const names[] = { "IEEE 802.11b+/g+", "IEEE 802.11b+" };
18470 + strcpy(cwrq, names[IS_ACX111(priv) ? 0 : 1]);
18476 +/*----------------------------------------------------------------
18477 +* acx_ioctl_set_freq
18478 +*----------------------------------------------------------------*/
18480 +acx_ioctl_set_freq(
18481 + struct net_device *dev,
18482 + struct iw_request_info *info,
18483 + struct iw_freq *fwrq,
18486 + wlandevice_t *priv = netdev_priv(dev);
18487 + int channel = -1;
18488 + unsigned int mult = 1;
18493 + if (fwrq->e == 0 && fwrq->m <= 1000) {
18494 + /* Setting by channel number */
18495 + channel = fwrq->m;
18497 + /* If setting by frequency, convert to a channel */
18500 + for (i = 0; i < (6 - fwrq->e); i++)
18503 + for (i = 1; i <= 14; i++)
18504 + if (fwrq->m == acx_channel_freq[i - 1] * mult)
18508 + if (channel > 14) {
18509 + result = -EINVAL;
18513 + acx_sem_lock(priv);
18515 + priv->channel = channel;
18516 + /* hmm, the following code part is strange, but this is how
18517 + * it was being done before... */
18518 + acxlog(L_IOCTL, "Changing to channel %d\n", channel);
18519 + SET_BIT(priv->set_mask, GETSET_CHANNEL);
18521 + result = -EINPROGRESS; /* need to call commit handler */
18523 + acx_sem_unlock(priv);
18525 + FN_EXIT1(result);
18530 +/***********************************************************************
18533 +acx_ioctl_get_freq(
18534 + struct net_device *dev,
18535 + struct iw_request_info *info,
18536 + struct iw_freq *fwrq,
18539 + wlandevice_t *priv = netdev_priv(dev);
18541 + fwrq->m = priv->channel;
18546 +/*----------------------------------------------------------------
18547 +* acx_ioctl_set_mode
18548 +*----------------------------------------------------------------*/
18550 +acx_ioctl_set_mode(
18551 + struct net_device *dev,
18552 + struct iw_request_info *info,
18556 + wlandevice_t *priv = netdev_priv(dev);
18561 + acx_sem_lock(priv);
18564 + case IW_MODE_AUTO:
18565 + priv->mode = ACX_MODE_OFF;
18567 +#if WIRELESS_EXT > 14
18568 + case IW_MODE_MONITOR:
18569 + priv->mode = ACX_MODE_MONITOR;
18571 +#endif /* WIRELESS_EXT > 14 */
18572 + case IW_MODE_ADHOC:
18573 + priv->mode = ACX_MODE_0_ADHOC;
18575 + case IW_MODE_INFRA:
18576 + priv->mode = ACX_MODE_2_STA;
18578 + case IW_MODE_MASTER:
18579 + printk("acx: master mode (HostAP) is very, very "
18580 + "experimental! It might work partially, but "
18581 + "better get prepared for nasty surprises "
18582 + "at any time\n");
18583 + priv->mode = ACX_MODE_3_AP;
18585 + case IW_MODE_REPEAT:
18586 + case IW_MODE_SECOND:
18588 + result = -EOPNOTSUPP;
18592 + acxlog(L_ASSOC, "new priv->mode=%d\n", priv->mode);
18593 + SET_BIT(priv->set_mask, GETSET_MODE);
18594 + result = -EINPROGRESS;
18597 + acx_sem_unlock(priv);
18599 + FN_EXIT1(result);
18604 +/***********************************************************************
18607 +acx_ioctl_get_mode(
18608 + struct net_device *dev,
18609 + struct iw_request_info *info,
18613 + wlandevice_t *priv = netdev_priv(dev);
18616 + switch (priv->mode) {
18617 + case ACX_MODE_OFF:
18618 + *uwrq = IW_MODE_AUTO; break;
18619 +#if WIRELESS_EXT > 14
18620 + case ACX_MODE_MONITOR:
18621 + *uwrq = IW_MODE_MONITOR; break;
18622 +#endif /* WIRELESS_EXT > 14 */
18623 + case ACX_MODE_0_ADHOC:
18624 + *uwrq = IW_MODE_ADHOC; break;
18625 + case ACX_MODE_2_STA:
18626 + *uwrq = IW_MODE_INFRA; break;
18627 + case ACX_MODE_3_AP:
18628 + *uwrq = IW_MODE_MASTER; break;
18630 + result = -EOPNOTSUPP;
18636 +/***********************************************************************
18639 +acx_ioctl_set_sens(
18640 + struct net_device *dev,
18641 + struct iw_request_info *info,
18642 + struct iw_param *vwrq,
18645 + wlandevice_t *priv = netdev_priv(dev);
18647 + acx_sem_lock(priv);
18649 + priv->sensitivity = (1 == vwrq->disabled) ? 0 : vwrq->value;
18650 + SET_BIT(priv->set_mask, GETSET_SENSITIVITY);
18652 + acx_sem_unlock(priv);
18654 + return -EINPROGRESS;
18658 +/***********************************************************************
18661 +acx_ioctl_get_sens(
18662 + struct net_device *dev,
18663 + struct iw_request_info *info,
18664 + struct iw_param *vwrq,
18667 + wlandevice_t *priv = netdev_priv(dev);
18669 + /* acx_sem_lock(priv); */
18671 + vwrq->value = priv->sensitivity;
18672 + vwrq->disabled = (vwrq->value == 0);
18675 + /* acx_sem_unlock(priv); */
18681 +/*------------------------------------------------------------------------------
18682 + * acx_ioctl_set_ap
18684 + * Sets the MAC address of the AP to associate with
18685 + *----------------------------------------------------------------------------*/
18688 + struct net_device *dev,
18689 + struct iw_request_info *info,
18690 + struct sockaddr *awrq,
18693 + wlandevice_t *priv = netdev_priv(dev);
18698 + if (NULL == awrq) {
18699 + result = -EFAULT;
18702 + if (ARPHRD_ETHER != awrq->sa_family) {
18703 + result = -EINVAL;
18707 + ap = awrq->sa_data;
18708 + acxlog_mac(L_IOCTL, "Set AP=", ap, "\n");
18710 + MAC_COPY(priv->ap, ap);
18712 + /* We want to start rescan in managed or ad-hoc mode,
18713 + ** otherwise just set priv->ap.
18714 + ** "iwconfig <if> ap <mac> mode managed": we must be able
18715 + ** to set ap _first_ and _then_ set mode */
18716 + switch (priv->mode) {
18717 + case ACX_MODE_0_ADHOC:
18718 + case ACX_MODE_2_STA:
18719 + /* FIXME: if there is a convention on what zero AP means,
18720 + ** please add a comment about that. I don't know of any --vda */
18721 + if (mac_is_zero(ap)) {
18722 + /* "off" == 00:00:00:00:00:00 */
18723 + MAC_BCAST(priv->ap);
18724 + acxlog(L_IOCTL, "Not reassociating\n");
18726 + acxlog(L_IOCTL, "Forcing reassociation\n");
18727 + SET_BIT(priv->set_mask, GETSET_RESCAN);
18731 + result = -EINPROGRESS;
18733 + FN_EXIT1(result);
18738 +/***********************************************************************
18742 + struct net_device *dev,
18743 + struct iw_request_info *info,
18744 + struct sockaddr *awrq,
18747 + wlandevice_t *priv = netdev_priv(dev);
18749 + if (ACX_STATUS_4_ASSOCIATED == priv->status) {
18750 + /* as seen in Aironet driver, airo.c */
18751 + MAC_COPY(awrq->sa_data, priv->bssid);
18753 + MAC_ZERO(awrq->sa_data);
18755 + awrq->sa_family = ARPHRD_ETHER;
18760 +/*----------------------------------------------------------------
18761 +* acx_ioctl_get_aplist
18763 +* Comment: deprecated in favour of iwscan.
18764 +* We simply return the list of currently available stations in range,
18765 +* don't do a new scan.
18766 +*----------------------------------------------------------------*/
18768 +acx_ioctl_get_aplist(
18769 + struct net_device *dev,
18770 + struct iw_request_info *info,
18771 + struct iw_point *dwrq,
18774 + wlandevice_t *priv = netdev_priv(dev);
18775 + struct sockaddr *address = (struct sockaddr *) extra;
18776 + struct iw_quality qual[IW_MAX_AP];
18782 + /* we have AP list only in STA mode */
18783 + if (ACX_MODE_2_STA != priv->mode) {
18784 + result = -EOPNOTSUPP;
18789 + for (i = 0; i < VEC_SIZE(priv->sta_list); i++) {
18790 + struct client *bss = &priv->sta_list[i];
18791 + if (!bss->used) continue;
18792 + MAC_COPY(address[cur].sa_data, bss->bssid);
18793 + address[cur].sa_family = ARPHRD_ETHER;
18794 + qual[cur].level = bss->sir;
18795 + qual[cur].noise = bss->snr;
18796 +#ifndef OLD_QUALITY
18797 + qual[cur].qual = acx_signal_determine_quality(qual[cur].level,
18798 + qual[cur].noise);
18800 + qual[cur].qual = (qual[cur].noise <= 100) ?
18801 + 100 - qual[cur].noise : 0;
18803 + /* no scan: level/noise/qual not updated: */
18804 + qual[cur].updated = 0;
18809 + memcpy(extra + sizeof(struct sockaddr)*cur, &qual,
18810 + sizeof(struct iw_quality)*cur);
18812 + dwrq->length = cur;
18814 + FN_EXIT1(result);
18819 +/***********************************************************************
18822 +acx_ioctl_set_scan(
18823 + struct net_device *dev,
18824 + struct iw_request_info *info,
18825 + struct iw_param *vwrq,
18828 + wlandevice_t *priv = netdev_priv(dev);
18833 + acx_sem_lock(priv);
18835 + /* don't start scan if device is not up yet */
18836 + if (!(priv->dev_state_mask & ACX_STATE_IFACE_UP)) {
18837 + result = -EAGAIN;
18841 + /* This is NOT a rescan for new AP!
18842 + ** Do not use SET_BIT(GETSET_RESCAN); */
18843 + acx_s_cmd_start_scan(priv);
18847 + acx_sem_unlock(priv);
18849 + FN_EXIT1(result);
18854 +#if WIRELESS_EXT > 13
18855 +/***********************************************************************
18856 +** acx_s_scan_add_station
18858 +/* helper. not sure wheter it's really a _s_leeping fn */
18860 +acx_s_scan_add_station(
18861 + wlandevice_t *priv,
18864 + struct client *bss)
18866 + struct iw_event iwe;
18871 + /* MAC address has to be added first */
18872 + iwe.cmd = SIOCGIWAP;
18873 + iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
18874 + MAC_COPY(iwe.u.ap_addr.sa_data, bss->bssid);
18875 + acxlog_mac(L_IOCTL, "scan, station address: ", bss->bssid, "\n");
18876 + ptr = iwe_stream_add_event(ptr, end_buf, &iwe, IW_EV_ADDR_LEN);
18879 + iwe.cmd = SIOCGIWESSID;
18880 + iwe.u.data.length = bss->essid_len;
18881 + iwe.u.data.flags = 1;
18882 + acxlog(L_IOCTL, "scan, essid: %s\n", bss->essid);
18883 + ptr = iwe_stream_add_point(ptr, end_buf, &iwe, bss->essid);
18886 + iwe.cmd = SIOCGIWMODE;
18887 + if (bss->cap_info & (WF_MGMT_CAP_ESS | WF_MGMT_CAP_IBSS)) {
18888 + if (bss->cap_info & WF_MGMT_CAP_ESS)
18889 + iwe.u.mode = IW_MODE_MASTER;
18891 + iwe.u.mode = IW_MODE_ADHOC;
18892 + acxlog(L_IOCTL, "scan, mode: %d\n", iwe.u.mode);
18893 + ptr = iwe_stream_add_event(ptr, end_buf, &iwe, IW_EV_UINT_LEN);
18896 + /* Add frequency */
18897 + iwe.cmd = SIOCGIWFREQ;
18898 + iwe.u.freq.m = acx_channel_freq[bss->channel - 1] * 100000;
18899 + iwe.u.freq.e = 1;
18900 + acxlog(L_IOCTL, "scan, frequency: %d\n", iwe.u.freq.m);
18901 + ptr = iwe_stream_add_event(ptr, end_buf, &iwe, IW_EV_FREQ_LEN);
18903 + /* Add link quality */
18904 + iwe.cmd = IWEVQUAL;
18905 + /* FIXME: these values should be expressed in dBm, but we don't know
18906 + * how to calibrate it yet */
18907 + iwe.u.qual.level = bss->sir;
18908 + iwe.u.qual.noise = bss->snr;
18909 +#ifndef OLD_QUALITY
18910 + iwe.u.qual.qual = acx_signal_determine_quality(iwe.u.qual.level,
18911 + iwe.u.qual.noise);
18913 + iwe.u.qual.qual = (iwe.u.qual.noise <= 100) ?
18914 + 100 - iwe.u.qual.noise : 0;
18916 + iwe.u.qual.updated = 7;
18917 + acxlog(L_IOCTL, "scan, link quality: %d/%d/%d\n",
18918 + iwe.u.qual.level, iwe.u.qual.noise, iwe.u.qual.qual);
18919 + ptr = iwe_stream_add_event(ptr, end_buf, &iwe, IW_EV_QUAL_LEN);
18921 + /* Add encryption */
18922 + iwe.cmd = SIOCGIWENCODE;
18923 + if (bss->cap_info & WF_MGMT_CAP_PRIVACY)
18924 + iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
18926 + iwe.u.data.flags = IW_ENCODE_DISABLED;
18927 + iwe.u.data.length = 0;
18928 + acxlog(L_IOCTL, "scan, encryption flags: %X\n", iwe.u.data.flags);
18929 + ptr = iwe_stream_add_point(ptr, end_buf, &iwe, bss->essid);
18932 + iwe.cmd = SIOCGIWRATE;
18933 + iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
18934 + ptr_rate = ptr + IW_EV_LCP_LEN;
18937 + u16 rate = bss->rate_cap;
18938 + const u8* p = bitpos2ratebyte;
18941 + iwe.u.bitrate.value = *p * 500000; /* units of 500kb/s */
18942 + acxlog(L_IOCTL, "scan, rate: %d\n", iwe.u.bitrate.value);
18943 + ptr = iwe_stream_add_value(ptr, ptr_rate, end_buf, &iwe, IW_EV_PARAM_LEN);
18949 + if ((ptr_rate - ptr) > (ptrdiff_t)IW_EV_LCP_LEN)
18952 + /* drop remaining station data items for now */
18959 +/***********************************************************************
18960 + * acx_ioctl_get_scan
18963 +acx_ioctl_get_scan(
18964 + struct net_device *dev,
18965 + struct iw_request_info *info,
18966 + struct iw_point *dwrq,
18969 + wlandevice_t *priv = netdev_priv(dev);
18970 + char *ptr = extra;
18976 + acx_sem_lock(priv);
18978 + /* no scan available if device is not up yet */
18979 + if (!(priv->dev_state_mask & ACX_STATE_IFACE_UP)) {
18980 + acxlog(L_IOCTL, "iface not up yet\n");
18981 + result = -EAGAIN;
18984 +#if 0 /* Why is this needed? If needed, add a comment */
18985 + if (priv->scan_start && time_before(jiffies, priv->scan_start + 3*HZ)) {
18986 + acxlog(L_IOCTL, "scan in progress, no results yet\n");
18987 + result = -EAGAIN;
18992 +#ifdef ENODATA_TO_BE_USED_AFTER_SCAN_ERROR_ONLY
18993 + if (priv->bss_table_count == 0) {
18994 + /* no stations found */
18995 + result = -ENODATA;
19000 + for (i = 0; i < VEC_SIZE(priv->sta_list); i++) {
19001 + struct client *bss = &priv->sta_list[i];
19002 + if (!bss->used) continue;
19003 + ptr = acx_s_scan_add_station(priv, ptr,
19004 + extra + IW_SCAN_MAX_DATA, bss);
19006 + dwrq->length = ptr - extra;
19010 + acx_sem_unlock(priv);
19012 + FN_EXIT1(result);
19015 +#endif /* WIRELESS_EXT > 13 */
19018 +/*----------------------------------------------------------------
19019 +* acx_ioctl_set_essid
19020 +*----------------------------------------------------------------*/
19022 +acx_ioctl_set_essid(
19023 + struct net_device *dev,
19024 + struct iw_request_info *info,
19025 + struct iw_point *dwrq,
19028 + wlandevice_t *priv = netdev_priv(dev);
19029 + int len = dwrq->length;
19034 + acxlog(L_IOCTL, "Set ESSID '%*s', length %d, flags 0x%04X\n",
19035 + len, extra, len, dwrq->flags);
19038 + result = -EINVAL;
19042 + acx_sem_lock(priv);
19044 + /* ESSID disabled? */
19045 + if (0 == dwrq->flags) {
19046 + priv->essid_active = 0;
19049 + if (dwrq->length > IW_ESSID_MAX_SIZE+1) {
19054 + if (len > sizeof(priv->essid))
19055 + len = sizeof(priv->essid);
19056 + memcpy(priv->essid, extra, len-1);
19057 + priv->essid[len-1] = '\0';
19058 + /* Paranoia: just in case there is a '\0'... */
19059 + priv->essid_len = strlen(priv->essid);
19060 + priv->essid_active = 1;
19063 + SET_BIT(priv->set_mask, GETSET_RESCAN);
19065 + result = -EINPROGRESS;
19068 + acx_sem_unlock(priv);
19070 + FN_EXIT1(result);
19075 +/***********************************************************************
19078 +acx_ioctl_get_essid(
19079 + struct net_device *dev,
19080 + struct iw_request_info *info,
19081 + struct iw_point *dwrq,
19084 + wlandevice_t *priv = netdev_priv(dev);
19086 + dwrq->flags = priv->essid_active;
19087 + if (priv->essid_active) {
19088 + memcpy(extra, priv->essid, priv->essid_len);
19089 + extra[priv->essid_len] = '\0';
19090 + dwrq->length = priv->essid_len + 1;
19097 +/*----------------------------------------------------------------
19098 +* acx_l_update_client_rates
19099 +*----------------------------------------------------------------*/
19101 +acx_l_update_client_rates(wlandevice_t *priv, u16 rate)
19104 + for (i = 0; i < VEC_SIZE(priv->sta_list); i++) {
19105 + client_t *clt = &priv->sta_list[i];
19106 + if (!clt->used) continue;
19107 + clt->rate_cfg = (clt->rate_cap & rate);
19108 + if (!clt->rate_cfg) {
19109 + /* no compatible rates left: kick client */
19110 + acxlog_mac(L_ASSOC, "client ",clt->address," kicked: "
19111 + "rates are not compatible anymore\n");
19112 + acx_l_sta_list_del(priv, clt);
19115 + clt->rate_cur &= clt->rate_cfg;
19116 + if (!clt->rate_cur) {
19117 + /* current rate become invalid, choose a valid one */
19118 + clt->rate_cur = 1 << lowest_bit(clt->rate_cfg);
19120 + clt->fallback_count = clt->stepup_count = 0;
19121 + clt->ignore_count = 16;
19123 + switch (priv->mode) {
19124 + case ACX_MODE_2_STA:
19125 + if (priv->ap_client && !priv->ap_client->used) {
19126 + /* Owwww... we kicked our AP!! :) */
19127 + SET_BIT(priv->set_mask, GETSET_RESCAN);
19133 +/***********************************************************************
19135 +/* maps bits from acx111 rate to rate in Mbits */
19136 +static const unsigned int
19137 +acx111_rate_tbl[] = {
19143 + 11000000, /* 5 */
19144 + 12000000, /* 6 */
19145 + 18000000, /* 7 */
19146 + 22000000, /* 8 */
19147 + 24000000, /* 9 */
19148 + 36000000, /* 10 */
19149 + 48000000, /* 11 */
19150 + 54000000, /* 12 */
19151 + 500000, /* 13, should not happen */
19152 + 500000, /* 14, should not happen */
19153 + 500000, /* 15, should not happen */
19156 +/***********************************************************************
19157 + * acx_ioctl_set_rate
19160 +acx_ioctl_set_rate(
19161 + struct net_device *dev,
19162 + struct iw_request_info *info,
19163 + struct iw_param *vwrq,
19166 + wlandevice_t *priv = netdev_priv(dev);
19167 + u16 txrate_cfg = 1;
19168 + unsigned long flags;
19170 + int result = -EINVAL;
19174 + "rate %d fixed 0x%X disabled 0x%X flags 0x%X\n",
19175 + vwrq->value, vwrq->fixed, vwrq->disabled, vwrq->flags);
19177 + if ((0 == vwrq->fixed) || (1 == vwrq->fixed)) {
19178 + int i = VEC_SIZE(acx111_rate_tbl)-1;
19179 + if (vwrq->value == -1)
19180 + /* "iwconfig rate auto" --> choose highest */
19181 + vwrq->value = IS_ACX100(priv) ? 22000000 : 54000000;
19183 + if (vwrq->value == acx111_rate_tbl[i]) {
19184 + txrate_cfg <<= i;
19190 + if (i == -1) { /* no matching rate */
19191 + result = -EINVAL;
19194 + } else { /* rate N, N<1000 (driver specific): we don't use this */
19195 + result = -EOPNOTSUPP;
19198 + /* now: only one bit is set in txrate_cfg, corresponding to
19199 + ** indicated rate */
19201 + autorate = (vwrq->fixed == 0) && (RATE111_1 != txrate_cfg);
19203 + /* convert 00100000 -> 00111111 */
19204 + txrate_cfg = (txrate_cfg<<1)-1;
19207 + if (IS_ACX100(priv)) {
19208 + txrate_cfg &= RATE111_ACX100_COMPAT;
19209 + if (!txrate_cfg) {
19210 + result = -ENOTSUPP; /* rate is not supported by acx100 */
19215 + acx_sem_lock(priv);
19216 + acx_lock(priv, flags);
19218 + priv->rate_auto = autorate;
19219 + priv->rate_oper = txrate_cfg;
19220 + priv->rate_basic = txrate_cfg;
19221 + /* only do that in auto mode, non-auto will be able to use
19222 + * one specific Tx rate only anyway */
19224 + /* only use 802.11b base rates, for standard 802.11b H/W
19225 + * compatibility */
19226 + priv->rate_basic &= RATE111_80211B_COMPAT;
19228 + priv->rate_bcast = 1 << lowest_bit(txrate_cfg);
19229 + if (IS_ACX100(priv))
19230 + priv->rate_bcast100 = acx_rate111to100(priv->rate_bcast);
19231 + acx_l_update_ratevector(priv);
19232 + acx_l_update_client_rates(priv, txrate_cfg);
19234 + /* Do/don't do tx rate fallback; beacon contents and rate */
19235 + SET_BIT(priv->set_mask, SET_RATE_FALLBACK|SET_TEMPLATES);
19236 + result = -EINPROGRESS;
19238 + acx_unlock(priv, flags);
19239 + acx_sem_unlock(priv);
19241 + FN_EXIT1(result);
19246 +/*----------------------------------------------------------------
19247 +* acx_ioctl_get_rate
19248 +*----------------------------------------------------------------*/
19250 +acx_ioctl_get_rate(
19251 + struct net_device *dev,
19252 + struct iw_request_info *info,
19253 + struct iw_param *vwrq,
19256 + /* TODO: remember rate of last tx, show it. think about multiple peers... */
19257 + wlandevice_t *priv = netdev_priv(dev);
19258 + vwrq->value = acx111_rate_tbl[highest_bit(priv->rate_oper)];
19259 + vwrq->fixed = !priv->rate_auto;
19260 + vwrq->disabled = 0;
19265 +acx_ioctl_set_rts(
19266 + struct net_device *dev,
19267 + struct iw_request_info *info,
19268 + struct iw_param *vwrq,
19271 + wlandevice_t *priv = netdev_priv(dev);
19272 + int val = vwrq->value;
19274 + if (vwrq->disabled)
19276 + if ((val < 0) || (val > 2312))
19279 + priv->rts_threshold = val;
19284 +acx_ioctl_get_rts(
19285 + struct net_device *dev,
19286 + struct iw_request_info *info,
19287 + struct iw_param *vwrq,
19290 + wlandevice_t *priv = netdev_priv(dev);
19292 + vwrq->value = priv->rts_threshold;
19293 + vwrq->disabled = (vwrq->value >= 2312);
19299 +/*----------------------------------------------------------------
19300 +* acx_ioctl_set_encode
19301 +*----------------------------------------------------------------*/
19303 +acx_ioctl_set_encode(
19304 + struct net_device *dev,
19305 + struct iw_request_info *info,
19306 + struct iw_point *dwrq,
19309 + wlandevice_t *priv = netdev_priv(dev);
19315 + "Set Encoding flags=0x%04X, size=%d, key: %s\n",
19316 + dwrq->flags, dwrq->length, extra ? "set" : "No key");
19318 + acx_sem_lock(priv);
19320 + index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
19322 + if (dwrq->length > 0) {
19323 + /* if index is 0 or invalid, use default key */
19324 + if ((index < 0) || (index > 3))
19325 + index = (int)priv->wep_current_index;
19327 + if (0 == (dwrq->flags & IW_ENCODE_NOKEY)) {
19328 + if (dwrq->length > 29)
19329 + dwrq->length = 29; /* restrict it */
19331 + if (dwrq->length > 13)
19332 + priv->wep_keys[index].size = 29; /* 29*8 == 232, WEP256 */
19334 + if (dwrq->length > 5)
19335 + priv->wep_keys[index].size = 13; /* 13*8 == 104bit, WEP128 */
19337 + if (dwrq->length > 0)
19338 + priv->wep_keys[index].size = 5; /* 5*8 == 40bit, WEP64 */
19340 + /* disable key */
19341 + priv->wep_keys[index].size = 0;
19343 + memset(priv->wep_keys[index].key, 0, sizeof(priv->wep_keys[index].key));
19344 + memcpy(priv->wep_keys[index].key, extra, dwrq->length);
19348 + /* set transmit key */
19349 + if ((index >= 0) && (index <= 3))
19350 + priv->wep_current_index = index;
19352 + if (0 == (dwrq->flags & IW_ENCODE_MODE)) {
19353 + /* complain if we were not just setting
19354 + * the key mode */
19355 + result = -EINVAL;
19360 + priv->wep_enabled = !(dwrq->flags & IW_ENCODE_DISABLED);
19362 + if (dwrq->flags & IW_ENCODE_OPEN) {
19363 + priv->auth_alg = WLAN_AUTH_ALG_OPENSYSTEM;
19364 + priv->wep_restricted = 0;
19366 + } else if (dwrq->flags & IW_ENCODE_RESTRICTED) {
19367 + priv->auth_alg = WLAN_AUTH_ALG_SHAREDKEY;
19368 + priv->wep_restricted = 1;
19371 + /* set flag to make sure the card WEP settings get updated */
19372 + SET_BIT(priv->set_mask, GETSET_WEP);
19374 + acxlog(L_IOCTL, "len=%d, key at 0x%p, flags=0x%X\n",
19375 + dwrq->length, extra,
19378 + for (index = 0; index <= 3; index++) {
19379 + if (priv->wep_keys[index].size) {
19381 + "index=%d, size=%d, key at 0x%p\n",
19382 + priv->wep_keys[index].index,
19383 + (int) priv->wep_keys[index].size,
19384 + priv->wep_keys[index].key);
19387 + result = -EINPROGRESS;
19390 + acx_sem_unlock(priv);
19392 + FN_EXIT1(result);
19397 +/*----------------------------------------------------------------
19398 +* acx_ioctl_get_encode
19399 +*----------------------------------------------------------------*/
19401 +acx_ioctl_get_encode(
19402 + struct net_device *dev,
19403 + struct iw_request_info *info,
19404 + struct iw_point *dwrq,
19407 + wlandevice_t *priv = netdev_priv(dev);
19408 + int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
19410 + if (priv->wep_enabled == 0) {
19411 + dwrq->flags = IW_ENCODE_DISABLED;
19414 + if ((index < 0) || (index > 3))
19415 + index = (int)priv->wep_current_index;
19418 + (priv->wep_restricted == 1) ? IW_ENCODE_RESTRICTED : IW_ENCODE_OPEN;
19419 + dwrq->length = priv->wep_keys[index].size;
19422 + priv->wep_keys[index].key,
19423 + priv->wep_keys[index].size);
19426 + /* set the current index */
19427 + SET_BIT(dwrq->flags, index + 1);
19429 + acxlog(L_IOCTL, "len=%d, key=%p, flags=0x%X\n",
19430 + dwrq->length, dwrq->pointer,
19437 +/***********************************************************************
19440 +acx_ioctl_set_power(
19441 + struct net_device *dev,
19442 + struct iw_request_info *info,
19443 + struct iw_param *vwrq,
19446 + wlandevice_t *priv = netdev_priv(dev);
19448 + acxlog(L_IOCTL, "Set 802.11 Power Save flags=0x%04X\n", vwrq->flags);
19449 + if (vwrq->disabled) {
19450 + CLEAR_BIT(priv->ps_wakeup_cfg, PS_CFG_ENABLE);
19451 + SET_BIT(priv->set_mask, GETSET_POWER_80211);
19452 + return -EINPROGRESS;
19454 + if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
19455 + u16 ps_timeout = (vwrq->value * 1024) / 1000;
19457 + if (ps_timeout > 255)
19458 + ps_timeout = 255;
19459 + acxlog(L_IOCTL, "setting PS timeout value to %d time units "
19460 + "due to %dus\n", ps_timeout, vwrq->value);
19461 + priv->ps_hangover_period = ps_timeout;
19462 + } else if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_PERIOD) {
19463 + u16 ps_periods = vwrq->value / 1000000;
19465 + if (ps_periods > 255)
19466 + ps_periods = 255;
19467 + acxlog(L_IOCTL, "setting PS period value to %d periods "
19468 + "due to %dus\n", ps_periods, vwrq->value);
19469 + priv->ps_listen_interval = ps_periods;
19470 + CLEAR_BIT(priv->ps_wakeup_cfg, PS_CFG_WAKEUP_MODE_MASK);
19471 + SET_BIT(priv->ps_wakeup_cfg, PS_CFG_WAKEUP_EACH_ITVL);
19473 + switch (vwrq->flags & IW_POWER_MODE) {
19474 + /* FIXME: are we doing the right thing here? */
19475 + case IW_POWER_UNICAST_R:
19476 + CLEAR_BIT(priv->ps_options, PS_OPT_STILL_RCV_BCASTS);
19478 + case IW_POWER_MULTICAST_R:
19479 + SET_BIT(priv->ps_options, PS_OPT_STILL_RCV_BCASTS);
19481 + case IW_POWER_ALL_R:
19482 + SET_BIT(priv->ps_options, PS_OPT_STILL_RCV_BCASTS);
19484 + case IW_POWER_ON:
19487 + acxlog(L_IOCTL, "unknown PS mode\n");
19491 + SET_BIT(priv->ps_wakeup_cfg, PS_CFG_ENABLE);
19492 + SET_BIT(priv->set_mask, GETSET_POWER_80211);
19494 + return -EINPROGRESS;
19499 +/***********************************************************************
19502 +acx_ioctl_get_power(
19503 + struct net_device *dev,
19504 + struct iw_request_info *info,
19505 + struct iw_param *vwrq,
19508 + wlandevice_t *priv = netdev_priv(dev);
19510 + acxlog(L_IOCTL, "Get 802.11 Power Save flags = 0x%04X\n", vwrq->flags);
19511 + vwrq->disabled = ((priv->ps_wakeup_cfg & PS_CFG_ENABLE) == 0);
19512 + if (vwrq->disabled)
19514 + if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
19515 + vwrq->value = priv->ps_hangover_period * 1000 / 1024;
19516 + vwrq->flags = IW_POWER_TIMEOUT;
19518 + vwrq->value = priv->ps_listen_interval * 1000000;
19519 + vwrq->flags = IW_POWER_PERIOD|IW_POWER_RELATIVE;
19521 + if (priv->ps_options & PS_OPT_STILL_RCV_BCASTS)
19522 + SET_BIT(vwrq->flags, IW_POWER_ALL_R);
19524 + SET_BIT(vwrq->flags, IW_POWER_UNICAST_R);
19530 +/*----------------------------------------------------------------
19531 +* acx_ioctl_get_txpow
19532 +*----------------------------------------------------------------*/
19534 +acx_ioctl_get_txpow(
19535 + struct net_device *dev,
19536 + struct iw_request_info *info,
19537 + struct iw_param *vwrq,
19540 + wlandevice_t *priv = netdev_priv(dev);
19542 + vwrq->flags = IW_TXPOW_DBM;
19543 + vwrq->disabled = 0;
19545 + vwrq->value = priv->tx_level_dbm;
19547 + acxlog(L_IOCTL, "get txpower:%d dBm\n", priv->tx_level_dbm);
19553 +/*----------------------------------------------------------------
19554 +* acx_ioctl_set_txpow
19555 +*----------------------------------------------------------------*/
19557 +acx_ioctl_set_txpow(
19558 + struct net_device *dev,
19559 + struct iw_request_info *info,
19560 + struct iw_param *vwrq,
19563 + wlandevice_t *priv = netdev_priv(dev);
19567 + acxlog(L_IOCTL, "set txpower:%d, disabled:%d, flags:0x%04X\n",
19568 + vwrq->value, vwrq->disabled, vwrq->flags);
19570 + acx_sem_lock(priv);
19572 + if (vwrq->disabled != priv->tx_disabled) {
19573 + SET_BIT(priv->set_mask, GETSET_TX); /* Tx status needs update later */
19576 + priv->tx_disabled = vwrq->disabled;
19577 + if (vwrq->value == -1) {
19578 + if (vwrq->disabled) {
19579 + priv->tx_level_dbm = 0;
19580 + acxlog(L_IOCTL, "disable radio tx\n");
19582 + /* priv->tx_level_auto = 1; */
19583 + acxlog(L_IOCTL, "set tx power auto (NIY)\n");
19586 + priv->tx_level_dbm = vwrq->value <= 20 ? vwrq->value : 20;
19587 + /* priv->tx_level_auto = 0; */
19588 + acxlog(L_IOCTL, "set txpower=%d dBm\n", priv->tx_level_dbm);
19590 + SET_BIT(priv->set_mask, GETSET_TXPOWER);
19592 + result = -EINPROGRESS;
19594 + acx_sem_unlock(priv);
19596 + FN_EXIT1(result);
19601 +/*----------------------------------------------------------------
19602 +* acx_ioctl_get_range
19603 +*----------------------------------------------------------------*/
19605 +acx_ioctl_get_range(
19606 + struct net_device *dev,
19607 + struct iw_request_info *info,
19608 + struct iw_point *dwrq,
19611 + if (dwrq->pointer != NULL) {
19612 + struct iw_range *range = (struct iw_range *)extra;
19613 + wlandevice_t *priv = netdev_priv(dev);
19616 + dwrq->length = sizeof(struct iw_range);
19617 + memset(range, 0, sizeof(struct iw_range));
19618 + range->num_channels = 0;
19619 + for (i = 1; i <= 14; i++) {
19620 + if (priv->reg_dom_chanmask & (1 << (i - 1))) {
19621 + range->freq[range->num_channels].i = i;
19622 + range->freq[range->num_channels].m = acx_channel_freq[i - 1] * 100000;
19623 + range->freq[range->num_channels++].e = 1; /* MHz values */
19626 + range->num_frequency = range->num_channels;
19628 + range->min_rts = 0;
19629 + range->max_rts = 2312;
19630 + /* range->min_frag = 256;
19631 + * range->max_frag = 2312;
19634 + range->encoding_size[0] = 5;
19635 + range->encoding_size[1] = 13;
19636 + range->encoding_size[2] = 29;
19637 + range->num_encoding_sizes = 3;
19638 + range->max_encoding_tokens = 4;
19640 + range->min_pmp = 0;
19641 + range->max_pmp = 5000000;
19642 + range->min_pmt = 0;
19643 + range->max_pmt = 65535 * 1000;
19644 + range->pmp_flags = IW_POWER_PERIOD;
19645 + range->pmt_flags = IW_POWER_TIMEOUT;
19646 + range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R;
19648 + for (i = 0; i <= IW_MAX_TXPOWER - 1; i++)
19649 + range->txpower[i] = 20 * i / (IW_MAX_TXPOWER - 1);
19650 + range->num_txpower = IW_MAX_TXPOWER;
19651 + range->txpower_capa = IW_TXPOW_DBM;
19653 + range->we_version_compiled = WIRELESS_EXT;
19654 + range->we_version_source = 0x9;
19656 + range->retry_capa = IW_RETRY_LIMIT;
19657 + range->retry_flags = IW_RETRY_LIMIT;
19658 + range->min_retry = 1;
19659 + range->max_retry = 255;
19661 + range->r_time_flags = IW_RETRY_LIFETIME;
19662 + range->min_r_time = 0;
19663 + /* FIXME: lifetime ranges and orders of magnitude are strange?? */
19664 + range->max_r_time = 65535;
19666 + if (IS_USB(priv))
19667 + range->sensitivity = 0;
19668 + else if (IS_ACX111(priv))
19669 + range->sensitivity = 3;
19671 + range->sensitivity = 255;
19673 + for (i=0; i < priv->rate_supported_len; i++) {
19674 + range->bitrate[i] = (priv->rate_supported[i] & ~0x80) * 500000;
19675 + /* never happens, but keep it, to be safe: */
19676 + if (range->bitrate[i] == 0)
19679 + range->num_bitrates = i;
19681 + range->max_qual.qual = 100;
19682 + range->max_qual.level = 100;
19683 + range->max_qual.noise = 100;
19684 + /* TODO: better values */
19685 + range->avg_qual.qual = 90;
19686 + range->avg_qual.level = 80;
19687 + range->avg_qual.noise = 2;
19694 +/*================================================================*/
19695 +/* Private functions */
19696 +/*================================================================*/
19698 +#if WIRELESS_EXT < 13
19699 +/*----------------------------------------------------------------
19700 +* acx_ioctl_get_iw_priv
19702 +* Comment: I added the monitor mode and changed the stuff below
19703 +* to look more like the orinoco driver
19704 +*----------------------------------------------------------------*/
19706 +acx_ioctl_get_iw_priv(struct iwreq *iwr)
19708 + int result = -EINVAL;
19710 + if (!iwr->u.data.pointer)
19712 + result = verify_area(VERIFY_WRITE, iwr->u.data.pointer,
19713 + sizeof(acx_ioctl_private_args));
19717 + iwr->u.data.length = VEC_SIZE(acx_ioctl_private_args);
19718 + if (copy_to_user(iwr->u.data.pointer, acx_ioctl_private_args, sizeof(acx_ioctl_private_args)) != 0)
19719 + result = -EFAULT;
19726 +/*----------------------------------------------------------------
19727 +* acx_ioctl_get_nick
19728 +*----------------------------------------------------------------*/
19730 +acx_ioctl_get_nick(
19731 + struct net_device *dev,
19732 + struct iw_request_info *info,
19733 + struct iw_point *dwrq,
19736 + wlandevice_t *priv = netdev_priv(dev);
19738 + /* FIXME : consider spinlock here */
19739 + strcpy(extra, priv->nick);
19740 + /* FIXME : consider spinlock here */
19742 + dwrq->length = strlen(extra) + 1;
19748 +/*----------------------------------------------------------------
19749 +* acx_ioctl_set_nick
19750 +*----------------------------------------------------------------*/
19752 +acx_ioctl_set_nick(
19753 + struct net_device *dev,
19754 + struct iw_request_info *info,
19755 + struct iw_point *dwrq,
19758 + wlandevice_t *priv = netdev_priv(dev);
19763 + acx_sem_lock(priv);
19765 + if (dwrq->length > IW_ESSID_MAX_SIZE + 1) {
19770 + /* extra includes trailing \0, so it's ok */
19771 + strcpy(priv->nick, extra);
19775 + acx_sem_unlock(priv);
19777 + FN_EXIT1(result);
19782 +/*------------------------------------------------------------------------------
19783 + * acx_ioctl_get_retry
19784 + *----------------------------------------------------------------------------*/
19786 +acx_ioctl_get_retry(
19787 + struct net_device *dev,
19788 + struct iw_request_info *info,
19789 + struct iw_param *vwrq,
19792 + wlandevice_t *priv = netdev_priv(dev);
19793 + unsigned int type = vwrq->flags & IW_RETRY_TYPE;
19794 + unsigned int modifier = vwrq->flags & IW_RETRY_MODIFIER;
19797 + acx_sem_lock(priv);
19799 + /* return the short retry number by default */
19800 + if (type == IW_RETRY_LIFETIME) {
19801 + vwrq->flags = IW_RETRY_LIFETIME;
19802 + vwrq->value = priv->msdu_lifetime;
19803 + } else if (modifier == IW_RETRY_MAX) {
19804 + vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
19805 + vwrq->value = priv->long_retry;
19807 + vwrq->flags = IW_RETRY_LIMIT;
19808 + if (priv->long_retry != priv->short_retry)
19809 + SET_BIT(vwrq->flags, IW_RETRY_MIN);
19810 + vwrq->value = priv->short_retry;
19813 + /* can't be disabled */
19814 + vwrq->disabled = (u8)0;
19817 + acx_sem_unlock(priv);
19823 +/*----------------------------------------------------------------
19824 +* acx_ioctl_set_retry
19825 +*----------------------------------------------------------------*/
19827 +acx_ioctl_set_retry(
19828 + struct net_device *dev,
19829 + struct iw_request_info *info,
19830 + struct iw_param *vwrq,
19833 + wlandevice_t *priv = netdev_priv(dev);
19839 + result = -EFAULT;
19842 + if (vwrq->disabled) {
19843 + result = -EINVAL;
19847 + acx_sem_lock(priv);
19849 + result = -EINVAL;
19850 + if (IW_RETRY_LIMIT == (vwrq->flags & IW_RETRY_TYPE)) {
19851 + printk("old retry limits: short %d long %d\n",
19852 + priv->short_retry, priv->long_retry);
19853 + if (vwrq->flags & IW_RETRY_MAX) {
19854 + priv->long_retry = vwrq->value;
19855 + } else if (vwrq->flags & IW_RETRY_MIN) {
19856 + priv->short_retry = vwrq->value;
19858 + /* no modifier: set both */
19859 + priv->long_retry = vwrq->value;
19860 + priv->short_retry = vwrq->value;
19862 + printk("new retry limits: short %d long %d\n",
19863 + priv->short_retry, priv->long_retry);
19864 + SET_BIT(priv->set_mask, GETSET_RETRY);
19865 + result = -EINPROGRESS;
19867 + else if (vwrq->flags & IW_RETRY_LIFETIME) {
19868 + priv->msdu_lifetime = vwrq->value;
19869 + printk("new MSDU lifetime: %d\n", priv->msdu_lifetime);
19870 + SET_BIT(priv->set_mask, SET_MSDU_LIFETIME);
19871 + result = -EINPROGRESS;
19874 + acx_sem_unlock(priv);
19876 + FN_EXIT1(result);
19881 +/******************************* private ioctls ******************************/
19884 +/*----------------------------------------------------------------
19885 +* acx_ioctl_set_debug
19886 +*----------------------------------------------------------------*/
19889 +acx_ioctl_set_debug(
19890 + struct net_device *dev,
19891 + struct iw_request_info *info,
19892 + struct iw_param *vwrq,
19895 + unsigned int debug_new = *((unsigned int *)extra);
19896 + int result = -EINVAL;
19898 + acxlog(L_ANY, "setting debug from %04X to %04X\n", acx_debug, debug_new);
19899 + acx_debug = debug_new;
19907 +/*----------------------------------------------------------------
19908 +* acx_ioctl_list_reg_domain
19909 +*----------------------------------------------------------------*/
19910 +static const char * const
19911 +reg_domain_strings[] = {
19912 + " 1-11 FCC (USA)",
19913 + " 1-11 DOC/IC (Canada)",
19914 + /* BTW: WLAN use in ETSI is regulated by
19915 + * ETSI standard EN 300 328-2 V1.1.2 */
19916 + " 1-13 ETSI (Europe)",
19919 + " 14 MKK (Japan)",
19921 + " 3-9 Israel (not all firmware versions)",
19922 + NULL /* needs to remain as last entry */
19926 +acx_ioctl_list_reg_domain(
19927 + struct net_device *dev,
19928 + struct iw_request_info *info,
19929 + struct iw_param *vwrq,
19934 + const char * const *entry = reg_domain_strings;
19936 + printk("dom# chan# domain/country\n");
19938 + printk("%4d %s\n", i++, *entry++);
19943 +/*----------------------------------------------------------------
19944 +* acx_ioctl_set_reg_domain
19945 +*----------------------------------------------------------------*/
19947 +acx_ioctl_set_reg_domain(
19948 + struct net_device *dev,
19949 + struct iw_request_info *info,
19950 + struct iw_param *vwrq,
19953 + wlandevice_t *priv = netdev_priv(dev);
19958 + if ((*extra < 1) || ((size_t)*extra > reg_domain_ids_len)) {
19959 + result = -EINVAL;
19963 + acx_sem_lock(priv);
19965 + priv->reg_dom_id = reg_domain_ids[*extra - 1];
19966 + SET_BIT(priv->set_mask, GETSET_REG_DOMAIN);
19968 + result = -EINPROGRESS;
19970 + acx_sem_unlock(priv);
19972 + FN_EXIT1(result);
19977 +/*----------------------------------------------------------------
19978 +* acx_ioctl_get_reg_domain
19979 +*----------------------------------------------------------------*/
19981 +acx_ioctl_get_reg_domain(
19982 + struct net_device *dev,
19983 + struct iw_request_info *info,
19984 + struct iw_param *vwrq,
19987 + wlandevice_t *priv = netdev_priv(dev);
19991 + dom = priv->reg_dom_id;
19993 + for (i=1; i <= 7; i++) {
19994 + if (reg_domain_ids[i-1] == dom) {
19995 + acxlog(L_IOCTL, "regulatory domain is currently set "
19996 + "to %d (0x%X): %s\n", i, dom,
19997 + reg_domain_strings[i-1]);
20007 +/*----------------------------------------------------------------
20008 +* acx_ioctl_set_short_preamble
20009 +*----------------------------------------------------------------*/
20010 +static const char * const
20011 +preamble_modes[] = {
20014 + "auto (peer capability dependent)",
20015 + "unknown mode, error"
20019 +acx_ioctl_set_short_preamble(
20020 + struct net_device *dev,
20021 + struct iw_request_info *info,
20022 + struct iw_param *vwrq,
20025 + wlandevice_t *priv = netdev_priv(dev);
20031 + if ((unsigned char)*extra > 2) {
20032 + result = -EINVAL;
20036 + acx_sem_lock(priv);
20038 + priv->preamble_mode = (u8)*extra;
20039 + switch (priv->preamble_mode) {
20040 + case 0: /* long */
20041 + priv->preamble_cur = 0;
20044 + /* short, kick incapable peers */
20045 + priv->preamble_cur = 1;
20046 + for (i = 0; i < VEC_SIZE(priv->sta_list); i++) {
20047 + client_t *clt = &priv->sta_list[i];
20048 + if (!clt->used) continue;
20049 + if (!(clt->cap_info & WF_MGMT_CAP_SHORT)) {
20050 + clt->used = CLIENT_EMPTY_SLOT_0;
20053 + switch (priv->mode) {
20054 + case ACX_MODE_2_STA:
20055 + if (priv->ap_client && !priv->ap_client->used) {
20056 + /* We kicked our AP :) */
20057 + SET_BIT(priv->set_mask, GETSET_RESCAN);
20061 + case 2: /* auto. short only if all peers are short-capable */
20062 + priv->preamble_cur = 1;
20063 + for (i = 0; i < VEC_SIZE(priv->sta_list); i++) {
20064 + client_t *clt = &priv->sta_list[i];
20065 + if (!clt->used) continue;
20066 + if (!(clt->cap_info & WF_MGMT_CAP_SHORT)) {
20067 + priv->preamble_cur = 0;
20073 + printk("new short preamble setting: configured %s, active %s\n",
20074 + preamble_modes[priv->preamble_mode],
20075 + preamble_modes[priv->preamble_cur]);
20078 + acx_sem_unlock(priv);
20080 + FN_EXIT1(result);
20085 +/*----------------------------------------------------------------
20086 +* acx_ioctl_get_short_preamble
20087 +*----------------------------------------------------------------*/
20089 +acx_ioctl_get_short_preamble(
20090 + struct net_device *dev,
20091 + struct iw_request_info *info,
20092 + struct iw_param *vwrq,
20095 + wlandevice_t *priv = netdev_priv(dev);
20097 + acx_sem_lock(priv);
20099 + printk("current short preamble setting: configured %s, active %s\n",
20100 + preamble_modes[priv->preamble_mode],
20101 + preamble_modes[priv->preamble_cur]);
20103 + *extra = (char)priv->preamble_mode;
20105 + acx_sem_unlock(priv);
20111 +/*----------------------------------------------------------------
20112 +* acx_ioctl_set_antenna
20114 +* Comment: TX and RX antenna can be set separately but this function good
20115 +* for testing 0-4 bits
20116 +*----------------------------------------------------------------*/
20118 +acx_ioctl_set_antenna(
20119 + struct net_device *dev,
20120 + struct iw_request_info *info,
20121 + struct iw_param *vwrq,
20124 + wlandevice_t *priv = netdev_priv(dev);
20126 + acx_sem_lock(priv);
20128 + printk("old antenna value: 0x%02X (COMBINED bit mask)\n"
20129 + "Rx antenna selection:\n"
20132 + "0x80 full diversity\n"
20133 + "0xc0 partial diversity\n"
20134 + "0x0f dwell time mask (in units of us)\n"
20135 + "Tx antenna selection:\n"
20136 + "0x00 ant. 2\n" /* yep, those ARE reversed! */
20138 + "new antenna value: 0x%02X\n",
20139 + priv->antenna, (u8)*extra);
20141 + priv->antenna = (u8)*extra;
20142 + SET_BIT(priv->set_mask, GETSET_ANTENNA);
20144 + acx_sem_unlock(priv);
20146 + return -EINPROGRESS;
20150 +/*----------------------------------------------------------------
20151 +* acx_ioctl_get_antenna
20152 +*----------------------------------------------------------------*/
20154 +acx_ioctl_get_antenna(
20155 + struct net_device *dev,
20156 + struct iw_request_info *info,
20157 + struct iw_param *vwrq,
20160 + wlandevice_t *priv = netdev_priv(dev);
20162 + /* no locking. it's pointless to lock a single load */
20163 + printk("current antenna value: 0x%02X (COMBINED bit mask)\n"
20164 + "Rx antenna selection:\n"
20167 + "0x80 full diversity\n"
20168 + "0xc0 partial diversity\n"
20169 + "Tx antenna selection:\n"
20170 + "0x00 ant. 2\n" /* yep, those ARE reversed! */
20171 + "0x20 ant. 1\n", priv->antenna);
20177 +/*----------------------------------------------------------------
20178 +* acx_ioctl_set_rx_antenna
20182 +* 0 = antenna1; 1 = antenna2; 2 = full diversity; 3 = partial diversity
20183 +* Comment: Could anybody test which antenna is the external one
20184 +*----------------------------------------------------------------*/
20186 +acx_ioctl_set_rx_antenna(
20187 + struct net_device *dev,
20188 + struct iw_request_info *info,
20189 + struct iw_param *vwrq,
20192 + wlandevice_t *priv = netdev_priv(dev);
20197 + if (*extra > 3) {
20198 + result = -EINVAL;
20202 + printk("old antenna value: 0x%02X\n", priv->antenna);
20204 + acx_sem_lock(priv);
20206 + priv->antenna &= 0x3f;
20207 + SET_BIT(priv->antenna, (*extra << 6));
20208 + SET_BIT(priv->set_mask, GETSET_ANTENNA);
20209 + printk("new antenna value: 0x%02X\n", priv->antenna);
20210 + result = -EINPROGRESS;
20212 + acx_sem_unlock(priv);
20214 + FN_EXIT1(result);
20219 +/*----------------------------------------------------------------
20220 +* acx_ioctl_set_tx_antenna
20223 +* Arguments: 0 == antenna2; 1 == antenna1;
20224 +* Comment: Could anybody test which antenna is the external one
20225 +*----------------------------------------------------------------*/
20227 +acx_ioctl_set_tx_antenna(
20228 + struct net_device *dev,
20229 + struct iw_request_info *info,
20230 + struct iw_param *vwrq,
20233 + wlandevice_t *priv = netdev_priv(dev);
20238 + if (*extra > 1) {
20239 + result = -EINVAL;
20243 + printk("old antenna value: 0x%02X\n", priv->antenna);
20245 + acx_sem_lock(priv);
20247 + priv->antenna &= ~0x30;
20248 + SET_BIT(priv->antenna, ((*extra & 0x01) << 5));
20249 + SET_BIT(priv->set_mask, GETSET_ANTENNA);
20250 + printk("new antenna value: 0x%02X\n", priv->antenna);
20251 + result = -EINPROGRESS;
20253 + acx_sem_unlock(priv);
20255 + FN_EXIT1(result);
20260 +/*----------------------------------------------------------------
20261 +* acx_ioctl_wlansniff
20263 +* can we just remove this in favor of monitor mode? --vda
20264 +*----------------------------------------------------------------*/
20266 +acx_ioctl_wlansniff(
20267 + struct net_device *dev,
20268 + struct iw_request_info *info,
20269 + struct iw_param *vwrq,
20272 + wlandevice_t *priv = netdev_priv(dev);
20273 + unsigned int *params = (unsigned int*)extra;
20274 + unsigned int enable = (unsigned int)(params[0] > 0);
20279 + acx_sem_lock(priv);
20281 + /* not using printk() here, since it distorts kismet display
20282 + * when printk messages activated */
20283 + acxlog(L_IOCTL, "setting monitor to: 0x%02X\n", params[0]);
20285 + switch (params[0]) {
20287 + priv->netdev->type = ARPHRD_ETHER;
20290 + priv->netdev->type = ARPHRD_IEEE80211_PRISM;
20293 + priv->netdev->type = ARPHRD_IEEE80211;
20298 + priv->mode = ACX_MODE_MONITOR;
20299 + SET_BIT(priv->set_mask, GETSET_MODE);
20303 + priv->channel = params[1];
20304 + SET_BIT(priv->set_mask, GETSET_RX);
20306 + result = -EINPROGRESS;
20308 + acx_sem_unlock(priv);
20310 + FN_EXIT1(result);
20315 +/*----------------------------------------------------------------
20316 +* acx_ioctl_unknown11
20317 +* FIXME: looks like some sort of "iwpriv kick_sta MAC" but it's broken
20318 +*----------------------------------------------------------------*/
20320 +acx_ioctl_unknown11(
20321 + struct net_device *dev,
20322 + struct iw_request_info *info,
20323 + struct iw_param *vwrq,
20327 + wlandevice_t *priv = netdev_priv(dev);
20328 + unsigned long flags;
20332 + acx_sem_lock(priv);
20333 + acx_lock(priv, flags);
20335 + acx_l_transmit_disassoc(priv, &client);
20338 + acx_unlock(priv, flags);
20339 + acx_sem_unlock(priv);
20347 +/***********************************************************************
20348 +** debug helper function to be able to debug various issues relatively easily
20351 +acx_ioctl_dbg_set_masks(
20352 + struct net_device *dev,
20353 + struct iw_request_info *info,
20354 + struct iw_param *vwrq,
20357 + wlandevice_t *priv = netdev_priv(dev);
20358 + const unsigned int *params = (unsigned int*)extra;
20361 + acx_sem_lock(priv);
20363 + acxlog(L_IOCTL, "setting flags in settings mask: "
20364 + "get_mask %08X set_mask %08X\n"
20365 + "before: get_mask %08X set_mask %08X\n",
20366 + params[0], params[1],
20367 + priv->get_mask, priv->set_mask);
20368 + SET_BIT(priv->get_mask, params[0]);
20369 + SET_BIT(priv->set_mask, params[1]);
20370 + acxlog(L_IOCTL, "after: get_mask %08X set_mask %08X\n",
20371 + priv->get_mask, priv->set_mask);
20372 + result = -EINPROGRESS; /* immediately call commit handler */
20374 + acx_sem_unlock(priv);
20380 +/*----------------------------------------------------------------
20381 +* acx_ioctl_set_rates
20383 +* This ioctl takes string parameter. Examples:
20384 +* iwpriv wlan0 SetRates "1,2"
20385 +* use 1 and 2 Mbit rates, both are in basic rate set
20386 +* iwpriv wlan0 SetRates "1,2 5,11"
20387 +* use 1,2,5.5,11 Mbit rates. 1 and 2 are basic
20388 +* iwpriv wlan0 SetRates "1,2 5c,11c"
20389 +* same ('c' means 'CCK modulation' and it is a default for 5 and 11)
20390 +* iwpriv wlan0 SetRates "1,2 5p,11p"
20391 +* use 1,2,5.5,11 Mbit, 1,2 are basic. 5 and 11 are using PBCC
20392 +* iwpriv wlan0 SetRates "1,2,5,11 22p"
20393 +* use 1,2,5.5,11,22 Mbit. 1,2,5.5 and 11 are basic. 22 is using PBCC
20394 +* (this is the maximum acx100 can do (modulo x4 mode))
20395 +* iwpriv wlan0 SetRates "1,2,5,11 22"
20396 +* same. 802.11 defines only PBCC modulation
20397 +* for 22 and 33 Mbit rates, so there is no ambiguity
20398 +* iwpriv wlan0 SetRates "1,2,5,11 6o,9o,12o,18o,24o,36o,48o,54o"
20399 +* 1,2,5.5 and 11 are basic. 11g OFDM rates are enabled but
20400 +* they are not in basic rate set. 22 Mbit is disabled.
20401 +* iwpriv wlan0 SetRates "1,2,5,11 6,9,12,18,24,36,48,54"
20402 +* same. OFDM is default for 11g rates except 22 and 33 Mbit,
20403 +* thus 'o' is optional
20404 +* iwpriv wlan0 SetRates "1,2,5,11 6d,9d,12d,18d,24d,36d,48d,54d"
20405 +* 1,2,5.5 and 11 are basic. 11g CCK-OFDM rates are enabled
20406 +* (acx111 does not support CCK-OFDM, driver will reject this cmd)
20407 +* iwpriv wlan0 SetRates "6,9,12 18,24,36,48,54"
20408 +* 6,9,12 are basic, rest of 11g rates is enabled. Using OFDM
20409 +*----------------------------------------------------------------*/
20410 +#include "setrate.c"
20412 +/* disallow: 33Mbit (unsupported by hw) */
20413 +/* disallow: CCKOFDM (unsupported by hw) */
20415 +acx111_supported(int mbit, int modulation, void *opaque)
20417 + if (mbit==33) return -ENOTSUPP;
20418 + if (modulation==DOT11_MOD_CCKOFDM) return -ENOTSUPP;
20424 + [DOT11_RATE_1 ] = RATE111_1 ,
20425 + [DOT11_RATE_2 ] = RATE111_2 ,
20426 + [DOT11_RATE_5 ] = RATE111_5 ,
20427 + [DOT11_RATE_11] = RATE111_11,
20428 + [DOT11_RATE_22] = RATE111_22,
20429 + /* [DOT11_RATE_33] = */
20430 + [DOT11_RATE_6 ] = RATE111_6 ,
20431 + [DOT11_RATE_9 ] = RATE111_9 ,
20432 + [DOT11_RATE_12] = RATE111_12,
20433 + [DOT11_RATE_18] = RATE111_18,
20434 + [DOT11_RATE_24] = RATE111_24,
20435 + [DOT11_RATE_36] = RATE111_36,
20436 + [DOT11_RATE_48] = RATE111_48,
20437 + [DOT11_RATE_54] = RATE111_54,
20441 +acx111_gen_mask(int mbit, int modulation, void *opaque)
20443 + /* lower 16 bits show selected 1, 2, CCK and OFDM rates */
20444 + /* upper 16 bits show selected PBCC rates */
20445 + u32 m = acx111mask[rate_mbit2enum(mbit)];
20446 + if (modulation==DOT11_MOD_PBCC)
20452 +verify_rate(u32 rate, int chip_type)
20454 + /* never happens. be paranoid */
20455 + if (!rate) return -EINVAL;
20457 + /* disallow: mixing PBCC and CCK at 5 and 11Mbit
20458 + ** (can be supported, but needs complicated handling in tx code) */
20459 + if (( rate & ((RATE111_11+RATE111_5)<<16) )
20460 + && ( rate & (RATE111_11+RATE111_5) )
20462 + return -ENOTSUPP;
20464 + if (CHIPTYPE_ACX100 == chip_type) {
20465 + if ( rate & ~(RATE111_ACX100_COMPAT+(RATE111_ACX100_COMPAT<<16)) )
20466 + return -ENOTSUPP;
20472 +acx_ioctl_set_rates(struct net_device *dev, struct iw_request_info *info,
20473 + struct iw_param *vwrq, char *extra)
20475 + wlandevice_t *priv = netdev_priv(dev);
20476 + unsigned long flags;
20478 + u32 brate = 0, orate = 0; /* basic, operational rate set */
20482 + acxlog(L_IOCTL, "set_rates %s\n", extra);
20483 + result = fill_ratemasks(extra, &brate, &orate,
20484 + acx111_supported, acx111_gen_mask, 0);
20485 + if (result) goto end;
20486 + SET_BIT(orate, brate);
20487 + acxlog(L_IOCTL, "brate %08X orate %08X\n", brate, orate);
20489 + result = verify_rate(brate, priv->chip_type);
20490 + if (result) goto end;
20491 + result = verify_rate(orate, priv->chip_type);
20492 + if (result) goto end;
20494 + acx_sem_lock(priv);
20495 + acx_lock(priv, flags);
20497 + priv->rate_basic = brate;
20498 + priv->rate_oper = orate;
20499 + /* TODO: ideally, we shall monitor highest basic rate
20500 + ** which was successfully sent to every peer
20501 + ** (say, last we checked, everybody could hear 5.5 Mbits)
20502 + ** and use that for bcasts when we want to reach all peers.
20503 + ** For beacons, we probably shall use lowest basic rate
20504 + ** because we want to reach all *potential* new peers too */
20505 + priv->rate_bcast = 1 << lowest_bit(brate);
20506 + if (IS_ACX100(priv))
20507 + priv->rate_bcast100 = acx_rate111to100(priv->rate_bcast);
20508 + priv->rate_auto = !has_only_one_bit(orate);
20509 + acx_l_update_client_rates(priv, orate);
20510 + /* TODO: get rid of ratevector, build it only when needed */
20511 + acx_l_update_ratevector(priv);
20513 + /* Do/don't do tx rate fallback; beacon contents and rate */
20514 + SET_BIT(priv->set_mask, SET_RATE_FALLBACK|SET_TEMPLATES);
20515 + result = -EINPROGRESS;
20517 + acx_unlock(priv, flags);
20518 + acx_sem_unlock(priv);
20520 + FN_EXIT1(result);
20525 +/*----------------------------------------------------------------
20526 +* acx_ioctl_get_phy_chan_busy_percentage
20527 +*----------------------------------------------------------------*/
20529 +acx_ioctl_get_phy_chan_busy_percentage(
20530 + struct net_device *dev,
20531 + struct iw_request_info *info,
20532 + struct iw_param *vwrq,
20535 + wlandevice_t *priv = netdev_priv(dev);
20536 + struct { /* added ACX_PACKED, not tested --vda */
20537 + u16 type ACX_PACKED;
20538 + u16 len ACX_PACKED;
20539 + u32 busytime ACX_PACKED;
20540 + u32 totaltime ACX_PACKED;
20543 + acx_sem_lock(priv);
20545 + if (OK != acx_s_interrogate(priv, &usage, ACX1xx_IE_MEDIUM_USAGE))
20548 + printk("%s: average busy percentage since last invocation: %d%% "
20549 + "(microseconds: %u of %u)\n",
20551 + 100 * (le32_to_cpu(usage.busytime) / 100) / (le32_to_cpu(usage.totaltime) / 100),
20552 + le32_to_cpu(usage.busytime), le32_to_cpu(usage.totaltime));
20553 + /* prevent calculation overflow */
20555 + acx_sem_unlock(priv);
20560 + acx_sem_unlock(priv);
20566 +/*----------------------------------------------------------------
20567 +* acx_ioctl_set_ed_threshold
20568 +*----------------------------------------------------------------*/
20570 +acx_ioctl_set_ed_threshold(
20571 + struct net_device *dev,
20572 + struct iw_request_info *info,
20573 + struct iw_param *vwrq,
20576 + wlandevice_t *priv = netdev_priv(dev);
20578 + acx_sem_lock(priv);
20580 + printk("old ED threshold value: %d\n", priv->ed_threshold);
20581 + priv->ed_threshold = (unsigned char)*extra;
20582 + printk("new ED threshold value: %d\n", (unsigned char)*extra);
20583 + SET_BIT(priv->set_mask, GETSET_ED_THRESH);
20585 + acx_sem_unlock(priv);
20587 + return -EINPROGRESS;
20591 +/*----------------------------------------------------------------
20592 +* acx_ioctl_set_cca
20593 +*----------------------------------------------------------------*/
20595 +acx_ioctl_set_cca(
20596 + struct net_device *dev,
20597 + struct iw_request_info *info,
20598 + struct iw_param *vwrq,
20601 + wlandevice_t *priv = netdev_priv(dev);
20604 + acx_sem_lock(priv);
20606 + printk("old CCA value: 0x%02X\n", priv->cca);
20607 + priv->cca = (unsigned char)*extra;
20608 + printk("new CCA value: 0x%02X\n", (unsigned char)*extra);
20609 + SET_BIT(priv->set_mask, GETSET_CCA);
20610 + result = -EINPROGRESS;
20612 + acx_sem_unlock(priv);
20618 +/***********************************************************************
20620 +static const char * const
20621 +scan_modes[] = { "active", "passive", "background" };
20624 +acx_print_scan_params(wlandevice_t *priv, const char* head)
20626 + printk("%s: %smode %d (%s), min chan time %dTU, "
20627 + "max chan time %dTU, max scan rate byte: %d\n",
20628 + priv->netdev->name, head,
20629 + priv->scan_mode, scan_modes[priv->scan_mode],
20630 + priv->scan_probe_delay, priv->scan_duration, priv->scan_rate);
20634 +acx_ioctl_set_scan_params(
20635 + struct net_device *dev,
20636 + struct iw_request_info *info,
20637 + struct iw_param *vwrq,
20640 + wlandevice_t *priv = netdev_priv(dev);
20642 + const int *params = (int *)extra;
20644 + acx_sem_lock(priv);
20646 + acx_print_scan_params(priv, "old scan parameters: ");
20647 + if ((params[0] != -1) && (params[0] >= 0) && (params[0] <= 2))
20648 + priv->scan_mode = params[0];
20649 + if (params[1] != -1)
20650 + priv->scan_probe_delay = params[1];
20651 + if (params[2] != -1)
20652 + priv->scan_duration = params[2];
20653 + if ((params[3] != -1) && (params[3] <= 255))
20654 + priv->scan_rate = params[3];
20655 + acx_print_scan_params(priv, "new scan parameters: ");
20656 + SET_BIT(priv->set_mask, GETSET_RESCAN);
20657 + result = -EINPROGRESS;
20659 + acx_sem_unlock(priv);
20665 +acx_ioctl_get_scan_params(
20666 + struct net_device *dev,
20667 + struct iw_request_info *info,
20668 + struct iw_param *vwrq,
20671 + wlandevice_t *priv = netdev_priv(dev);
20673 + int *params = (int *)extra;
20675 + acx_sem_lock(priv);
20677 + acx_print_scan_params(priv, "current scan parameters: ");
20678 + params[0] = priv->scan_mode;
20679 + params[1] = priv->scan_probe_delay;
20680 + params[2] = priv->scan_duration;
20681 + params[3] = priv->scan_rate;
20684 + acx_sem_unlock(priv);
20690 +/***********************************************************************
20693 +acx100_ioctl_set_led_power(
20694 + struct net_device *dev,
20695 + struct iw_request_info *info,
20696 + struct iw_param *vwrq,
20699 + static const char * const led_modes[] = { "off", "on", "LinkQuality" };
20701 + wlandevice_t *priv = netdev_priv(dev);
20704 + acx_sem_lock(priv);
20706 + printk("%s: power LED status: old %d (%s), ",
20709 + led_modes[priv->led_power]);
20710 + priv->led_power = extra[0];
20711 + if (priv->led_power > 2) priv->led_power = 2;
20712 + printk("new %d (%s)\n",
20714 + led_modes[priv->led_power]);
20716 + if (priv->led_power == 2) {
20717 + printk("%s: max link quality setting: old %d, ",
20718 + dev->name, priv->brange_max_quality);
20720 + priv->brange_max_quality = extra[1];
20721 + printk("new %d\n", priv->brange_max_quality);
20724 + SET_BIT(priv->set_mask, GETSET_LED_POWER);
20726 + result = -EINPROGRESS;
20728 + acx_sem_unlock(priv);
20734 +/***********************************************************************
20737 +acx100_ioctl_get_led_power(
20738 + struct net_device *dev,
20739 + struct iw_request_info *info,
20740 + struct iw_param *vwrq,
20743 + wlandevice_t *priv = netdev_priv(dev);
20745 + acx_sem_lock(priv);
20747 + extra[0] = priv->led_power;
20748 + if (priv->led_power == 2)
20749 + extra[1] = priv->brange_max_quality;
20753 + acx_sem_unlock(priv);
20759 +/***********************************************************************
20762 +acx111_ioctl_info(
20763 + struct net_device *dev,
20764 + struct iw_request_info *info,
20765 + struct iw_param *vwrq,
20768 + if (!IS_PCI((wlandevice_t*)netdev_priv(dev)))
20770 + return acx111pci_ioctl_info(dev, info, vwrq, extra);
20774 +/***********************************************************************
20777 +acx100_ioctl_set_phy_amp_bias(
20778 + struct net_device *dev,
20779 + struct iw_request_info *info,
20780 + struct iw_param *vwrq,
20783 + if (!IS_PCI((wlandevice_t*)netdev_priv(dev))) {
20784 + printk("acx: set_phy_amp_bias() is not supported on USB\n");
20787 + return acx100pci_ioctl_set_phy_amp_bias(dev, info, vwrq, extra);
20791 +/***********************************************************************
20793 +#if WIRELESS_EXT >= 13
20794 +static const iw_handler acx_ioctl_handler[] =
20796 + (iw_handler) acx_ioctl_commit, /* SIOCSIWCOMMIT */
20797 + (iw_handler) acx_ioctl_get_name, /* SIOCGIWNAME */
20798 + (iw_handler) NULL, /* SIOCSIWNWID */
20799 + (iw_handler) NULL, /* SIOCGIWNWID */
20800 + (iw_handler) acx_ioctl_set_freq, /* SIOCSIWFREQ */
20801 + (iw_handler) acx_ioctl_get_freq, /* SIOCGIWFREQ */
20802 + (iw_handler) acx_ioctl_set_mode, /* SIOCSIWMODE */
20803 + (iw_handler) acx_ioctl_get_mode, /* SIOCGIWMODE */
20804 + (iw_handler) acx_ioctl_set_sens, /* SIOCSIWSENS */
20805 + (iw_handler) acx_ioctl_get_sens, /* SIOCGIWSENS */
20806 + (iw_handler) NULL, /* SIOCSIWRANGE */
20807 + (iw_handler) acx_ioctl_get_range, /* SIOCGIWRANGE */
20808 + (iw_handler) NULL, /* SIOCSIWPRIV */
20809 + (iw_handler) NULL, /* SIOCGIWPRIV */
20810 + (iw_handler) NULL, /* SIOCSIWSTATS */
20811 + (iw_handler) NULL, /* SIOCGIWSTATS */
20812 +#if IW_HANDLER_VERSION > 4
20813 + iw_handler_set_spy, /* SIOCSIWSPY */
20814 + iw_handler_get_spy, /* SIOCGIWSPY */
20815 + iw_handler_set_thrspy, /* SIOCSIWTHRSPY */
20816 + iw_handler_get_thrspy, /* SIOCGIWTHRSPY */
20817 +#else /* IW_HANDLER_VERSION > 4 */
20818 +#ifdef WIRELESS_SPY
20819 + (iw_handler) NULL /* acx_ioctl_set_spy FIXME */, /* SIOCSIWSPY */
20820 + (iw_handler) NULL /* acx_ioctl_get_spy FIXME */, /* SIOCGIWSPY */
20822 + (iw_handler) NULL, /* SIOCSIWSPY */
20823 + (iw_handler) NULL, /* SIOCGIWSPY */
20825 + (iw_handler) NULL, /* [nothing] */
20826 + (iw_handler) NULL, /* [nothing] */
20827 +#endif /* IW_HANDLER_VERSION > 4 */
20828 + (iw_handler) acx_ioctl_set_ap, /* SIOCSIWAP */
20829 + (iw_handler) acx_ioctl_get_ap, /* SIOCGIWAP */
20830 + (iw_handler) NULL, /* [nothing] */
20831 + (iw_handler) acx_ioctl_get_aplist, /* SIOCGIWAPLIST */
20832 +#if WIRELESS_EXT > 13
20833 + (iw_handler) acx_ioctl_set_scan, /* SIOCSIWSCAN */
20834 + (iw_handler) acx_ioctl_get_scan, /* SIOCGIWSCAN */
20835 +#else /* WE > 13 */
20836 + (iw_handler) NULL, /* SIOCSIWSCAN */
20837 + (iw_handler) NULL, /* SIOCGIWSCAN */
20838 +#endif /* WE > 13 */
20839 + (iw_handler) acx_ioctl_set_essid, /* SIOCSIWESSID */
20840 + (iw_handler) acx_ioctl_get_essid, /* SIOCGIWESSID */
20841 + (iw_handler) acx_ioctl_set_nick, /* SIOCSIWNICKN */
20842 + (iw_handler) acx_ioctl_get_nick, /* SIOCGIWNICKN */
20843 + (iw_handler) NULL, /* [nothing] */
20844 + (iw_handler) NULL, /* [nothing] */
20845 + (iw_handler) acx_ioctl_set_rate, /* SIOCSIWRATE */
20846 + (iw_handler) acx_ioctl_get_rate, /* SIOCGIWRATE */
20847 + (iw_handler) acx_ioctl_set_rts, /* SIOCSIWRTS */
20848 + (iw_handler) acx_ioctl_get_rts, /* SIOCGIWRTS */
20849 + (iw_handler) NULL /* acx_ioctl_set_frag FIXME */, /* SIOCSIWFRAG */
20850 + (iw_handler) NULL /* acx_ioctl_get_frag FIXME */, /* SIOCGIWFRAG */
20851 + (iw_handler) acx_ioctl_set_txpow, /* SIOCSIWTXPOW */
20852 + (iw_handler) acx_ioctl_get_txpow, /* SIOCGIWTXPOW */
20853 + (iw_handler) acx_ioctl_set_retry, /* SIOCSIWRETRY */
20854 + (iw_handler) acx_ioctl_get_retry, /* SIOCGIWRETRY */
20855 + (iw_handler) acx_ioctl_set_encode, /* SIOCSIWENCODE */
20856 + (iw_handler) acx_ioctl_get_encode, /* SIOCGIWENCODE */
20857 + (iw_handler) acx_ioctl_set_power, /* SIOCSIWPOWER */
20858 + (iw_handler) acx_ioctl_get_power, /* SIOCGIWPOWER */
20861 +static const iw_handler acx_ioctl_private_handler[] =
20864 +[ACX100_IOCTL_DEBUG - ACX100_IOCTL] = (iw_handler) acx_ioctl_set_debug,
20866 +[ACX100_IOCTL_DEBUG - ACX100_IOCTL] = (iw_handler) NULL,
20868 +[ACX100_IOCTL_SET_PLED - ACX100_IOCTL] = (iw_handler) acx100_ioctl_set_led_power,
20869 +[ACX100_IOCTL_GET_PLED - ACX100_IOCTL] = (iw_handler) acx100_ioctl_get_led_power,
20870 +[ACX100_IOCTL_SET_RATES - ACX100_IOCTL] = (iw_handler) acx_ioctl_set_rates,
20871 +[ACX100_IOCTL_LIST_DOM - ACX100_IOCTL] = (iw_handler) acx_ioctl_list_reg_domain,
20872 +[ACX100_IOCTL_SET_DOM - ACX100_IOCTL] = (iw_handler) acx_ioctl_set_reg_domain,
20873 +[ACX100_IOCTL_GET_DOM - ACX100_IOCTL] = (iw_handler) acx_ioctl_get_reg_domain,
20874 +[ACX100_IOCTL_SET_SCAN_PARAMS - ACX100_IOCTL] = (iw_handler) acx_ioctl_set_scan_params,
20875 +[ACX100_IOCTL_GET_SCAN_PARAMS - ACX100_IOCTL] = (iw_handler) acx_ioctl_get_scan_params,
20876 +[ACX100_IOCTL_SET_PREAMB - ACX100_IOCTL] = (iw_handler) acx_ioctl_set_short_preamble,
20877 +[ACX100_IOCTL_GET_PREAMB - ACX100_IOCTL] = (iw_handler) acx_ioctl_get_short_preamble,
20878 +[ACX100_IOCTL_SET_ANT - ACX100_IOCTL] = (iw_handler) acx_ioctl_set_antenna,
20879 +[ACX100_IOCTL_GET_ANT - ACX100_IOCTL] = (iw_handler) acx_ioctl_get_antenna,
20880 +[ACX100_IOCTL_RX_ANT - ACX100_IOCTL] = (iw_handler) acx_ioctl_set_rx_antenna,
20881 +[ACX100_IOCTL_TX_ANT - ACX100_IOCTL] = (iw_handler) acx_ioctl_set_tx_antenna,
20882 +[ACX100_IOCTL_SET_PHY_AMP_BIAS - ACX100_IOCTL] = (iw_handler) acx100_ioctl_set_phy_amp_bias,
20883 +[ACX100_IOCTL_GET_PHY_CHAN_BUSY - ACX100_IOCTL] = (iw_handler) acx_ioctl_get_phy_chan_busy_percentage,
20884 +[ACX100_IOCTL_SET_ED - ACX100_IOCTL] = (iw_handler) acx_ioctl_set_ed_threshold,
20885 +[ACX100_IOCTL_SET_CCA - ACX100_IOCTL] = (iw_handler) acx_ioctl_set_cca,
20886 +[ACX100_IOCTL_MONITOR - ACX100_IOCTL] = (iw_handler) acx_ioctl_wlansniff,
20887 +[ACX100_IOCTL_TEST - ACX100_IOCTL] = (iw_handler) acx_ioctl_unknown11,
20888 +[ACX100_IOCTL_DBG_SET_MASKS - ACX100_IOCTL] = (iw_handler) acx_ioctl_dbg_set_masks,
20889 +[ACX111_IOCTL_INFO - ACX100_IOCTL] = (iw_handler) acx111_ioctl_info,
20892 +const struct iw_handler_def acx_ioctl_handler_def =
20894 + .num_standard = VEC_SIZE(acx_ioctl_handler),
20895 + .num_private = VEC_SIZE(acx_ioctl_private_handler),
20896 + .num_private_args = VEC_SIZE(acx_ioctl_private_args),
20897 + .standard = (iw_handler *) acx_ioctl_handler,
20898 + .private = (iw_handler *) acx_ioctl_private_handler,
20899 + .private_args = (struct iw_priv_args *) acx_ioctl_private_args,
20902 +#endif /* WE >= 13 */
20905 +#if WIRELESS_EXT < 13
20906 +/*================================================================*/
20907 +/* Main function */
20908 +/*================================================================*/
20909 +/*----------------------------------------------------------------
20913 +* This is the *OLD* ioctl handler.
20914 +* Make sure to not only place your additions here, but instead mainly
20915 +* in the new one (acx_ioctl_handler[])!
20916 +*----------------------------------------------------------------*/
20918 +acx_e_ioctl_old(netdevice_t *dev, struct ifreq *ifr, int cmd)
20920 + wlandevice_t *priv = netdev_priv(dev);
20922 + struct iwreq *iwr = (struct iwreq *)ifr;
20924 + acxlog(L_IOCTL, "%s cmd = 0x%04X\n", __func__, cmd);
20926 + /* This is the way it is done in the orinoco driver.
20927 + * Check to see if device is present.
20929 + if (0 == netif_device_present(dev)) {
20934 +/* WE 13 and higher will use acx_ioctl_handler_def */
20935 + case SIOCGIWNAME:
20936 + /* get name == wireless protocol */
20937 + result = acx_ioctl_get_name(dev, NULL,
20938 + (char *)&(iwr->u.name), NULL);
20941 + case SIOCSIWNWID: /* pre-802.11, */
20942 + case SIOCGIWNWID: /* not supported. */
20943 + result = -EOPNOTSUPP;
20946 + case SIOCSIWFREQ:
20947 + /* set channel/frequency (Hz)
20948 + data can be frequency or channel :
20950 + > 1000 = frequency in Hz */
20951 + result = acx_ioctl_set_freq(dev, NULL, &(iwr->u.freq), NULL);
20954 + case SIOCGIWFREQ:
20955 + /* get channel/frequency (Hz) */
20956 + result = acx_ioctl_get_freq(dev, NULL, &(iwr->u.freq), NULL);
20959 + case SIOCSIWMODE:
20960 + /* set operation mode */
20961 + result = acx_ioctl_set_mode(dev, NULL, &(iwr->u.mode), NULL);
20964 + case SIOCGIWMODE:
20965 + /* get operation mode */
20966 + result = acx_ioctl_get_mode(dev, NULL, &(iwr->u.mode), NULL);
20969 + case SIOCSIWSENS:
20970 + /* Set sensitivity */
20971 + result = acx_ioctl_set_sens(dev, NULL, &(iwr->u.sens), NULL);
20974 + case SIOCGIWSENS:
20975 + /* Get sensitivity */
20976 + result = acx_ioctl_get_sens(dev, NULL, &(iwr->u.sens), NULL);
20979 +#if WIRELESS_EXT > 10
20980 + case SIOCGIWRANGE:
20981 + /* Get range of parameters */
20983 + struct iw_range range;
20984 + result = acx_ioctl_get_range(dev, NULL,
20985 + &(iwr->u.data), (char *)&range);
20986 + if (copy_to_user(iwr->u.data.pointer, &range,
20987 + sizeof(struct iw_range)))
20988 + result = -EFAULT;
20993 + case SIOCGIWPRIV:
20994 + result = acx_ioctl_get_iw_priv(iwr);
20998 + /* case SIOCSIWSPY: */
20999 + /* case SIOCGIWSPY: */
21000 + /* case SIOCSIWTHRSPY: */
21001 + /* case SIOCGIWTHRSPY: */
21004 + /* set access point by MAC address */
21005 + result = acx_ioctl_set_ap(dev, NULL, &(iwr->u.ap_addr),
21010 + /* get access point MAC address */
21011 + result = acx_ioctl_get_ap(dev, NULL, &(iwr->u.ap_addr),
21015 + case SIOCGIWAPLIST:
21016 + /* get list of access points in range */
21017 + result = acx_ioctl_get_aplist(dev, NULL, &(iwr->u.data),
21021 +#if NOT_FINISHED_YET
21022 + /* FIXME: do proper interfacing to activate that! */
21023 + case SIOCSIWSCAN:
21024 + /* start a station scan */
21025 + result = acx_ioctl_set_scan(iwr, priv);
21028 + case SIOCGIWSCAN:
21029 + /* get list of stations found during scan */
21030 + result = acx_ioctl_get_scan(iwr, priv);
21034 + case SIOCSIWESSID:
21035 + /* set ESSID (network name) */
21037 + char essid[IW_ESSID_MAX_SIZE+1];
21039 + if (iwr->u.essid.length > IW_ESSID_MAX_SIZE)
21044 + if (copy_from_user(essid, iwr->u.essid.pointer,
21045 + iwr->u.essid.length))
21047 + result = -EFAULT;
21050 + result = acx_ioctl_set_essid(dev, NULL,
21051 + &(iwr->u.essid), essid);
21055 + case SIOCGIWESSID:
21058 + char essid[IW_ESSID_MAX_SIZE+1];
21059 + if (iwr->u.essid.pointer)
21060 + result = acx_ioctl_get_essid(dev, NULL,
21061 + &(iwr->u.essid), essid);
21062 + if (copy_to_user(iwr->u.essid.pointer, essid,
21063 + iwr->u.essid.length))
21064 + result = -EFAULT;
21068 + case SIOCSIWNICKN:
21071 + char nick[IW_ESSID_MAX_SIZE+1];
21073 + if (iwr->u.data.length > IW_ESSID_MAX_SIZE)
21078 + if (copy_from_user(nick, iwr->u.data.pointer,
21079 + iwr->u.data.length))
21081 + result = -EFAULT;
21084 + result = acx_ioctl_set_nick(dev, NULL,
21085 + &(iwr->u.data), nick);
21089 + case SIOCGIWNICKN:
21092 + char nick[IW_ESSID_MAX_SIZE+1];
21093 + if (iwr->u.data.pointer)
21094 + result = acx_ioctl_get_nick(dev, NULL,
21095 + &(iwr->u.data), nick);
21096 + if (copy_to_user(iwr->u.data.pointer, nick,
21097 + iwr->u.data.length))
21098 + result = -EFAULT;
21102 + case SIOCSIWRATE:
21103 + /* set default bit rate (bps) */
21104 + result = acx_ioctl_set_rate(dev, NULL, &(iwr->u.bitrate),
21108 + case SIOCGIWRATE:
21109 + /* get default bit rate (bps) */
21110 + result = acx_ioctl_get_rate(dev, NULL, &(iwr->u.bitrate),
21115 + /* set RTS threshold value */
21116 + result = acx_ioctl_set_rts(dev, NULL, &(iwr->u.rts), NULL);
21119 + /* get RTS threshold value */
21120 + result = acx_ioctl_get_rts(dev, NULL, &(iwr->u.rts), NULL);
21124 + /* case SIOCSIWFRAG: */
21125 + /* case SIOCGIWFRAG: */
21127 +#if WIRELESS_EXT > 9
21128 + case SIOCGIWTXPOW:
21129 + /* get tx power */
21130 + result = acx_ioctl_get_txpow(dev, NULL, &(iwr->u.txpower),
21134 + case SIOCSIWTXPOW:
21135 + /* set tx power */
21136 + result = acx_ioctl_set_txpow(dev, NULL, &(iwr->u.txpower),
21141 + case SIOCSIWRETRY:
21142 + result = acx_ioctl_set_retry(dev, NULL, &(iwr->u.retry), NULL);
21145 + case SIOCGIWRETRY:
21146 + result = acx_ioctl_get_retry(dev, NULL, &(iwr->u.retry), NULL);
21149 + case SIOCSIWENCODE:
21151 + /* set encoding token & mode */
21153 + if (iwr->u.encoding.pointer) {
21154 + if (iwr->u.encoding.length > 29) {
21158 + if (copy_from_user(key, iwr->u.encoding.pointer,
21159 + iwr->u.encoding.length)) {
21160 + result = -EFAULT;
21165 + if (iwr->u.encoding.length) {
21166 + result = -EINVAL;
21169 + result = acx_ioctl_set_encode(dev, NULL,
21170 + &(iwr->u.encoding), key);
21174 + case SIOCGIWENCODE:
21176 + /* get encoding token & mode */
21179 + result = acx_ioctl_get_encode(dev, NULL,
21180 + &(iwr->u.encoding), key);
21181 + if (iwr->u.encoding.pointer) {
21182 + if (copy_to_user(iwr->u.encoding.pointer,
21183 + key, iwr->u.encoding.length))
21184 + result = -EFAULT;
21189 + /******************** iwpriv ioctls below ********************/
21191 + case ACX100_IOCTL_DEBUG:
21192 + acx_ioctl_set_debug(dev, NULL, NULL, iwr->u.name);
21196 + case ACX100_IOCTL_SET_PLED:
21197 + acx100_ioctl_set_led_power(dev, NULL, NULL, iwr->u.name);
21200 + case ACX100_IOCTL_GET_PLED:
21201 + acx100_ioctl_get_led_power(dev, NULL, NULL, iwr->u.name);
21204 + case ACX100_IOCTL_LIST_DOM:
21205 + acx_ioctl_list_reg_domain(dev, NULL, NULL, NULL);
21208 + case ACX100_IOCTL_SET_DOM:
21209 + acx_ioctl_set_reg_domain(dev, NULL, NULL, iwr->u.name);
21212 + case ACX100_IOCTL_GET_DOM:
21213 + acx_ioctl_get_reg_domain(dev, NULL, NULL, iwr->u.name);
21216 + case ACX100_IOCTL_SET_SCAN_PARAMS:
21217 + acx_ioctl_set_scan_params(dev, NULL, NULL, iwr->u.name);
21220 + case ACX100_IOCTL_GET_SCAN_PARAMS:
21221 + acx_ioctl_get_scan_params(dev, NULL, NULL, iwr->u.name);
21224 + case ACX100_IOCTL_SET_PREAMB:
21225 + acx_ioctl_set_short_preamble(dev, NULL, NULL, iwr->u.name);
21228 + case ACX100_IOCTL_GET_PREAMB:
21229 + acx_ioctl_get_short_preamble(dev, NULL, NULL, iwr->u.name);
21232 + case ACX100_IOCTL_SET_ANT:
21233 + acx_ioctl_set_antenna(dev, NULL, NULL, iwr->u.name);
21236 + case ACX100_IOCTL_GET_ANT:
21237 + acx_ioctl_get_antenna(dev, NULL, NULL, NULL);
21240 + case ACX100_IOCTL_RX_ANT:
21241 + acx_ioctl_set_rx_antenna(dev, NULL, NULL, iwr->u.name);
21244 + case ACX100_IOCTL_TX_ANT:
21245 + acx_ioctl_set_tx_antenna(dev, NULL, NULL, iwr->u.name);
21248 + case ACX100_IOCTL_SET_ED:
21249 + acx_ioctl_set_ed_threshold(dev, NULL, NULL, iwr->u.name);
21252 + case ACX100_IOCTL_SET_CCA:
21253 + acx_ioctl_set_cca(dev, NULL, NULL, iwr->u.name);
21256 + case ACX100_IOCTL_MONITOR: /* set sniff (monitor) mode */
21257 + acxlog(L_IOCTL, "%s: IWPRIV monitor\n", dev->name);
21259 + /* can only be done by admin */
21260 + if (!capable(CAP_NET_ADMIN)) {
21264 + result = acx_ioctl_wlansniff(dev, NULL, NULL, iwr->u.name);
21267 + case ACX100_IOCTL_TEST:
21268 + acx_ioctl_unknown11(dev, NULL, NULL, NULL);
21271 + case ACX111_IOCTL_INFO:
21272 + acx111_ioctl_info(dev, NULL, NULL, NULL);
21276 + acxlog(L_IOCTL, "wireless ioctl 0x%04X queried "
21277 + "but not implemented yet\n", cmd);
21278 + result = -EOPNOTSUPP;
21282 + if ((priv->dev_state_mask & ACX_STATE_IFACE_UP) && priv->set_mask) {
21283 + acx_sem_lock(priv);
21284 + acx_s_update_card_settings(priv, 0, 0);
21285 + acx_sem_unlock(priv);
21288 + /* older WEs don't have a commit handler,
21289 + * so we need to fix return code in this case */
21290 + if (-EINPROGRESS == result)
21295 +#endif /* WE < 13 */
21296 diff -Naur linux-2.6.14-omap2/drivers/net/wireless/tiacx/Kconfig linux-h6300-omap2-2.6.14.3/drivers/net/wireless/tiacx/Kconfig
21297 --- linux-2.6.14-omap2/drivers/net/wireless/tiacx/Kconfig 1970-01-01 02:00:00.000000000 +0200
21298 +++ linux-h6300-omap2-2.6.14.3/drivers/net/wireless/tiacx/Kconfig 2005-09-28 23:54:23.000000000 +0300
21301 + tristate "TI acx100/acx111 802.11b/g wireless chipsets"
21302 + depends on NET_RADIO && EXPERIMENTAL && FW_LOADER
21304 + A driver for 802.11b/g wireless cards based on
21305 + Texas Instruments acx100 and acx111 chipsets.
21307 + This driver supports Host AP mode that allows
21308 + your computer to act as an IEEE 802.11 access point.
21309 + This driver is quite new and experimental.
21311 + These chipsets need their firmware loaded at startup.
21312 + You will need to provide a firmware image via hotplug.
21314 + Firmware may be in a form of single image 40-100kb in size
21315 + (a 'combined' firmware) or two images - main image
21316 + (again 40-100kb) and radio image (~10kb or less).
21318 + Firmware images are requested from hotplug using following names:
21320 + tiacx100 - main firmware image for acx100 chipset
21321 + tiacx100rNN - radio acx100 firmware for radio type NN
21322 + tiacx100cNN - combined acx100 firmware for radio type NN
21323 + tiacx111 - main acx111 firmware
21324 + tiacx111rNN - radio acx111 firmware for radio type NN
21325 + tiacx111cNN - combined acx111 firmware for radio type NN
21327 + Driver will attempt to load combined image first.
21328 + If no such image is found, it will try to load main image
21329 + and radio image instead.
21331 + Firmware files are not covered by GPL and are not distributed
21332 + with this driver for legal reasons.
21334 + Texas Instruments did not take part in development of this driver
21335 + in any way, shape or form.
21337 + The driver can be compiled as a module and will be named "acx".
21340 + bool "TI acx100/acx111 802.11b/g PCI"
21341 + depends on PCI && ACX
21343 + Include PCI and CardBus support in acx.
21346 + bool "TI acx100/acx111 802.11b/g USB"
21347 + depends on USB && ACX && BROKEN
21349 + Include USB support in acx.
21351 + There is only one currently known device in this category,
21352 + D-Link DWL-120+, but newer devices seem to be on the horizon.
21355 + bool "TI acx100 802.11b/g Compact Flash"
21358 + Include Compact Flash support.
21359 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
21360 --- linux-2.6.14-omap2/drivers/net/wireless/tiacx/macros.h 1970-01-01 02:00:00.000000000 +0200
21361 +++ linux-h6300-omap2-2.6.14.3/drivers/net/wireless/tiacx/macros.h 2005-09-28 23:54:23.000000000 +0300
21368 +#define HW_SLAVE_REG_ADDR_REG 0x00000004
21369 +#define HW_SLAVE_REG_DATA_REG 0x00000008
21370 +#define HW_SLAVE_REG_CTRL_REG 0x0000000c
21371 +#define HW_SLAVE_MEM_ADDR_REG 0x00000014
21372 +#define HW_SLAVE_MEM_DATA_REG 0x00000018
21374 +#define REG_LO(b,r) ((u8 *) b + r)
21375 +#define REG_HI(b,r) ((u8 *) b + r + 2)
21377 +static inline u32 acx_readl(unsigned char *iobase, unsigned int reg)
21381 + writew( 0, REG_LO(iobase, HW_SLAVE_REG_CTRL_REG));
21382 + writew( 1, REG_HI(iobase,HW_SLAVE_REG_CTRL_REG));
21384 + writew( reg, REG_LO(iobase, HW_SLAVE_REG_ADDR_REG));
21385 + writew( 0, REG_HI(iobase,HW_SLAVE_REG_ADDR_REG));
21387 + lo = readw(REG_LO(iobase,HW_SLAVE_REG_DATA_REG));
21388 + hi = readw(REG_HI(iobase,HW_SLAVE_REG_DATA_REG));
21390 + printk("hi=%04x,lo=%04x\n",hi,lo);
21392 + return ((u32)hi<<16) | lo;
21396 diff -Naur linux-2.6.14-omap2/drivers/net/wireless/tiacx/Makefile linux-h6300-omap2-2.6.14.3/drivers/net/wireless/tiacx/Makefile
21397 --- linux-2.6.14-omap2/drivers/net/wireless/tiacx/Makefile 1970-01-01 02:00:00.000000000 +0200
21398 +++ linux-h6300-omap2-2.6.14.3/drivers/net/wireless/tiacx/Makefile 2005-09-28 23:54:23.000000000 +0300
21400 +#Use this if you have proper Kconfig integration:
21402 +obj-$(CONFIG_ACX) += acx.o
21404 +acx-obj-$(CONFIG_ACX_PCI) += pci.o
21405 +acx-obj-$(CONFIG_ACX_USB) += usb.o
21406 +acx-obj-$(CONFIG_ACX_CFI) += cfi.o
21408 +acx-objs := wlan.o conv.o ioctl.o common.o $(acx-obj-y)
21409 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
21410 --- linux-2.6.14-omap2/drivers/net/wireless/tiacx/pci.c 1970-01-01 02:00:00.000000000 +0200
21411 +++ linux-h6300-omap2-2.6.14.3/drivers/net/wireless/tiacx/pci.c 2005-09-28 23:54:23.000000000 +0300
21413 +/***********************************************************************
21414 +** Copyright (C) 2003 ACX100 Open Source Project
21416 +** The contents of this file are subject to the Mozilla Public
21417 +** License Version 1.1 (the "License"); you may not use this file
21418 +** except in compliance with the License. You may obtain a copy of
21419 +** the License at http://www.mozilla.org/MPL/
21421 +** Software distributed under the License is distributed on an "AS
21422 +** IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
21423 +** implied. See the License for the specific language governing
21424 +** rights and limitations under the License.
21426 +** Alternatively, the contents of this file may be used under the
21427 +** terms of the GNU Public License version 2 (the "GPL"), in which
21428 +** case the provisions of the GPL are applicable instead of the
21429 +** above. If you wish to allow the use of your version of this file
21430 +** only under the terms of the GPL and not to allow others to use
21431 +** your version of this file under the MPL, indicate your decision
21432 +** by deleting the provisions above and replace them with the notice
21433 +** and other provisions required by the GPL. If you do not delete
21434 +** the provisions above, a recipient may use your version of this
21435 +** file under either the MPL or the GPL.
21436 +** ---------------------------------------------------------------------
21437 +** Inquiries regarding the ACX100 Open Source Project can be
21438 +** made directly to:
21440 +** acx100-users@lists.sf.net
21441 +** http://acx100.sf.net
21442 +** ---------------------------------------------------------------------
21446 +#include <linux/config.h>
21447 +#include <linux/version.h>
21448 +#include <linux/kernel.h>
21449 +#include <linux/module.h>
21450 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
21451 +#include <linux/moduleparam.h>
21453 +#include <linux/sched.h>
21454 +#include <linux/types.h>
21455 +#include <linux/skbuff.h>
21456 +#include <linux/slab.h>
21457 +#include <linux/if_arp.h>
21458 +#include <linux/rtnetlink.h>
21459 +#include <linux/wireless.h>
21460 +#if WIRELESS_EXT >= 13
21461 +#include <net/iw_handler.h>
21463 +#include <linux/netdevice.h>
21464 +#include <linux/ioport.h>
21465 +#include <linux/pci.h>
21466 +#include <linux/pm.h>
21471 +/*================================================================*/
21472 +/* Local Constants */
21473 +#define PCI_TYPE (PCI_USES_MEM | PCI_ADDR0 | PCI_NO_ACPI_WAKE)
21474 +#define PCI_ACX100_REGION1 0x01
21475 +#define PCI_ACX100_REGION1_SIZE 0x1000 /* Memory size - 4K bytes */
21476 +#define PCI_ACX100_REGION2 0x02
21477 +#define PCI_ACX100_REGION2_SIZE 0x10000 /* Memory size - 64K bytes */
21479 +#define PCI_ACX111_REGION1 0x00
21480 +#define PCI_ACX111_REGION1_SIZE 0x2000 /* Memory size - 8K bytes */
21481 +#define PCI_ACX111_REGION2 0x01
21482 +#define PCI_ACX111_REGION2_SIZE 0x20000 /* Memory size - 128K bytes */
21484 +/* Texas Instruments Vendor ID */
21485 +#define PCI_VENDOR_ID_TI 0x104c
21487 +/* ACX100 22Mb/s WLAN controller */
21488 +#define PCI_DEVICE_ID_TI_TNETW1100A 0x8400
21489 +#define PCI_DEVICE_ID_TI_TNETW1100B 0x8401
21491 +/* ACX111 54Mb/s WLAN controller */
21492 +#define PCI_DEVICE_ID_TI_TNETW1130 0x9066
21494 +/* PCI Class & Sub-Class code, Network-'Other controller' */
21495 +#define PCI_CLASS_NETWORK_OTHERS 0x280
21497 +#define CARD_EEPROM_ID_SIZE 6
21498 +#define MAX_IRQLOOPS_PER_JIFFY (20000/HZ) /* a la orinoco.c */
21501 +/***********************************************************************
21503 +static void acx_l_disable_irq(wlandevice_t *priv);
21504 +static void acx_l_enable_irq(wlandevice_t *priv);
21505 +static int acx_e_probe_pci(struct pci_dev *pdev,
21506 + const struct pci_device_id *id);
21507 +static void acx_e_remove_pci(struct pci_dev *pdev);
21510 +static int acx_e_suspend(struct pci_dev *pdev, pm_message_t state);
21511 +static int acx_e_resume(struct pci_dev *pdev);
21514 +static void acx_i_tx_timeout(netdevice_t *dev);
21515 +static struct net_device_stats *acx_e_get_stats(netdevice_t *dev);
21516 +static struct iw_statistics *acx_e_get_wireless_stats(netdevice_t *dev);
21518 +static irqreturn_t acx_i_interrupt(int irq, void *dev_id, struct pt_regs *regs);
21519 +static void acx_i_set_multicast_list(netdevice_t *dev);
21521 +static int acx_e_open(netdevice_t *dev);
21522 +static int acx_e_close(netdevice_t *dev);
21523 +static void acx_s_up(netdevice_t *dev);
21524 +static void acx_s_down(netdevice_t *dev);
21527 +/***********************************************************************
21528 +** Register access
21532 +/* #define INLINE_IO static */
21533 +#define INLINE_IO static inline
21536 +acx_read_reg32(wlandevice_t *priv, unsigned int offset)
21538 +#if ACX_IO_WIDTH == 32
21539 + return readl((u8 *)priv->iobase + priv->io[offset]);
21541 + return readw((u8 *)priv->iobase + priv->io[offset])
21542 + + (readw((u8 *)priv->iobase + priv->io[offset] + 2) << 16);
21547 +acx_read_reg16(wlandevice_t *priv, unsigned int offset)
21549 + return readw((u8 *)priv->iobase + priv->io[offset]);
21553 +acx_read_reg8(wlandevice_t *priv, unsigned int offset)
21555 + return readb((u8 *)priv->iobase + priv->io[offset]);
21559 +acx_write_reg32(wlandevice_t *priv, unsigned int offset, u32 val)
21561 +#if ACX_IO_WIDTH == 32
21562 + writel(val, (u8 *)priv->iobase + priv->io[offset]);
21564 + writew(val & 0xffff, (u8 *)priv->iobase + priv->io[offset]);
21565 + writew(val >> 16, (u8 *)priv->iobase + priv->io[offset] + 2);
21570 +acx_write_reg16(wlandevice_t *priv, unsigned int offset, u16 val)
21572 + writew(val, (u8 *)priv->iobase + priv->io[offset]);
21576 +acx_write_reg8(wlandevice_t *priv, unsigned int offset, u8 val)
21578 + writeb(val, (u8 *)priv->iobase + priv->io[offset]);
21581 +/* Handle PCI posting properly:
21582 + * Make sure that writes reach the adapter in case they require to be executed
21583 + * *before* the next write, by reading a random (and safely accessible) register.
21584 + * This call has to be made if there is no read following (which would flush the data
21585 + * to the adapter), yet the written data has to reach the adapter immediately. */
21587 +acx_write_flush(wlandevice_t *priv)
21589 + /* readb(priv->iobase + priv->io[IO_ACX_INFO_MAILBOX_OFFS]); */
21590 + /* faster version (accesses the first register, IO_ACX_SOFT_RESET,
21591 + * which should also be safe): */
21592 + readb(priv->iobase);
21596 +/***********************************************************************
21598 +static const char name_acx100[] = "ACX100";
21599 +static const char name_tnetw1100a[] = "TNETW1100A";
21600 +static const char name_tnetw1100b[] = "TNETW1100B";
21602 +static const char name_acx111[] = "ACX111";
21603 +static const char name_tnetw1130[] = "TNETW1130";
21605 +static const struct pci_device_id
21606 +acx_pci_id_tbl[] __devinitdata = {
21608 + .vendor = PCI_VENDOR_ID_TI,
21609 + .device = PCI_DEVICE_ID_TI_TNETW1100A,
21610 + .subvendor = PCI_ANY_ID,
21611 + .subdevice = PCI_ANY_ID,
21612 + .driver_data = CHIPTYPE_ACX100,
21615 + .vendor = PCI_VENDOR_ID_TI,
21616 + .device = PCI_DEVICE_ID_TI_TNETW1100B,
21617 + .subvendor = PCI_ANY_ID,
21618 + .subdevice = PCI_ANY_ID,
21619 + .driver_data = CHIPTYPE_ACX100,
21622 + .vendor = PCI_VENDOR_ID_TI,
21623 + .device = PCI_DEVICE_ID_TI_TNETW1130,
21624 + .subvendor = PCI_ANY_ID,
21625 + .subdevice = PCI_ANY_ID,
21626 + .driver_data = CHIPTYPE_ACX111,
21633 + .driver_data = 0,
21637 +MODULE_DEVICE_TABLE(pci, acx_pci_id_tbl);
21639 +/* FIXME: checks should be removed once driver is included in the kernel */
21640 +#ifndef __devexit_p
21641 +#warning *** your kernel is EXTREMELY old since it does not even know about
21642 +#warning __devexit_p - this driver could easily FAIL to work, so better
21643 +#warning upgrade your kernel! ***
21644 +#define __devexit_p(x) x
21647 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11)
21648 +/* pci_name() got introduced at start of 2.6.x,
21649 + * got mandatory (slot_name member removed) in 2.6.11-bk1 */
21650 +#define pci_name(x) x->slot_name
21653 +static struct pci_driver acx_pci_drv_id = {
21654 + .name = "acx_pci",
21655 + .id_table = acx_pci_id_tbl,
21656 + .probe = acx_e_probe_pci,
21657 + .remove = __devexit_p(acx_e_remove_pci),
21659 + .suspend = acx_e_suspend,
21660 + .resume = acx_e_resume
21661 +#endif /* CONFIG_PM */
21664 +typedef struct acx_device {
21665 + netdevice_t *newest;
21668 +/* if this driver was only about PCI devices, then we probably wouldn't
21669 + * need this linked list.
21670 + * But if we want to register ALL kinds of devices in one global list,
21671 + * then we need it and need to maintain it properly. */
21672 +static struct acx_device root_acx_dev = {
21675 +DECLARE_MUTEX(root_acx_dev_sem);
21678 +/***********************************************************************
21680 +static inline txdesc_t*
21681 +get_txdesc(wlandevice_t* priv, int index)
21683 + return (txdesc_t*) (((u8*)priv->txdesc_start) + index * priv->txdesc_size);
21686 +static inline txdesc_t*
21687 +move_txdesc(wlandevice_t* priv, txdesc_t* txdesc, int inc)
21689 + return (txdesc_t*) (((u8*)txdesc) + inc * priv->txdesc_size);
21692 +static txhostdesc_t*
21693 +acx_get_txhostdesc(wlandevice_t* priv, txdesc_t* txdesc)
21695 + int index = (u8*)txdesc - (u8*)priv->txdesc_start;
21696 + if (ACX_DEBUG && (index % priv->txdesc_size)) {
21697 + printk("bad txdesc ptr %p\n", txdesc);
21700 + index /= priv->txdesc_size;
21701 + if (ACX_DEBUG && (index >= TX_CNT)) {
21702 + printk("bad txdesc ptr %p\n", txdesc);
21705 + return &priv->txhostdesc_start[index*2];
21709 +acx_get_txc(wlandevice_t* priv, txdesc_t* txdesc)
21711 + int index = (u8*)txdesc - (u8*)priv->txdesc_start;
21712 + if (ACX_DEBUG && (index % priv->txdesc_size)) {
21713 + printk("bad txdesc ptr %p\n", txdesc);
21716 + index /= priv->txdesc_size;
21717 + if (ACX_DEBUG && (index >= TX_CNT)) {
21718 + printk("bad txdesc ptr %p\n", txdesc);
21721 + return priv->txc[index];
21725 +acx_put_txc(wlandevice_t* priv, txdesc_t* txdesc, client_t* c)
21727 + int index = (u8*)txdesc - (u8*)priv->txdesc_start;
21728 + if (ACX_DEBUG && (index % priv->txdesc_size)) {
21729 + printk("bad txdesc ptr %p\n", txdesc);
21732 + index /= priv->txdesc_size;
21733 + if (ACX_DEBUG && (index >= TX_CNT)) {
21734 + printk("bad txdesc ptr %p\n", txdesc);
21737 + priv->txc[index] = c;
21740 +/***********************************************************************
21741 +** EEPROM and PHY read/write helpers
21743 +/***********************************************************************
21744 +** acx_read_eeprom_offset
21746 +** Function called to read an octet in the EEPROM.
21748 +** This function is used by acx_probe_pci to check if the
21749 +** connected card is a legal one or not.
21752 +** priv ptr to wlandevice structure
21753 +** addr address to read in the EEPROM
21754 +** charbuf ptr to a char. This is where the read octet
21758 +** zero (0) - failed
21759 +** one (1) - success
21761 +** NOT ADAPTED FOR ACX111!!
21764 +acx_read_eeprom_offset(wlandevice_t *priv, u32 addr, u8 *charbuf)
21766 + int result = NOT_OK;
21769 + acx_write_reg32(priv, IO_ACX_EEPROM_CFG, 0);
21770 + acx_write_reg32(priv, IO_ACX_EEPROM_ADDR, addr);
21771 + acx_write_flush(priv);
21772 + acx_write_reg32(priv, IO_ACX_EEPROM_CTL, 2);
21775 + while (acx_read_reg16(priv, IO_ACX_EEPROM_CTL)) {
21776 + /* scheduling away instead of CPU burning loop
21777 + * doesn't seem to work here at all:
21778 + * awful delay, sometimes also failure.
21779 + * Doesn't matter anyway (only small delay). */
21780 + if (unlikely(!--count)) {
21781 + printk("%s: timeout waiting for EEPROM read\n",
21782 + priv->netdev->name);
21787 + *charbuf = acx_read_reg8(priv, IO_ACX_EEPROM_DATA);
21788 + acxlog(L_DEBUG, "EEPROM at 0x%04X = 0x%02X\n", addr, *charbuf);
21796 +/***********************************************************************
21797 +** Dummy EEPROM read? why?!
21800 +acx_read_eeprom_area(wlandevice_t *priv)
21805 + for (offs = 0x8c; offs < 0xb9; offs++) {
21806 + acx_read_eeprom_offset(priv, offs, &tmp[offs - 0x8c]);
21812 +/***********************************************************************
21813 +** We don't lock hw accesses here since we never r/w eeprom in IRQ
21814 +** Note: this function sleeps only because of GFP_KERNEL alloc
21818 +acx_s_write_eeprom_offset(wlandevice_t *priv, u32 addr, u32 len, const u8 *charbuf)
21820 + u8 *data_verify = NULL;
21821 + unsigned long flags;
21823 + int result = NOT_OK;
21826 + printk("acx: WARNING! I would write to EEPROM now. "
21827 + "Since I really DON'T want to unless you know "
21828 + "what you're doing (THIS CODE WILL PROBABLY "
21829 + "NOT WORK YET!), I will abort that now. And "
21830 + "definitely make sure to make a "
21831 + "/proc/driver/acx_wlan0_eeprom backup copy first!!! "
21832 + "(the EEPROM content includes the PCI config header!! "
21833 + "If you kill important stuff, then you WILL "
21834 + "get in trouble and people DID get in trouble already)\n");
21839 + data_verify = kmalloc(len, GFP_KERNEL);
21840 + if (!data_verify) {
21844 + /* first we need to enable the OE (EEPROM Output Enable) GPIO line
21845 + * to be able to write to the EEPROM.
21846 + * NOTE: an EEPROM writing success has been reported,
21847 + * but you probably have to modify GPIO_OUT, too,
21848 + * and you probably need to activate a different GPIO
21849 + * line instead! */
21850 + gpio_orig = acx_read_reg16(priv, IO_ACX_GPIO_OE);
21851 + acx_write_reg16(priv, IO_ACX_GPIO_OE, gpio_orig & ~1);
21852 + acx_write_flush(priv);
21854 + /* ok, now start writing the data out */
21855 + for (i = 0; i < len; i++) {
21856 + acx_write_reg32(priv, IO_ACX_EEPROM_CFG, 0);
21857 + acx_write_reg32(priv, IO_ACX_EEPROM_ADDR, addr + i);
21858 + acx_write_reg32(priv, IO_ACX_EEPROM_DATA, *(charbuf + i));
21859 + acx_write_flush(priv);
21860 + acx_write_reg32(priv, IO_ACX_EEPROM_CTL, 1);
21862 + while (acx_read_reg16(priv, IO_ACX_EEPROM_CTL)) {
21863 + if (unlikely(++count > 0xffff)) {
21864 + printk("WARNING, DANGER!!! "
21865 + "Timeout waiting for EEPROM write\n");
21871 + /* disable EEPROM writing */
21872 + acx_write_reg16(priv, IO_ACX_GPIO_OE, gpio_orig);
21873 + acx_write_flush(priv);
21875 + /* now start a verification run */
21877 + for (i = 0; i < len; i++) {
21878 + acx_write_reg32(priv, IO_ACX_EEPROM_CFG, 0);
21879 + acx_write_reg32(priv, IO_ACX_EEPROM_ADDR, addr + i);
21880 + acx_write_flush(priv);
21881 + acx_write_reg32(priv, IO_ACX_EEPROM_CTL, 2);
21883 + while (acx_read_reg16(priv, IO_ACX_EEPROM_CTL)) {
21884 + if (unlikely(!--count)) {
21885 + printk("timeout waiting for EEPROM read\n");
21890 + data_verify[i] = acx_read_reg16(priv, IO_ACX_EEPROM_DATA);
21893 + if (0 == memcmp(charbuf, data_verify, len))
21894 + result = OK; /* read data matches, success */
21897 + kfree(data_verify);
21898 + FN_EXIT1(result);
21901 +#endif /* UNUSED */
21904 +/***********************************************************************
21905 +** acxpci_s_read_phy_reg
21907 +** Messing with rx/tx disabling and enabling here
21908 +** (acx_write_reg32(priv, IO_ACX_ENABLE, 0b000000xx)) kills traffic
21911 +acxpci_s_read_phy_reg(wlandevice_t *priv, u32 reg, u8 *charbuf)
21913 + int result = NOT_OK;
21918 + acx_write_reg32(priv, IO_ACX_PHY_ADDR, reg);
21919 + acx_write_flush(priv);
21920 + acx_write_reg32(priv, IO_ACX_PHY_CTL, 2);
21923 + while (acx_read_reg32(priv, IO_ACX_PHY_CTL)) {
21924 + /* scheduling away instead of CPU burning loop
21925 + * doesn't seem to work here at all:
21926 + * awful delay, sometimes also failure.
21927 + * Doesn't matter anyway (only small delay). */
21928 + if (unlikely(!--count)) {
21929 + printk("%s: timeout waiting for phy read\n",
21930 + priv->netdev->name);
21936 + acxlog(L_DEBUG, "count was %u\n", count);
21937 + *charbuf = acx_read_reg8(priv, IO_ACX_PHY_DATA);
21939 + acxlog(L_DEBUG, "radio PHY at 0x%04X = 0x%02X\n", *charbuf, reg);
21941 + goto fail; /* silence compiler warning */
21943 + FN_EXIT1(result);
21948 +/***********************************************************************
21951 +acxpci_s_write_phy_reg(wlandevice_t *priv, u32 reg, u8 value)
21955 + /* FIXME: we didn't use 32bit access here since mprusko said that
21956 + * it results in distorted sensitivity on his card (huh!?!?
21957 + * doesn't happen with my setup...)
21958 + * But with the access reordering and flushing it
21959 + * shouldn't happen any more...
21960 + * FIXME: which radio is in the problematic card? My working one
21962 + acx_write_reg32(priv, IO_ACX_PHY_DATA, value);
21963 + acx_write_reg32(priv, IO_ACX_PHY_ADDR, reg);
21964 + acx_write_flush(priv);
21965 + acx_write_reg32(priv, IO_ACX_PHY_CTL, 1);
21966 + acx_write_flush(priv);
21967 + acxlog(L_DEBUG, "radio PHY write 0x%02X at 0x%04X\n", value, reg);
21974 +#define NO_AUTO_INCREMENT 1
21976 +/***********************************************************************
21979 +** Write the firmware image into the card.
21982 +** priv wlan device structure
21983 +** apfw_image firmware image.
21986 +** 1 firmware image corrupted
21990 +acx_s_write_fw(wlandevice_t *priv, const firmware_image_t *apfw_image, u32 offset)
21994 + /* we skip the first four bytes which contain the control sum */
21995 + const u8 *image = (u8*)apfw_image + 4;
21997 + /* start the image checksum by adding the image size value */
21998 + sum = image[0]+image[1]+image[2]+image[3];
22001 + acx_write_reg32(priv, IO_ACX_SLV_END_CTL, 0);
22003 +#if NO_AUTO_INCREMENT
22004 + acxlog(L_INIT, "not using auto increment for firmware loading\n");
22005 + acx_write_reg32(priv, IO_ACX_SLV_MEM_CTL, 0); /* use basic mode */
22007 + acx_write_reg32(priv, IO_ACX_SLV_MEM_CTL, 1); /* use autoincrement mode */
22008 + acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR, offset); /* configure start address */
22009 + acx_write_flush(priv);
22013 + size = le32_to_cpu(apfw_image->size) & (~3);
22015 + while (likely(len < size)) {
22016 + v32 = be32_to_cpu(*(u32*)image);
22017 + sum += image[0]+image[1]+image[2]+image[3];
22021 +#if NO_AUTO_INCREMENT
22022 + acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR, offset + len - 4);
22023 + acx_write_flush(priv);
22025 + acx_write_reg32(priv, IO_ACX_SLV_MEM_DATA, v32);
22028 + acxlog(L_DEBUG, "%s: firmware written\n", __func__);
22030 + /* compare our checksum with the stored image checksum */
22031 + return (sum != le32_to_cpu(apfw_image->chksum));
22035 +/***********************************************************************
22036 +** acx_s_validate_fw
22038 +** Compare the firmware image given with
22039 +** the firmware image written into the card.
22042 +** priv wlan device structure
22043 +** apfw_image firmware image.
22046 +** NOT_OK firmware image corrupted or not correctly written
22050 +acx_s_validate_fw(wlandevice_t *priv, const firmware_image_t *apfw_image,
22053 + u32 v32, w32, sum;
22056 + /* we skip the first four bytes which contain the control sum */
22057 + const u8 *image = (u8*)apfw_image + 4;
22059 + /* start the image checksum by adding the image size value */
22060 + sum = image[0]+image[1]+image[2]+image[3];
22063 + acx_write_reg32(priv, IO_ACX_SLV_END_CTL, 0);
22065 +#if NO_AUTO_INCREMENT
22066 + acx_write_reg32(priv, IO_ACX_SLV_MEM_CTL, 0); /* use basic mode */
22068 + acx_write_reg32(priv, IO_ACX_SLV_MEM_CTL, 1); /* use autoincrement mode */
22069 + acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR, offset); /* configure start address */
22073 + size = le32_to_cpu(apfw_image->size) & (~3);
22075 + while (likely(len < size)) {
22076 + v32 = be32_to_cpu(*(u32*)image);
22080 +#if NO_AUTO_INCREMENT
22081 + acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR, offset + len - 4);
22083 + w32 = acx_read_reg32(priv, IO_ACX_SLV_MEM_DATA);
22085 + if (unlikely(w32 != v32)) {
22086 + printk("acx: FATAL: firmware upload: "
22087 + "data parts at offset %d don't match (0x%08X vs. 0x%08X)! "
22088 + "I/O timing issues or defective memory, with DWL-xx0+? "
22089 + "ACX_IO_WIDTH=16 may help. Please report\n",
22095 + sum += (u8)w32 + (u8)(w32>>8) + (u8)(w32>>16) + (u8)(w32>>24);
22098 + /* sum control verification */
22099 + if (result != NOT_OK) {
22100 + if (sum != le32_to_cpu(apfw_image->chksum)) {
22101 + printk("acx: FATAL: firmware upload: "
22102 + "checksums don't match!\n");
22111 +/***********************************************************************
22112 +** acx_s_upload_fw
22115 +** wlandevice: private device that contains card device
22123 +acx_s_upload_fw(wlandevice_t *priv)
22125 + firmware_image_t *apfw_image = NULL;
22126 + int res = NOT_OK;
22129 + char filename[sizeof("tiacx1NNcNN")];
22133 + /* Try combined, then main image */
22134 + priv->need_radio_fw = 0;
22135 + sprintf(filename, "tiacx1%02dc%02X",
22136 + IS_ACX111(priv)*11, priv->radio_type);
22138 + apfw_image = acx_s_read_fw(&priv->pdev->dev, filename, &size);
22139 + if (!apfw_image) {
22140 + priv->need_radio_fw = 1;
22141 + filename[sizeof("tiacx1NN")-1] = '\0';
22142 + apfw_image = acx_s_read_fw(&priv->pdev->dev, filename, &size);
22143 + if (!apfw_image) {
22144 + FN_EXIT1(NOT_OK);
22149 + for (try = 1; try <= 5; try++) {
22150 + res = acx_s_write_fw(priv, apfw_image, 0);
22151 + acxlog(L_DEBUG|L_INIT, "acx_write_fw (main/combined):%d\n", res);
22153 + res = acx_s_validate_fw(priv, apfw_image, 0);
22154 + acxlog(L_DEBUG|L_INIT, "acx_validate_fw "
22155 + "(main/combined):%d\n", res);
22159 + SET_BIT(priv->dev_state_mask, ACX_STATE_FW_LOADED);
22162 + printk("acx: firmware upload attempt #%d FAILED, "
22163 + "retrying...\n", try);
22164 + acx_s_msleep(1000); /* better wait for a while... */
22167 + vfree(apfw_image);
22174 +/***********************************************************************
22175 +** acx_s_upload_radio
22177 +** Uploads the appropriate radio module firmware
22181 +acx_s_upload_radio(wlandevice_t *priv)
22183 + acx_ie_memmap_t mm;
22184 + firmware_image_t *radio_image = NULL;
22185 + acx_cmd_radioinit_t radioinit;
22186 + int res = NOT_OK;
22190 + char filename[sizeof("tiacx1NNrNN")];
22192 + if (!priv->need_radio_fw) return OK;
22196 + acx_s_interrogate(priv, &mm, ACX1xx_IE_MEMORY_MAP);
22197 + offset = le32_to_cpu(mm.CodeEnd);
22199 + sprintf(filename, "tiacx1%02dr%02X",
22200 + IS_ACX111(priv)*11,
22201 + priv->radio_type);
22202 + radio_image = acx_s_read_fw(&priv->pdev->dev, filename, &size);
22203 + if (!radio_image) {
22204 + printk("acx: can't load radio module '%s'\n", filename);
22208 + acx_s_issue_cmd(priv, ACX1xx_CMD_SLEEP, NULL, 0);
22210 + for (try = 1; try <= 5; try++) {
22211 + res = acx_s_write_fw(priv, radio_image, offset);
22212 + acxlog(L_DEBUG|L_INIT, "acx_write_fw (radio): %d\n", res);
22214 + res = acx_s_validate_fw(priv, radio_image, offset);
22215 + acxlog(L_DEBUG|L_INIT, "acx_validate_fw (radio): %d\n", res);
22220 + printk("acx: radio firmware upload attempt #%d FAILED, "
22221 + "retrying...\n", try);
22222 + acx_s_msleep(1000); /* better wait for a while... */
22225 + acx_s_issue_cmd(priv, ACX1xx_CMD_WAKE, NULL, 0);
22226 + radioinit.offset = cpu_to_le32(offset);
22227 + /* no endian conversion needed, remains in card CPU area: */
22228 + radioinit.len = radio_image->size;
22230 + vfree(radio_image);
22235 + /* will take a moment so let's have a big timeout */
22236 + acx_s_issue_cmd_timeo(priv, ACX1xx_CMD_RADIOINIT,
22237 + &radioinit, sizeof(radioinit), CMD_TIMEOUT_MS(1000));
22239 + res = acx_s_interrogate(priv, &mm, ACX1xx_IE_MEMORY_MAP);
22246 +/***********************************************************************
22247 +** acx_l_reset_mac
22250 +** wlandevice: private device that contains card device
22252 +** MAC will be reset
22256 +** resets onboard acx100 MAC
22258 +** Requires lock to be taken
22261 +acx_l_reset_mac(wlandevice_t *priv)
22268 + temp = acx_read_reg16(priv, IO_ACX_ECPU_CTRL) | 0x1;
22269 + acx_write_reg16(priv, IO_ACX_ECPU_CTRL, temp);
22271 + /* now do soft reset of eCPU */
22272 + temp = acx_read_reg16(priv, IO_ACX_SOFT_RESET) | 0x1;
22273 + acxlog(L_DEBUG, "%s: enable soft reset...\n", __func__);
22274 + acx_write_reg16(priv, IO_ACX_SOFT_RESET, temp);
22275 + acx_write_flush(priv);
22277 + /* now reset bit again */
22278 + acxlog(L_DEBUG, "%s: disable soft reset and go to init mode...\n", __func__);
22279 + /* deassert eCPU reset */
22280 + acx_write_reg16(priv, IO_ACX_SOFT_RESET, temp & ~0x1);
22282 + /* now start a burst read from initial flash EEPROM */
22283 + temp = acx_read_reg16(priv, IO_ACX_EE_START) | 0x1;
22284 + acx_write_reg16(priv, IO_ACX_EE_START, temp);
22285 + acx_write_flush(priv);
22291 +/***********************************************************************
22292 +** acx_s_verify_init
22295 +acx_s_verify_init(wlandevice_t *priv)
22297 + int result = NOT_OK;
22302 + for (timer = 40; timer > 0; timer--) {
22303 + u16 irqstat = acx_read_reg16(priv, IO_ACX_IRQ_STATUS_NON_DES);
22304 + if (irqstat & HOST_INT_FCS_THRESHOLD) {
22306 + acx_write_reg16(priv, IO_ACX_IRQ_ACK, HOST_INT_FCS_THRESHOLD);
22309 + /* HZ / 50 resulted in 24 schedules for ACX100 on my machine,
22310 + * so better schedule away longer for greater efficiency,
22311 + * decrease loop count */
22312 + acx_s_msleep(50);
22315 + FN_EXIT1(result);
22320 +/***********************************************************************
22321 +** A few low-level helpers
22323 +** Note: these functions are not protected by lock
22324 +** and thus are never allowed to be called from IRQ.
22325 +** Also they must not race with fw upload which uses same hw regs
22328 +/***********************************************************************
22329 +** acx_read_info_status
22331 +/* Info mailbox format:
22334 +more bytes may follow
22335 + docs say about status:
22336 + 0x0000 info available (set by hw)
22337 + 0x0001 information received (must be set by host)
22338 + 0x1000 info available, mailbox overflowed (messages lost) (set by hw)
22339 + but in practice we've seen:
22340 + 0x9000 when we did not set status to 0x0001 on prev message
22341 + 0x1001 when we did set it
22342 + 0x0000 was never seen
22343 + conclusion: this is really a bitfield:
22344 + 0x1000 is 'info available' bit
22345 + 'mailbox overflowed' bit is 0x8000, not 0x1000
22346 + value of 0x0000 probably means that there is no message at all
22347 + P.S. I dunno how in hell hw is supposed to notice that messages are lost -
22348 + it does NOT clear bit 0x0001, and this bit will probably stay forever set
22349 + after we set it once. Let's hope this will be fixed in firmware someday
22352 +acx_read_info_status(wlandevice_t *priv)
22356 + acx_write_reg32(priv, IO_ACX_SLV_END_CTL, 0x0);
22357 + acx_write_reg32(priv, IO_ACX_SLV_MEM_CTL, 0x1);
22359 + acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR,
22360 + acx_read_reg32(priv, IO_ACX_INFO_MAILBOX_OFFS));
22362 + /* make sure we only read the data once all cfg registers are written: */
22363 + acx_write_flush(priv);
22364 + value = acx_read_reg32(priv, IO_ACX_SLV_MEM_DATA);
22366 + priv->info_type = (u16)value;
22367 + priv->info_status = (value >> 16);
22369 + /* inform hw that we have read this info message */
22370 + acx_write_reg32(priv, IO_ACX_SLV_MEM_DATA, priv->info_type | 0x00010000);
22371 + acx_write_flush(priv);
22372 + /* now bother hw to notice it: */
22373 + acx_write_reg16(priv, IO_ACX_INT_TRIG, INT_TRIG_INFOACK);
22374 + acx_write_flush(priv);
22376 + acxlog(L_CTL, "info_type 0x%04X, info_status 0x%04X\n",
22377 + priv->info_type, priv->info_status);
22381 +/***********************************************************************
22382 +** acx_write_cmd_type_or_status
22385 +acx_write_cmd_type_or_status(wlandevice_t *priv, u32 val)
22387 + acx_write_reg32(priv, IO_ACX_SLV_END_CTL, 0x0);
22388 + acx_write_reg32(priv, IO_ACX_SLV_MEM_CTL, 0x1); /* FIXME: why auto increment?? */
22390 + acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR,
22391 + acx_read_reg32(priv, IO_ACX_CMD_MAILBOX_OFFS));
22393 + /* make sure we only write the data once all config registers are written */
22394 + acx_write_flush(priv);
22395 + acx_write_reg32(priv, IO_ACX_SLV_MEM_DATA, val);
22396 + acx_write_flush(priv);
22398 +static inline void
22399 +acx_write_cmd_type(wlandevice_t *priv, u32 val)
22401 + acx_write_cmd_type_or_status(priv, val);
22403 +static inline void
22404 +acx_write_cmd_status(wlandevice_t *priv, u32 val)
22406 + acx_write_cmd_type_or_status(priv, val<<16);
22410 +/***********************************************************************
22411 +** acx_read_cmd_status
22414 +acx_read_cmd_status(wlandevice_t *priv)
22418 + acx_write_reg32(priv, IO_ACX_SLV_END_CTL, 0x0);
22419 + acx_write_reg32(priv, IO_ACX_SLV_MEM_CTL, 0x1); /* FIXME: why auto increment?? */
22421 + acx_write_reg32(priv, IO_ACX_SLV_MEM_ADDR,
22422 + acx_read_reg32(priv, IO_ACX_CMD_MAILBOX_OFFS));
22424 + /* make sure we only read the data once all config registers are written */
22425 + acx_write_flush(priv);
22426 + value = acx_read_reg32(priv, IO_ACX_SLV_MEM_DATA);
22428 + priv->cmd_type = (u16)value;
22429 + priv->cmd_status = (value >> 16);
22431 + acxlog(L_CTL, "cmd_type 0x%04X, cmd_status 0x%04X [%s]\n",
22432 + priv->cmd_type, priv->cmd_status,
22433 + acx_cmd_status_str(priv->cmd_status));
22437 +/***********************************************************************
22438 +** acx_s_reset_dev
22441 +** netdevice that contains the wlandevice priv variable
22446 +** device is hard reset
22450 +** This resets the acx100 device using low level hardware calls
22451 +** as well as uploads and verifies the firmware to the card
22454 +acx_s_reset_dev(netdevice_t *dev)
22456 + wlandevice_t *priv = netdev_priv(dev);
22457 + const char* msg = "";
22458 + unsigned long flags;
22459 + int result = NOT_OK;
22460 + u16 hardware_info;
22465 + /* we're doing a reset, so hardware is unavailable */
22467 + /* reset the device to make sure the eCPU is stopped
22468 + * to upload the firmware correctly */
22470 + acx_lock(priv, flags);
22472 + acx_l_reset_mac(priv);
22474 + ecpu_ctrl = acx_read_reg16(priv, IO_ACX_ECPU_CTRL) & 1;
22475 + if (!ecpu_ctrl) {
22476 + msg = "eCPU is already running. ";
22477 + goto fail_unlock;
22480 +#ifdef WE_DONT_NEED_THAT_DO_WE
22481 + if (acx_read_reg16(priv, IO_ACX_SOR_CFG) & 2) {
22482 + /* eCPU most likely means "embedded CPU" */
22483 + msg = "eCPU did not start after boot from flash. ";
22484 + goto fail_unlock;
22487 + /* check sense on reset flags */
22488 + if (acx_read_reg16(priv, IO_ACX_SOR_CFG) & 0x10) {
22489 + printk("%s: eCPU did not start after boot (SOR), "
22490 + "is this fatal?\n", dev->name);
22493 + /* scan, if any, is stopped now, setting corresponding IRQ bit */
22494 + priv->irq_status |= HOST_INT_SCAN_COMPLETE;
22496 + acx_unlock(priv, flags);
22498 + /* without this delay acx100 may fail to report hardware_info
22499 + ** (see below). Most probably eCPU runs some init code */
22500 + acx_s_msleep(10);
22502 + /* Need to know radio type before fw load */
22503 + hardware_info = acx_read_reg16(priv, IO_ACX_EEPROM_INFORMATION);
22504 + priv->form_factor = hardware_info & 0xff;
22505 + priv->radio_type = hardware_info >> 8;
22507 + /* load the firmware */
22508 + if (OK != acx_s_upload_fw(priv))
22511 + acx_s_msleep(10);
22513 + /* now start eCPU by clearing bit */
22514 + acxlog(L_DEBUG, "booted eCPU up and waiting for completion...\n");
22515 + acx_write_reg16(priv, IO_ACX_ECPU_CTRL, ecpu_ctrl & ~0x1);
22517 + /* wait for eCPU bootup */
22518 + if (OK != acx_s_verify_init(priv)) {
22519 + msg = "timeout waiting for eCPU. ";
22523 + acxlog(L_DEBUG, "eCPU has woken up, card is ready to be configured\n");
22525 + if (IS_ACX111(priv)) {
22526 + acxlog(L_DEBUG, "cleaning up cmd mailbox access area\n");
22527 + acx_write_cmd_status(priv, 0);
22528 + acx_read_cmd_status(priv);
22529 + if (priv->cmd_status) {
22530 + msg = "error cleaning cmd mailbox area. ";
22535 + /* TODO what is this one doing ?? adapt for acx111 */
22536 + if ((OK != acx_read_eeprom_area(priv)) && IS_ACX100(priv)) {
22537 + /* does "CIS" mean "Card Information Structure"?
22538 + * If so, then this would be a PCMCIA message...
22540 + msg = "CIS error. ";
22545 + FN_EXIT1(result);
22548 +/* Finish error message. Indicate which function failed */
22550 + acx_unlock(priv, flags);
22552 + printk("acx: %sreset_dev() FAILED\n", msg);
22553 + FN_EXIT1(result);
22558 +/***********************************************************************
22559 +** acx_init_mboxes
22562 +acx_init_mboxes(wlandevice_t *priv)
22564 + u32 cmd_offs, info_offs;
22568 + cmd_offs = acx_read_reg32(priv, IO_ACX_CMD_MAILBOX_OFFS);
22569 + info_offs = acx_read_reg32(priv, IO_ACX_INFO_MAILBOX_OFFS);
22570 + priv->cmd_area = (u8 *)priv->iobase2 + cmd_offs + 0x4;
22571 + priv->info_area = (u8 *)priv->iobase2 + info_offs + 0x4;
22572 + acxlog(L_DEBUG, "iobase2=%p\n"
22573 + "cmd_mbox_offset=%X cmd_area=%p\n"
22574 + "info_mbox_offset=%X info_area=%p\n",
22576 + cmd_offs, priv->cmd_area,
22577 + info_offs, priv->info_area);
22583 +/*----------------------------------------------------------------
22584 +* acx_s_issue_cmd_timeo
22585 +* Excecutes a command in the command mailbox
22588 +* *pcmdparam = an pointer to the data. The data mustn't include
22589 +* the 4 byte command header!
22591 +* NB: we do _not_ take lock inside, so be sure to not touch anything
22592 +* which may interfere with IRQ handler operation
22594 +* TODO: busy wait is a bit silly, so:
22595 +* 1) stop doing many iters - go to sleep after first
22596 +* 2) go to waitqueue based approach: wait, not poll!
22597 +*----------------------------------------------------------------*/
22599 +#define FUNC "issue_cmd"
22603 +acxpci_s_issue_cmd_timeo(
22604 + wlandevice_t *priv,
22605 + unsigned int cmd,
22608 + unsigned timeout)
22612 +acxpci_s_issue_cmd_timeo_debug(
22613 + wlandevice_t *priv,
22617 + unsigned timeout,
22618 + const char* cmdstr)
22620 + unsigned long start = jiffies;
22622 + const char *devname;
22623 + unsigned counter;
22629 + devname = priv->netdev->name;
22630 + if (!devname || !devname[0])
22633 + acxlog(L_CTL, FUNC"(cmd:%s,buflen:%u,timeout:%ums,type:0x%04X)\n",
22634 + cmdstr, buflen, timeout,
22635 + buffer ? le16_to_cpu(((acx_ie_generic_t *)buffer)->type) : -1);
22637 + if (!(priv->dev_state_mask & ACX_STATE_FW_LOADED)) {
22638 + printk("%s: "FUNC"(): firmware is not loaded yet, "
22639 + "cannot execute commands!\n", devname);
22643 + if ((acx_debug & L_DEBUG) && (cmd != ACX1xx_CMD_INTERROGATE)) {
22644 + printk("input pdr (len=%u):\n", buflen);
22645 + acx_dump_bytes(buffer, buflen);
22648 + /* wait for firmware to become idle for our command submission */
22649 + counter = 199; /* in ms */
22651 + acx_read_cmd_status(priv);
22652 + /* Test for IDLE state */
22653 + if (!priv->cmd_status)
22655 + if (counter % 10 == 0) {
22656 + /* we waited 10 iterations, no luck. Sleep 10 ms */
22657 + acx_s_msleep(10);
22659 + } while (--counter);
22662 + /* the card doesn't get idle, we're in trouble */
22663 + printk("%s: "FUNC"(): cmd_status is not IDLE: 0x%04X!=0\n",
22664 + devname, priv->cmd_status);
22666 + } else if (counter < 190) { /* if waited >10ms... */
22667 + acxlog(L_CTL|L_DEBUG, FUNC"(): waited for IDLE %dms. "
22668 + "Please report\n", 199 - counter);
22671 + /* now write the parameters of the command if needed */
22672 + if (buffer && buflen) {
22673 + /* if it's an INTERROGATE command, just pass the length
22674 + * of parameters to read, as data */
22676 + if (cmd == ACX1xx_CMD_INTERROGATE)
22677 + memset(priv->cmd_area, 0xAA, buflen);
22679 + memcpy(priv->cmd_area, buffer,
22680 + (cmd == ACX1xx_CMD_INTERROGATE) ? 4 : buflen);
22682 + /* now write the actual command type */
22683 + priv->cmd_type = cmd;
22684 + acx_write_cmd_type(priv, cmd);
22685 + /* execute command */
22686 + acx_write_reg16(priv, IO_ACX_INT_TRIG, INT_TRIG_CMD);
22687 + acx_write_flush(priv);
22689 + /* wait for firmware to process command */
22691 + /* Ensure nonzero and not too large timeout.
22692 + ** Also converts e.g. 100->99, 200->199
22693 + ** which is nice but not essential */
22694 + timeout = (timeout-1) | 1;
22695 + if (unlikely(timeout > 1199))
22697 + /* clear CMD_COMPLETE bit. can be set only by IRQ handler: */
22698 + priv->irq_status &= ~HOST_INT_CMD_COMPLETE;
22700 + /* we schedule away sometimes (timeout can be large) */
22701 + counter = timeout;
22703 + if (!priv->irqs_active) { /* IRQ disabled: poll */
22704 + irqtype = acx_read_reg16(priv, IO_ACX_IRQ_STATUS_NON_DES);
22705 + if (irqtype & HOST_INT_CMD_COMPLETE) {
22706 + acx_write_reg16(priv, IO_ACX_IRQ_ACK,
22707 + HOST_INT_CMD_COMPLETE);
22710 + } else { /* Wait when IRQ will set the bit */
22711 + irqtype = priv->irq_status;
22712 + if (irqtype & HOST_INT_CMD_COMPLETE)
22716 + if (counter % 10 == 0) {
22717 + /* we waited 10 iterations, no luck. Sleep 10 ms */
22718 + acx_s_msleep(10);
22720 + } while (--counter);
22722 + /* save state for debugging */
22723 + acx_read_cmd_status(priv);
22724 + cmd_status = priv->cmd_status;
22726 + /* put the card in IDLE state */
22727 + priv->cmd_status = 0;
22728 + acx_write_cmd_status(priv, 0);
22730 + if (!counter) { /* timed out! */
22731 + printk("%s: "FUNC"(): timed out %s for CMD_COMPLETE. "
22732 + "irq bits:0x%04X irq_status:0x%04X timeout:%dms "
22733 + "cmd_status:%d (%s)\n",
22734 + devname, (priv->irqs_active) ? "waiting" : "polling",
22735 + irqtype, priv->irq_status, timeout,
22736 + cmd_status, acx_cmd_status_str(cmd_status));
22738 + } else if (timeout - counter > 30) { /* if waited >30ms... */
22739 + acxlog(L_CTL|L_DEBUG, FUNC"(): %s for CMD_COMPLETE %dms. "
22740 + "count:%d. Please report\n",
22741 + (priv->irqs_active) ? "waited" : "polled",
22742 + timeout - counter, counter);
22745 + if (1 != cmd_status) { /* it is not a 'Success' */
22746 + printk("%s: "FUNC"(): cmd_status is not SUCCESS: %d (%s). "
22747 + "Took %dms of %d\n",
22748 + devname, cmd_status, acx_cmd_status_str(cmd_status),
22749 + timeout - counter, timeout);
22750 + /* zero out result buffer */
22751 + if (buffer && buflen)
22752 + memset(buffer, 0, buflen);
22756 + /* read in result parameters if needed */
22757 + if (buffer && buflen && (cmd == ACX1xx_CMD_INTERROGATE)) {
22758 + memcpy(buffer, priv->cmd_area, buflen);
22759 + if (acx_debug & L_DEBUG) {
22760 + printk("output buffer (len=%u): ", buflen);
22761 + acx_dump_bytes(buffer, buflen);
22765 + acxlog(L_CTL, FUNC"(%s): took %ld jiffies to complete\n",
22766 + cmdstr, jiffies - start);
22771 + /* Give enough info so that callers can avoid
22772 + ** printing their own diagnostic messages */
22774 + printk("%s: "FUNC"(cmd:%s) FAILED\n", devname, cmdstr);
22776 + printk("%s: "FUNC"(cmd:0x%04X) FAILED\n", devname, cmd);
22779 + FN_EXIT1(NOT_OK);
22784 +/*----------------------------------------------------------------
22785 +* acx_s_get_firmware_version
22786 +*----------------------------------------------------------------*/
22788 +acx_s_get_firmware_version(wlandevice_t *priv)
22791 + u8 hexarr[4] = { 0, 0, 0, 0 };
22792 + int hexidx = 0, val = 0;
22798 + acx_s_interrogate(priv, &fw, ACX1xx_IE_FWREV);
22799 + memcpy(priv->firmware_version, fw.fw_id, FW_ID_SIZE);
22800 + priv->firmware_version[FW_ID_SIZE] = '\0';
22801 + acxlog(L_DEBUG, "fw_ver: fw_id='%s' hw_id=%08X\n",
22802 + priv->firmware_version, fw.hw_id);
22804 + if (strncmp(fw.fw_id, "Rev ", 4) != 0) {
22805 + printk("acx: strange firmware version string "
22806 + "'%s', please report\n", priv->firmware_version);
22807 + priv->firmware_numver = 0x01090407; /* assume 1.9.4.7 */
22809 + num = &fw.fw_id[4];
22812 + if ((c == '.') || (c == '\0')) {
22813 + hexarr[hexidx++] = val;
22814 + if ((hexidx > 3) || (c == '\0')) /* end? */
22819 + if ((c >= '0') && (c <= '9'))
22822 + c = c - 'a' + (char)10;
22823 + val = val*16 + c;
22826 + priv->firmware_numver = (u32)(
22827 + (hexarr[0] << 24) + (hexarr[1] << 16)
22828 + + (hexarr[2] << 8) + hexarr[3]);
22829 + acxlog(L_DEBUG, "firmware_numver 0x%08X\n", priv->firmware_numver);
22831 + if (IS_ACX111(priv)) {
22832 + if (priv->firmware_numver == 0x00010011) {
22833 + /* This one does not survive floodpinging */
22834 + printk("acx: firmware '%s' is known to be buggy, "
22835 + "please upgrade\n", priv->firmware_version);
22837 + if (priv->firmware_numver == 0x02030131) {
22838 + /* With this one, all rx packets look mangled
22839 + ** Most probably we simply do not know how to use it
22841 + printk("acx: firmware '%s' does not work well "
22842 + "with this driver\n", priv->firmware_version);
22846 + priv->firmware_id = le32_to_cpu(fw.hw_id);
22848 + /* we're able to find out more detailed chip names now */
22849 + switch (priv->firmware_id & 0xffff0000) {
22852 + priv->chip_name = name_tnetw1100a;
22855 + priv->chip_name = name_tnetw1100b;
22859 + priv->chip_name = name_tnetw1130;
22862 + printk("acx: unknown chip ID 0x%08X, "
22863 + "please report\n", priv->firmware_id);
22871 +/*----------------------------------------------------------------
22872 +* acx_display_hardware_details
22875 +* priv: ptr to wlandevice that contains all the details
22876 +* displayed by this function
22880 +* This function will display strings to the system log according
22881 +* to device form_factor and radio type. It will needed to be
22882 +*----------------------------------------------------------------*/
22884 +acx_display_hardware_details(wlandevice_t *priv)
22886 + const char *radio_str, *form_str;
22890 + switch (priv->radio_type) {
22891 + case RADIO_MAXIM_0D:
22892 + /* hmm, the DWL-650+ seems to have two variants,
22893 + * according to a windows driver changelog comment:
22894 + * RFMD and Maxim. */
22895 + radio_str = "Maxim";
22897 + case RADIO_RFMD_11:
22898 + radio_str = "RFMD";
22900 + case RADIO_RALINK_15:
22901 + radio_str = "Ralink";
22903 + case RADIO_RADIA_16:
22904 + radio_str = "Radia";
22906 + case RADIO_UNKNOWN_17:
22907 + /* TI seems to have a radio which is
22908 + * additionally 802.11a capable, too */
22909 + radio_str = "802.11a/b/g radio?! Please report";
22911 + case RADIO_UNKNOWN_19:
22912 + radio_str = "A radio used by Safecom cards?! Please report";
22915 + radio_str = "UNKNOWN, please report the radio type name!";
22919 + switch (priv->form_factor) {
22921 + form_str = "unspecified";
22924 + form_str = "(mini-)PCI / CardBus";
22927 + form_str = "USB";
22930 + form_str = "Compact Flash";
22933 + form_str = "UNKNOWN, Please report";
22937 + printk("acx: form factor 0x%02X (%s), "
22938 + "radio type 0x%02X (%s), EEPROM version 0x%02X, "
22939 + "uploaded firmware '%s' (0x%08X)\n",
22940 + priv->form_factor, form_str, priv->radio_type, radio_str,
22941 + priv->eeprom_version, priv->firmware_version,
22942 + priv->firmware_id);
22947 +/***********************************************************************
22949 +#ifdef NONESSENTIAL_FEATURES
22950 +typedef struct device_id {
22951 + unsigned char id[6];
22956 +static const device_id_t
22960 + {'G', 'l', 'o', 'b', 'a', 'l'},
22965 + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
22967 + "SpeedStream SS1021 or Gigafast WF721-AEX"
22970 + {0x80, 0x81, 0x82, 0x83, 0x84, 0x85},
22972 + "DrayTek Vigor 520"
22975 + {'?', '?', '?', '?', '?', '?'},
22977 + "Level One WPC-0200"
22980 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
22982 + "DWL-650+ variant"
22987 +acx_show_card_eeprom_id(wlandevice_t *priv)
22989 + unsigned char buffer[CARD_EEPROM_ID_SIZE];
22992 + memset(&buffer, 0, CARD_EEPROM_ID_SIZE);
22993 + /* use direct EEPROM access */
22994 + for (i = 0; i < CARD_EEPROM_ID_SIZE; i++) {
22995 + if (OK != acx_read_eeprom_offset(priv,
22996 + ACX100_EEPROM_ID_OFFSET + i,
22999 + printk("acx: reading EEPROM FAILED\n");
23004 + for (i = 0; i < VEC_SIZE(device_ids); i++) {
23005 + if (!memcmp(&buffer, device_ids[i].id, CARD_EEPROM_ID_SIZE)) {
23006 + if (device_ids[i].descr) {
23007 + printk("acx: EEPROM card ID string check "
23008 + "found %s card ID: is this %s?\n",
23009 + device_ids[i].descr, device_ids[i].type);
23014 + if (i == VEC_SIZE(device_ids)) {
23015 + printk("acx: EEPROM card ID string check found "
23016 + "unknown card: expected 'Global', got '%.*s\'. "
23017 + "Please report\n", CARD_EEPROM_ID_SIZE, buffer);
23020 +#endif /* NONESSENTIAL_FEATURES */
23023 +/***********************************************************************
23026 +acx_s_device_chain_add(struct net_device *dev)
23028 + wlandevice_t *priv = netdev_priv(dev);
23030 + down(&root_acx_dev_sem);
23031 + priv->prev_nd = root_acx_dev.newest;
23032 + root_acx_dev.newest = dev;
23033 + priv->netdev = dev;
23034 + up(&root_acx_dev_sem);
23038 +acx_s_device_chain_remove(struct net_device *dev)
23040 + struct net_device *querydev;
23041 + struct net_device *olderdev;
23042 + struct net_device *newerdev;
23044 + down(&root_acx_dev_sem);
23045 + querydev = root_acx_dev.newest;
23047 + while (querydev) {
23048 + olderdev = ((wlandevice_t*)netdev_priv(querydev))->prev_nd;
23049 + if (0 == strcmp(querydev->name, dev->name)) {
23051 + /* if we were at the beginning of the
23052 + * list, then it's the list head that
23053 + * we need to update to point at the
23054 + * next older device */
23055 + root_acx_dev.newest = olderdev;
23057 + /* it's the device that is newer than us
23058 + * that we need to update to point at
23059 + * the device older than us */
23060 + ((wlandevice_t*)netdev_priv(newerdev))->
23061 + prev_nd = olderdev;
23065 + /* "newerdev" is actually the device of the old iteration,
23066 + * but since the list starts (root_acx_dev.newest)
23067 + * with the newest devices,
23068 + * it's newer than the ones following.
23069 + * Oh the joys of iterating from newest to oldest :-\ */
23070 + newerdev = querydev;
23072 + /* keep checking old devices for matches until we hit the end
23074 + querydev = olderdev;
23076 + up(&root_acx_dev_sem);
23080 +/***********************************************************************
23081 +** acx_free_desc_queues
23083 +** Releases the queues that have been allocated, the
23084 +** others have been initialised to NULL so this
23085 +** function can be used if only part of the queues were allocated.
23087 +static inline void
23088 +acx_free_coherent(struct pci_dev *hwdev, size_t size,
23089 + void *vaddr, dma_addr_t dma_handle)
23091 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 53)
23092 + dma_free_coherent(hwdev == NULL ? NULL : &hwdev->dev,
23093 + size, vaddr, dma_handle);
23095 + pci_free_consistent(hwdev, size, vaddr, dma_handle);
23100 +acx_free_desc_queues(wlandevice_t *priv)
23102 +#define ACX_FREE_QUEUE(size, ptr, phyaddr) \
23104 + acx_free_coherent(0, size, ptr, phyaddr); \
23111 + ACX_FREE_QUEUE(priv->txhostdesc_area_size, priv->txhostdesc_start, priv->txhostdesc_startphy);
23112 + ACX_FREE_QUEUE(priv->txbuf_area_size, priv->txbuf_start, priv->txbuf_startphy);
23114 + priv->txdesc_start = NULL;
23116 + ACX_FREE_QUEUE(priv->rxhostdesc_area_size, priv->rxhostdesc_start, priv->rxhostdesc_startphy);
23117 + ACX_FREE_QUEUE(priv->rxbuf_area_size, priv->rxbuf_start, priv->rxbuf_startphy);
23119 + priv->rxdesc_start = NULL;
23125 +/*----------------------------------------------------------------
23126 +* acx_s_delete_dma_regions
23127 +*----------------------------------------------------------------*/
23129 +acx_s_delete_dma_regions(wlandevice_t *priv)
23131 + unsigned long flags;
23134 + /* disable radio Tx/Rx. Shouldn't we use the firmware commands
23135 + * here instead? Or are we that much down the road that it's no
23136 + * longer possible here? */
23137 + acx_write_reg16(priv, IO_ACX_ENABLE, 0);
23139 + acx_s_msleep(100);
23141 + acx_lock(priv, flags);
23142 + acx_free_desc_queues(priv);
23143 + acx_unlock(priv, flags);
23149 +/*----------------------------------------------------------------
23152 +* Probe routine called when a PCI device w/ matching ID is found.
23153 +* Here's the sequence:
23154 +* - Allocate the PCI resources.
23155 +* - Read the PCMCIA attribute memory to make sure we have a WLAN card
23157 +* - Initialize the dev and wlan data
23158 +* - Initialize the MAC
23161 +* pdev ptr to pci device structure containing info about
23162 +* pci configuration.
23163 +* id ptr to the device id entry that matched this device.
23167 +* negative - failed
23171 +----------------------------------------------------------------*/
23175 + 0x0000, /* IO_ACX_SOFT_RESET */
23177 + 0x0014, /* IO_ACX_SLV_MEM_ADDR */
23178 + 0x0018, /* IO_ACX_SLV_MEM_DATA */
23179 + 0x001c, /* IO_ACX_SLV_MEM_CTL */
23180 + 0x0020, /* IO_ACX_SLV_END_CTL */
23182 + 0x0034, /* IO_ACX_FEMR */
23184 + 0x007c, /* IO_ACX_INT_TRIG */
23185 + 0x0098, /* IO_ACX_IRQ_MASK */
23186 + 0x00a4, /* IO_ACX_IRQ_STATUS_NON_DES */
23187 + 0x00a8, /* IO_ACX_IRQ_STATUS_CLEAR */
23188 + 0x00ac, /* IO_ACX_IRQ_ACK */
23189 + 0x00b0, /* IO_ACX_HINT_TRIG */
23191 + 0x0104, /* IO_ACX_ENABLE */
23193 + 0x0250, /* IO_ACX_EEPROM_CTL */
23194 + 0x0254, /* IO_ACX_EEPROM_ADDR */
23195 + 0x0258, /* IO_ACX_EEPROM_DATA */
23196 + 0x025c, /* IO_ACX_EEPROM_CFG */
23198 + 0x0268, /* IO_ACX_PHY_ADDR */
23199 + 0x026c, /* IO_ACX_PHY_DATA */
23200 + 0x0270, /* IO_ACX_PHY_CTL */
23202 + 0x0290, /* IO_ACX_GPIO_OE */
23204 + 0x0298, /* IO_ACX_GPIO_OUT */
23206 + 0x02a4, /* IO_ACX_CMD_MAILBOX_OFFS */
23207 + 0x02a8, /* IO_ACX_INFO_MAILBOX_OFFS */
23208 + 0x02ac, /* IO_ACX_EEPROM_INFORMATION */
23210 + 0x02d0, /* IO_ACX_EE_START */
23211 + 0x02d4, /* IO_ACX_SOR_CFG */
23212 + 0x02d8 /* IO_ACX_ECPU_CTRL */
23218 + 0x0000, /* IO_ACX_SOFT_RESET */
23220 + 0x0014, /* IO_ACX_SLV_MEM_ADDR */
23221 + 0x0018, /* IO_ACX_SLV_MEM_DATA */
23222 + 0x001c, /* IO_ACX_SLV_MEM_CTL */
23223 + 0x0020, /* IO_ACX_SLV_END_CTL */
23225 + 0x0034, /* IO_ACX_FEMR */
23227 + 0x00b4, /* IO_ACX_INT_TRIG */
23228 + 0x00d4, /* IO_ACX_IRQ_MASK */
23229 + /* we need NON_DES (0xf0), not NON_DES_MASK which is at 0xe0: */
23230 + 0x00f0, /* IO_ACX_IRQ_STATUS_NON_DES */
23231 + 0x00e4, /* IO_ACX_IRQ_STATUS_CLEAR */
23232 + 0x00e8, /* IO_ACX_IRQ_ACK */
23233 + 0x00ec, /* IO_ACX_HINT_TRIG */
23235 + 0x01d0, /* IO_ACX_ENABLE */
23237 + 0x0338, /* IO_ACX_EEPROM_CTL */
23238 + 0x033c, /* IO_ACX_EEPROM_ADDR */
23239 + 0x0340, /* IO_ACX_EEPROM_DATA */
23240 + 0x0344, /* IO_ACX_EEPROM_CFG */
23242 + 0x0350, /* IO_ACX_PHY_ADDR */
23243 + 0x0354, /* IO_ACX_PHY_DATA */
23244 + 0x0358, /* IO_ACX_PHY_CTL */
23246 + 0x0374, /* IO_ACX_GPIO_OE */
23248 + 0x037c, /* IO_ACX_GPIO_OUT */
23250 + 0x0388, /* IO_ACX_CMD_MAILBOX_OFFS */
23251 + 0x038c, /* IO_ACX_INFO_MAILBOX_OFFS */
23252 + 0x0390, /* IO_ACX_EEPROM_INFORMATION */
23254 + 0x0100, /* IO_ACX_EE_START */
23255 + 0x0104, /* IO_ACX_SOR_CFG */
23256 + 0x0108, /* IO_ACX_ECPU_CTRL */
23260 +acx_netdev_init(struct net_device *dev) {}
23262 +//FIXME: do the same for USB
23264 +acx_change_mtu(struct net_device *dev, int mtu)
23268 + MAX_MTU = WLAN_DATA_MAXLEN - (ETH_HLEN)
23271 + if (mtu < MIN_MTU || mtu > MAX_MTU)
23278 +static int __devinit
23279 +acx_e_probe_pci(struct pci_dev *pdev, const struct pci_device_id *id)
23281 + unsigned long mem_region1 = 0;
23282 + unsigned long mem_region2 = 0;
23283 + unsigned long mem_region1_size;
23284 + unsigned long mem_region2_size;
23285 + unsigned long phymem1;
23286 + unsigned long phymem2;
23287 + void *mem1 = NULL;
23288 + void *mem2 = NULL;
23289 + wlandevice_t *priv = NULL;
23290 + struct net_device *dev = NULL;
23291 + const char *chip_name;
23292 + int result = -EIO;
23296 +#if SEPARATE_DRIVER_INSTANCES
23297 + struct pci_dev *tdev;
23298 + unsigned int inited;
23299 + static int turn = 0;
23300 +#endif /* SEPARATE_DRIVER_INSTANCES */
23304 +#if SEPARATE_DRIVER_INSTANCES
23308 + pci_for_each_dev(tdev) {
23309 + if (tdev->vendor != PCI_VENDOR_ID_TI)
23312 + if (tdev == pdev)
23314 + if (pci_get_drvdata(tdev))
23317 + if (inited + turn != card) {
23318 + result = -ENODEV;
23322 +#endif /* SEPARATE_DRIVER_INSTANCES */
23324 + /* Enable the PCI device */
23325 + if (pci_enable_device(pdev)) {
23326 + printk("acx: pci_enable_device() FAILED\n");
23327 + result = -ENODEV;
23328 + goto fail_pci_enable_device;
23331 + /* enable busmastering (required for CardBus) */
23332 + pci_set_master(pdev);
23334 + /* chiptype is u8 but id->driver_data is ulong
23335 + ** Works for now (possible values are 1 and 2) */
23336 + chip_type = (u8)id->driver_data;
23337 + /* acx100 and acx111 have different PCI memory regions */
23338 + if (chip_type == CHIPTYPE_ACX100) {
23339 + chip_name = name_acx100;
23340 + mem_region1 = PCI_ACX100_REGION1;
23341 + mem_region1_size = PCI_ACX100_REGION1_SIZE;
23343 + mem_region2 = PCI_ACX100_REGION2;
23344 + mem_region2_size = PCI_ACX100_REGION2_SIZE;
23345 + } else if (chip_type == CHIPTYPE_ACX111) {
23346 + chip_name = name_acx111;
23347 + mem_region1 = PCI_ACX111_REGION1;
23348 + mem_region1_size = PCI_ACX111_REGION1_SIZE;
23350 + mem_region2 = PCI_ACX111_REGION2;
23351 + mem_region2_size = PCI_ACX111_REGION2_SIZE;
23353 + printk("acx: unknown chip type 0x%04X\n", chip_type);
23354 + goto fail_unknown_chiptype;
23357 + /* Figure out our resources */
23358 + phymem1 = pci_resource_start(pdev, mem_region1);
23359 + phymem2 = pci_resource_start(pdev, mem_region2);
23361 + if (!request_mem_region(phymem1, pci_resource_len(pdev, mem_region1), "ACX1xx_1")) {
23362 + printk("acx: cannot reserve PCI memory region 1 (are you sure "
23363 + "you have CardBus support in kernel?)\n");
23364 + goto fail_request_mem_region1;
23367 + if (!request_mem_region(phymem2, pci_resource_len(pdev, mem_region2), "ACX1xx_2")) {
23368 + printk("acx: cannot reserve PCI memory region 2\n");
23369 + goto fail_request_mem_region2;
23372 + mem1 = ioremap(phymem1, mem_region1_size);
23373 + if (NULL == mem1) {
23374 + printk("acx: ioremap() FAILED\n");
23375 + goto fail_ioremap1;
23378 + mem2 = ioremap(phymem2, mem_region2_size);
23379 + if (NULL == mem2) {
23380 + printk("acx: ioremap() #2 FAILED\n");
23381 + goto fail_ioremap2;
23384 + /* Log the device */
23385 + printk("acx: found %s-based wireless network card at %s, irq:%d, "
23386 + "phymem1:0x%lX, phymem2:0x%lX, mem1:0x%p, mem1_size:%ld, "
23387 + "mem2:0x%p, mem2_size:%ld\n",
23388 + chip_name, pci_name(pdev), pdev->irq, phymem1, phymem2,
23389 + mem1, mem_region1_size,
23390 + mem2, mem_region2_size);
23391 + acxlog(L_ANY, "initial debug setting is 0x%04X\n", acx_debug);
23393 + if (0 == pdev->irq) {
23394 + printk("acx: can't use IRQ 0\n");
23398 + dev = alloc_netdev(sizeof(wlandevice_t), "wlan%d", acx_netdev_init);
23399 + /* (NB: memsets to 0 entire area) */
23401 + printk("acx: no memory for netdevice structure\n");
23402 + goto fail_alloc_netdev;
23405 + ether_setup(dev);
23406 + dev->open = &acx_e_open;
23407 + dev->stop = &acx_e_close;
23408 + dev->hard_start_xmit = &acx_i_start_xmit;
23409 + dev->get_stats = &acx_e_get_stats;
23410 + dev->get_wireless_stats = &acx_e_get_wireless_stats;
23411 +#if WIRELESS_EXT >= 13
23412 + dev->wireless_handlers = (struct iw_handler_def *)&acx_ioctl_handler_def;
23414 + dev->do_ioctl = &acx_e_ioctl_old;
23416 + dev->set_multicast_list = &acx_i_set_multicast_list;
23417 + dev->tx_timeout = &acx_i_tx_timeout;
23418 + dev->change_mtu = &acx_change_mtu;
23419 + dev->watchdog_timeo = 4 * HZ;
23420 + dev->irq = pdev->irq;
23421 + dev->base_addr = pci_resource_start(pdev, 0);
23423 + priv = netdev_priv(dev);
23424 + spin_lock_init(&priv->lock); /* initial state: unlocked */
23425 + /* We do not start with downed sem: we want PARANOID_LOCKING to work */
23426 + sema_init(&priv->sem, 1); /* initial state: 1 (upped) */
23427 + /* since nobody can see new netdev yet, we can as well
23428 + ** just _presume_ that we're under sem (instead of actually taking it): */
23429 + /* acx_sem_lock(priv); */
23430 + priv->pdev = pdev;
23431 + priv->dev_type = DEVTYPE_PCI;
23432 + priv->chip_type = chip_type;
23433 + priv->chip_name = chip_name;
23434 + priv->io = (CHIPTYPE_ACX100 == chip_type) ? IO_ACX100 : IO_ACX111;
23435 + priv->membase = phymem1;
23436 + priv->iobase = mem1;
23437 + priv->membase2 = phymem2;
23438 + priv->iobase2 = mem2;
23439 + /* to find crashes due to weird driver access
23440 + * to unconfigured interface (ifup) */
23441 + priv->mgmt_timer.function = (void (*)(unsigned long))0x0000dead;
23443 +#ifdef NONESSENTIAL_FEATURES
23444 + acx_show_card_eeprom_id(priv);
23445 +#endif /* NONESSENTIAL_FEATURES */
23447 + /* now we have our device, so make sure the kernel doesn't try
23448 + * to send packets even though we're not associated to a network yet */
23449 + acx_stop_queue(dev, "after setup");
23451 +#ifdef SET_MODULE_OWNER
23452 + SET_MODULE_OWNER(dev);
23454 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 70)
23455 + /* this define and its netdev member exist since 2.5.70 */
23456 + SET_NETDEV_DEV(dev, &pdev->dev);
23459 + /* register new dev in linked list */
23460 + acx_s_device_chain_add(dev);
23462 + acxlog(L_IRQ|L_INIT, "using IRQ %d\n", pdev->irq);
23464 + /* need to be able to restore PCI state after a suspend */
23465 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
23466 + /* 2.6.9-rc3-mm2 (2.6.9-bk4, too) introduced this shorter version,
23467 + then it made its way into 2.6.10 */
23468 + pci_save_state(pdev);
23470 + pci_save_state(pdev, priv->pci_state);
23473 + /* NB: acx_read_reg() reads may return bogus data before reset_dev().
23474 + ** acx100 seems to be more affected than acx111 */
23475 + if (OK != acx_s_reset_dev(dev)) {
23479 + /* ok, basic setup is finished, now start initialising the card */
23481 + if (OK != acx_read_eeprom_offset(priv, 0x05, &priv->eeprom_version)) {
23482 + goto fail_read_eeprom_version;
23485 + if (OK != acx_s_init_mac(dev)) {
23486 + printk("acx: init_mac() FAILED\n");
23487 + goto fail_init_mac;
23489 + if (OK != acx_s_set_defaults(priv)) {
23490 + printk("acx: set_defaults() FAILED\n");
23491 + goto fail_set_defaults;
23494 + /* needs to be after acx_s_init_mac() due to necessary init stuff */
23495 + acx_s_get_firmware_version(priv);
23497 + acx_display_hardware_details(priv);
23499 + pci_set_drvdata(pdev, dev);
23501 + /* ...and register the card, AFTER everything else has been set up,
23502 + * since otherwise an ioctl could step on our feet due to
23503 + * firmware operations happening in parallel or uninitialized data */
23504 + err = register_netdev(dev);
23506 + printk("acx: register_netdev() FAILED: %d\n", err);
23507 + goto fail_register_netdev;
23510 + acx_carrier_off(dev, "on probe");
23512 +#ifdef CONFIG_PROC_FS
23513 + if (OK != acx_proc_register_entries(dev)) {
23514 + goto fail_proc_register_entries;
23518 + /* after register_netdev() userspace may start working with dev
23519 + * (in particular, on other CPUs), we only need to up the sem */
23520 + /* acx_sem_unlock(priv); */
23522 + printk("acx "WLAN_RELEASE": net device %s, driver compiled "
23523 + "against wireless extensions %d and Linux %s\n",
23524 + dev->name, WIRELESS_EXT, UTS_RELEASE);
23527 + great_inquisitor(priv);
23533 + /* error paths: undo everything in reverse order... */
23535 +#ifdef CONFIG_PROC_FS
23536 +fail_proc_register_entries:
23538 + if (priv->dev_state_mask & ACX_STATE_IFACE_UP)
23541 + unregister_netdev(dev);
23543 + /* after unregister_netdev() userspace is guaranteed to finish
23544 + * working with it. netdev does not exist anymore.
23545 + * For paranoid reasons I am taking sem anyway */
23546 + acx_sem_lock(priv);
23549 +fail_register_netdev:
23551 + acx_s_delete_dma_regions(priv);
23552 + pci_set_drvdata(pdev, NULL);
23554 +fail_set_defaults:
23556 +fail_read_eeprom_version:
23559 + acx_s_device_chain_remove(dev);
23560 + free_netdev(dev);
23561 +fail_alloc_netdev:
23570 + release_mem_region(pci_resource_start(pdev, mem_region2),
23571 + pci_resource_len(pdev, mem_region2));
23572 +fail_request_mem_region2:
23574 + release_mem_region(pci_resource_start(pdev, mem_region1),
23575 + pci_resource_len(pdev, mem_region1));
23576 +fail_request_mem_region1:
23577 +fail_unknown_chiptype:
23579 + pci_disable_device(pdev);
23580 +fail_pci_enable_device:
23582 + pci_set_power_state(pdev, 3);
23585 + FN_EXIT1(result);
23590 +/*----------------------------------------------------------------
23591 +* acx_e_remove_pci
23593 +* Deallocate PCI resources for the ACX100 chip.
23595 +* This should NOT execute any other hardware operations on the card,
23596 +* since the card might already be ejected. Instead, that should be done
23597 +* in cleanup_module, since the card is most likely still available there.
23600 +* pdev ptr to PCI device structure containing info about
23601 +* PCI configuration.
23605 +----------------------------------------------------------------*/
23606 +static void __devexit
23607 +acx_e_remove_pci(struct pci_dev *pdev)
23609 + struct net_device *dev;
23610 + wlandevice_t *priv;
23611 + unsigned long mem_region1, mem_region2;
23615 + dev = (struct net_device *) pci_get_drvdata(pdev);
23617 + acxlog(L_DEBUG, "%s: card is unused. Skipping any release code\n",
23622 + priv = netdev_priv(dev);
23624 + /* unregister the device to not let the kernel
23625 + * (e.g. ioctls) access a half-deconfigured device
23626 + * NB: this will cause acx_e_close() to be called,
23627 + * thus we shouldn't call it under sem! */
23628 + acxlog(L_INIT, "removing device %s\n", dev->name);
23629 + unregister_netdev(dev);
23631 + /* unregister_netdev ensures that no references to us left.
23632 + * For paranoid reasons we continue to follow the rules */
23633 + acx_sem_lock(priv);
23635 + if (IS_ACX100(priv)) {
23636 + mem_region1 = PCI_ACX100_REGION1;
23637 + mem_region2 = PCI_ACX100_REGION2;
23639 + mem_region1 = PCI_ACX111_REGION1;
23640 + mem_region2 = PCI_ACX111_REGION2;
23643 +#ifdef CONFIG_PROC_FS
23644 + acx_proc_unregister_entries(dev);
23647 + /* find our PCI device in the global acx list and remove it */
23648 + acx_s_device_chain_remove(dev);
23650 + if (priv->dev_state_mask & ACX_STATE_IFACE_UP)
23653 + CLEAR_BIT(priv->dev_state_mask, ACX_STATE_IFACE_UP);
23655 + acx_s_delete_dma_regions(priv);
23657 + /* finally, clean up PCI bus state */
23658 + if (priv->iobase) iounmap(priv->iobase);
23659 + if (priv->iobase2) iounmap(priv->iobase2);
23661 + release_mem_region(pci_resource_start(pdev, mem_region1),
23662 + pci_resource_len(pdev, mem_region1));
23664 + release_mem_region(pci_resource_start(pdev, mem_region2),
23665 + pci_resource_len(pdev, mem_region2));
23667 + pci_disable_device(pdev);
23669 + /* remove dev registration */
23670 + pci_set_drvdata(pdev, NULL);
23672 + /* Free netdev (quite late,
23673 + * since otherwise we might get caught off-guard
23674 + * by a netdev timeout handler execution
23675 + * expecting to see a working dev...)
23676 + * But don't use free_netdev() here,
23677 + * it's supported by newer kernels only */
23678 + free_netdev(dev);
23680 + /* put device into ACPI D3 mode (shutdown) */
23681 + pci_set_power_state(pdev, 3);
23688 +/***********************************************************************
23691 +static int if_was_up = 0; /* FIXME: HACK, do it correctly sometime instead */
23693 +acx_e_suspend(struct pci_dev *pdev, pm_message_t state)
23695 + struct net_device *dev = pci_get_drvdata(pdev);
23696 + wlandevice_t *priv = netdev_priv(dev);
23700 + acx_sem_lock(priv);
23702 + printk("acx: experimental suspend handler called for %p\n", priv);
23703 + if (netif_device_present(dev)) {
23710 + netif_device_detach(dev); /* This one cannot sleep */
23711 + acx_s_delete_dma_regions(priv);
23713 + acx_sem_unlock(priv);
23720 +acx_e_resume(struct pci_dev *pdev)
23722 + struct net_device *dev;
23723 + wlandevice_t *priv;
23725 + printk(KERN_WARNING "rsm: resume\n");
23726 + dev = pci_get_drvdata(pdev);
23727 + printk(KERN_WARNING "rsm: got dev\n");
23729 + if (!netif_running(dev))
23732 + priv = netdev_priv(dev);
23734 + acx_sem_lock(priv);
23736 + printk(KERN_WARNING "rsm: got priv\n");
23738 + printk("acx: experimental resume handler called for %p!\n", priv);
23739 + pci_set_power_state(pdev, 0);
23740 + acxlog(L_DEBUG, "rsm: power state set\n");
23741 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
23742 + /* 2.6.9-rc3-mm2 (2.6.9-bk4, too) introduced this shorter version,
23743 + then it made its way into 2.6.10 */
23744 + pci_restore_state(pdev);
23746 + pci_restore_state(pdev, priv->pci_state);
23748 + acxlog(L_DEBUG, "rsm: PCI state restored\n");
23749 + acx_s_reset_dev(dev);
23750 + acxlog(L_DEBUG, "rsm: device reset done\n");
23752 + if (OK != acx_s_init_mac(dev)) {
23753 + printk("rsm: init_mac FAILED\n");
23756 + acxlog(L_DEBUG, "rsm: init MAC done\n");
23758 + if (1 == if_was_up)
23760 + acxlog(L_DEBUG, "rsm: acx up\n");
23762 + /* now even reload all card parameters as they were before suspend,
23763 + * and possibly be back in the network again already :-)
23764 + * FIXME: should this be done in that scheduled task instead?? */
23765 + if (ACX_STATE_IFACE_UP & priv->dev_state_mask)
23766 + acx_s_update_card_settings(priv, 0, 1);
23767 + acxlog(L_DEBUG, "rsm: settings updated\n");
23768 + netif_device_attach(dev);
23769 + acxlog(L_DEBUG, "rsm: device attached\n");
23770 +fail: /* we need to return OK here anyway, right? */
23771 + acx_sem_unlock(priv);
23775 +#endif /* CONFIG_PM */
23778 +/*----------------------------------------------------------------
23782 +* - Enables on-card interrupt requests
23783 +* - calls acx_start
23785 +* - process thread
23787 +* This function is called by acx_open (when ifconfig sets the
23789 +*----------------------------------------------------------------*/
23791 +acx_s_up(netdevice_t *dev)
23793 + wlandevice_t *priv = netdev_priv(dev);
23794 + unsigned long flags;
23798 + acx_lock(priv, flags);
23799 + acx_l_enable_irq(priv);
23800 + acx_unlock(priv, flags);
23802 + /* acx fw < 1.9.3.e has a hardware timer, and older drivers
23803 + ** used to use it. But we don't do that anymore, our OS
23804 + ** has reliable software timers */
23805 + init_timer(&priv->mgmt_timer);
23806 + priv->mgmt_timer.function = acx_i_timer;
23807 + priv->mgmt_timer.data = (unsigned long)priv;
23809 + /* Need to set ACX_STATE_IFACE_UP first, or else
23810 + ** timer won't be started by acx_set_status() */
23811 + SET_BIT(priv->dev_state_mask, ACX_STATE_IFACE_UP);
23812 + switch (priv->mode) {
23813 + case ACX_MODE_0_ADHOC:
23814 + case ACX_MODE_2_STA:
23815 + /* actual scan cmd will happen in start() */
23816 + acx_set_status(priv, ACX_STATUS_1_SCANNING); break;
23817 + case ACX_MODE_3_AP:
23818 + case ACX_MODE_MONITOR:
23819 + acx_set_status(priv, ACX_STATUS_4_ASSOCIATED); break;
23822 + acx_s_start(priv);
23828 +/*----------------------------------------------------------------
23832 +* - disables on-card interrupt request
23836 +* this disables the netdevice
23837 +*----------------------------------------------------------------*/
23839 +acx_s_down(netdevice_t *dev)
23841 + wlandevice_t *priv = netdev_priv(dev);
23842 + unsigned long flags;
23846 + /* Disable IRQs first, so that IRQs cannot race with us */
23847 + acx_lock(priv, flags);
23848 + acx_l_disable_irq(priv);
23849 + acx_unlock(priv, flags);
23851 + /* we really don't want to have an asynchronous tasklet disturb us
23852 + ** after something vital for its job has been shut down, so
23853 + ** end all remaining work now.
23855 + ** NB: carrier_off (done by set_status below) would lead to
23856 + ** not yet fully understood deadlock in FLUSH_SCHEDULED_WORK().
23857 + ** That's why we do FLUSH first.
23859 + ** NB2: we have a bad locking bug here: FLUSH_SCHEDULED_WORK()
23860 + ** waits for acx_e_after_interrupt_task to complete if it is running
23861 + ** on another CPU, but acx_e_after_interrupt_task
23862 + ** will sleep on sem forever, because it is taken by us!
23863 + ** Work around that by temporary sem unlock.
23864 + ** This will fail miserably if we'll be hit by concurrent
23865 + ** iwconfig or something in between. TODO! */
23866 + acx_sem_unlock(priv);
23867 + FLUSH_SCHEDULED_WORK();
23868 + acx_sem_lock(priv);
23870 + /* This is possible:
23871 + ** FLUSH_SCHEDULED_WORK -> acx_e_after_interrupt_task ->
23872 + ** -> set_status(ASSOCIATED) -> wake_queue()
23873 + ** That's why we stop queue _after_ FLUSH_SCHEDULED_WORK
23874 + ** lock/unlock is just paranoia, maybe not needed */
23875 + acx_lock(priv, flags);
23876 + acx_stop_queue(dev, "during close");
23877 + acx_set_status(priv, ACX_STATUS_0_STOPPED);
23878 + acx_unlock(priv, flags);
23880 + /* kernel/timer.c says it's illegal to del_timer_sync()
23881 + ** a timer which restarts itself. We guarantee this cannot
23882 + ** ever happen because acx_i_timer() never does this if
23883 + ** status is ACX_STATUS_0_STOPPED */
23884 + del_timer_sync(&priv->mgmt_timer);
23890 +/*----------------------------------------------------------------
23893 +* WLAN device open method. Called from p80211netdev when kernel
23894 +* device open (start) method is called in response to the
23895 +* SIOCSIFFLAGS ioctl changing the flags bit IFF_UP
23896 +* from clear to set.
23900 +* >0 f/w reported error
23901 +* <0 driver reported error
23905 +----------------------------------------------------------------*/
23907 +acx_e_open(netdevice_t *dev)
23909 + wlandevice_t *priv = netdev_priv(dev);
23914 + acxlog(L_INIT, "module count++\n");
23915 + WLAN_MOD_INC_USE_COUNT;
23917 + acx_sem_lock(priv);
23919 + acx_init_task_scheduler(priv);
23921 + /* request shared IRQ handler */
23922 + if (request_irq(dev->irq, acx_i_interrupt, SA_SHIRQ, dev->name, dev)) {
23923 + printk("%s: request_irq FAILED\n", dev->name);
23924 + result = -EAGAIN;
23927 + acxlog(L_DEBUG|L_IRQ, "request_irq %d successful\n", dev->irq);
23929 + /* ifup device */
23932 + /* We don't currently have to do anything else.
23933 + * The setup of the MAC should be subsequently completed via
23934 + * the mlme commands.
23935 + * Higher layers know we're ready from dev->start==1 and
23936 + * dev->tbusy==0. Our rx path knows to pass up received/
23937 + * frames because of dev->flags&IFF_UP is true.
23940 + acx_sem_unlock(priv);
23942 + FN_EXIT1(result);
23947 +/*----------------------------------------------------------------
23950 +* WLAN device close method. Called from network core when kernel
23951 +* device close method is called in response to the
23952 +* SIOCSIIFFLAGS ioctl changing the flags bit IFF_UP
23953 +* from set to clear.
23954 +* (i.e. called for "ifconfig DEV down")
23958 +* >0 f/w reported error
23959 +* <0 driver reported error
23963 +----------------------------------------------------------------*/
23965 +acx_e_close(netdevice_t *dev)
23967 + wlandevice_t *priv = netdev_priv(dev);
23971 + acx_sem_lock(priv);
23973 + /* ifdown device */
23974 + CLEAR_BIT(priv->dev_state_mask, ACX_STATE_IFACE_UP);
23975 + if (netif_device_present(dev)) {
23979 + /* disable all IRQs, release shared IRQ handler */
23980 + acx_write_reg16(priv, IO_ACX_IRQ_MASK, 0xffff);
23981 + acx_write_reg16(priv, IO_ACX_FEMR, 0x0);
23982 + free_irq(dev->irq, dev);
23984 + /* We currently don't have to do anything else.
23985 + * Higher layers know we're not ready from dev->start==0 and
23986 + * dev->tbusy==1. Our rx path knows to not pass up received
23987 + * frames because of dev->flags&IFF_UP is false.
23989 + acxlog(L_INIT, "module count--\n");
23990 + WLAN_MOD_DEC_USE_COUNT;
23992 + acx_sem_unlock(priv);
23994 + acxlog(L_INIT, "closed device\n");
24000 +/*----------------------------------------------------------------
24001 +* acx_i_tx_timeout
24003 +* Called from network core. Must not sleep!
24004 +*----------------------------------------------------------------*/
24006 +acx_i_tx_timeout(netdevice_t *dev)
24008 + wlandevice_t *priv = netdev_priv(dev);
24009 + unsigned long flags;
24010 + unsigned int tx_num_cleaned;
24014 + acx_lock(priv, flags);
24016 + /* clean processed tx descs, they may have been completely full */
24017 + tx_num_cleaned = acx_l_clean_tx_desc(priv);
24019 + /* nothing cleaned, yet (almost) no free buffers available?
24020 + * --> clean all tx descs, no matter which status!!
24021 + * Note that I strongly suspect that doing emergency cleaning
24022 + * may confuse the firmware. This is a last ditch effort to get
24023 + * ANYTHING to work again...
24025 + * TODO: it's best to simply reset & reinit hw from scratch...
24027 + if ((priv->tx_free <= TX_EMERG_CLEAN) && (tx_num_cleaned == 0)) {
24028 + printk("%s: FAILED to free any of the many full tx buffers. "
24029 + "Switching to emergency freeing. "
24030 + "Please report!\n", dev->name);
24031 + acx_l_clean_tx_desc_emergency(priv);
24034 + if (acx_queue_stopped(dev) && (ACX_STATUS_4_ASSOCIATED == priv->status))
24035 + acx_wake_queue(dev, "after tx timeout");
24037 + /* stall may have happened due to radio drift, so recalib radio */
24038 + acx_schedule_after_interrupt_task(priv, ACX_AFTER_IRQ_CMD_RADIO_RECALIB);
24040 + /* do unimportant work last */
24041 + printk("%s: tx timeout!\n", dev->name);
24042 + priv->stats.tx_errors++;
24044 + acx_unlock(priv, flags);
24050 +/*----------------------------------------------------------------
24052 +*----------------------------------------------------------------*/
24053 +static struct net_device_stats*
24054 +acx_e_get_stats(netdevice_t *dev)
24056 + wlandevice_t *priv = netdev_priv(dev);
24057 + return &priv->stats;
24061 +/*----------------------------------------------------------------
24062 +* acx_e_get_wireless_stats
24063 +*----------------------------------------------------------------*/
24064 +static struct iw_statistics*
24065 +acx_e_get_wireless_stats(netdevice_t *dev)
24067 + wlandevice_t *priv = netdev_priv(dev);
24068 + return &priv->wstats;
24072 +/*----------------------------------------------------------------
24073 +* acx_i_set_multicast_list
24074 +* FIXME: most likely needs refinement
24075 +*----------------------------------------------------------------*/
24077 +acx_i_set_multicast_list(netdevice_t *dev)
24079 + wlandevice_t *priv = netdev_priv(dev);
24080 + unsigned long flags;
24084 + acx_lock(priv, flags);
24086 + /* firmwares don't have allmulti capability,
24087 + * so just use promiscuous mode instead in this case. */
24088 + if (dev->flags & (IFF_PROMISC|IFF_ALLMULTI)) {
24089 + SET_BIT(priv->rx_config_1, RX_CFG1_RCV_PROMISCUOUS);
24090 + CLEAR_BIT(priv->rx_config_1, RX_CFG1_FILTER_ALL_MULTI);
24091 + SET_BIT(priv->set_mask, SET_RXCONFIG);
24092 + /* let kernel know in case *we* needed to set promiscuous */
24093 + dev->flags |= (IFF_PROMISC|IFF_ALLMULTI);
24095 + CLEAR_BIT(priv->rx_config_1, RX_CFG1_RCV_PROMISCUOUS);
24096 + SET_BIT(priv->rx_config_1, RX_CFG1_FILTER_ALL_MULTI);
24097 + SET_BIT(priv->set_mask, SET_RXCONFIG);
24098 + dev->flags &= ~(IFF_PROMISC|IFF_ALLMULTI);
24101 + /* cannot update card settings directly here, atomic context */
24102 + acx_schedule_after_interrupt_task(priv, ACX_AFTER_IRQ_UPDATE_CARD_CFG);
24104 + acx_unlock(priv, flags);
24110 +acx_l_update_link_quality_led(wlandevice_t *priv)
24114 + qual = acx_signal_determine_quality(priv->wstats.qual.level, priv->wstats.qual.noise);
24115 + if (qual > priv->brange_max_quality)
24116 + qual = priv->brange_max_quality;
24118 + if (time_after(jiffies, priv->brange_time_last_state_change +
24119 + (HZ/2 - HZ/2 * (unsigned long) qual/priv->brange_max_quality ) )) {
24120 + acx_l_power_led(priv, (priv->brange_last_state == 0));
24121 + priv->brange_last_state ^= 1; /* toggle */
24122 + priv->brange_time_last_state_change = jiffies;
24127 +/*----------------------------------------------------------------
24128 +* acx_l_enable_irq
24129 +*----------------------------------------------------------------*/
24131 +acx_l_enable_irq(wlandevice_t *priv)
24134 + acx_write_reg16(priv, IO_ACX_IRQ_MASK, priv->irq_mask);
24135 + acx_write_reg16(priv, IO_ACX_FEMR, 0x8000);
24136 + priv->irqs_active = 1;
24141 +/*----------------------------------------------------------------
24142 +* acx_l_disable_irq
24143 +*----------------------------------------------------------------*/
24145 +acx_l_disable_irq(wlandevice_t *priv)
24148 + acx_write_reg16(priv, IO_ACX_IRQ_MASK, priv->irq_mask_off);
24149 + acx_write_reg16(priv, IO_ACX_FEMR, 0x0);
24150 + priv->irqs_active = 0;
24154 +/* scan is complete. all frames now on the receive queue are valid */
24155 +#define INFO_SCAN_COMPLETE 0x0001
24156 +#define INFO_WEP_KEY_NOT_FOUND 0x0002
24157 +/* hw has been reset as the result of a watchdog timer timeout */
24158 +#define INFO_WATCH_DOG_RESET 0x0003
24159 +/* failed to send out NULL frame from PS mode notification to AP */
24160 +/* recommended action: try entering 802.11 PS mode again */
24161 +#define INFO_PS_FAIL 0x0004
24162 +/* encryption/decryption process on a packet failed */
24163 +#define INFO_IV_ICV_FAILURE 0x0005
24166 +acx_l_handle_info_irq(wlandevice_t *priv)
24169 + static const char * const info_type_msg[] = {
24172 + "WEP key not found",
24173 + "internal watchdog reset was done",
24174 + "failed to send powersave (NULL frame) notification to AP",
24175 + "encrypt/decrypt on a packet has failed",
24176 + "TKIP tx keys disabled",
24177 + "TKIP rx keys disabled",
24178 + "TKIP rx: key ID not found",
24186 + "TKIP IV value exceeds thresh"
24189 + acx_read_info_status(priv);
24190 + acxlog(L_IRQ, "got Info IRQ: status 0x%04X type 0x%04X: %s\n",
24191 + priv->info_status, priv->info_type,
24192 + info_type_msg[(priv->info_type >= VEC_SIZE(info_type_msg)) ?
24193 + 0 : priv->info_type]
24198 +/*----------------------------------------------------------------
24201 +* IRQ handler (atomic context, must not sleep, blah, blah)
24202 +*----------------------------------------------------------------*/
24204 +acx_log_unusual_irq(u16 irqtype) {
24206 + if (!printk_ratelimit())
24210 + printk("acx: got");
24211 + if (irqtype & HOST_INT_RX_DATA) {
24212 + printk(" Rx_Data");
24214 + /* HOST_INT_TX_COMPLETE */
24215 + if (irqtype & HOST_INT_TX_XFER) {
24216 + printk(" Tx_Xfer");
24218 + /* HOST_INT_RX_COMPLETE */
24219 + if (irqtype & HOST_INT_DTIM) {
24222 + if (irqtype & HOST_INT_BEACON) {
24223 + printk(" Beacon");
24225 + if (irqtype & HOST_INT_TIMER) {
24226 + acxlog(L_IRQ, " Timer");
24228 + if (irqtype & HOST_INT_KEY_NOT_FOUND) {
24229 + printk(" Key_Not_Found");
24231 + if (irqtype & HOST_INT_IV_ICV_FAILURE) {
24232 + printk(" IV_ICV_Failure");
24234 + /* HOST_INT_CMD_COMPLETE */
24235 + /* HOST_INT_INFO */
24236 + if (irqtype & HOST_INT_OVERFLOW) {
24237 + printk(" Overflow");
24239 + if (irqtype & HOST_INT_PROCESS_ERROR) {
24240 + printk(" Process_Error");
24242 + /* HOST_INT_SCAN_COMPLETE */
24243 + if (irqtype & HOST_INT_FCS_THRESHOLD) {
24244 + printk(" FCS_Threshold");
24246 + if (irqtype & HOST_INT_UNKNOWN) {
24247 + printk(" Unknown");
24249 + printk(" IRQ(s)\n");
24252 +static irqreturn_t
24253 +acx_i_interrupt(int irq, void *dev_id, struct pt_regs *regs)
24255 + wlandevice_t *priv;
24256 + unsigned long flags;
24257 + unsigned int irqcount = MAX_IRQLOOPS_PER_JIFFY;
24258 + u16 irqtype, unmasked;
24260 + priv = (wlandevice_t *) (((netdevice_t *) dev_id)->priv);
24262 + /* LOCKING: can just spin_lock() since IRQs are disabled anyway.
24263 + * I am paranoid */
24264 + acx_lock(priv, flags);
24266 + unmasked = acx_read_reg16(priv, IO_ACX_IRQ_STATUS_CLEAR);
24267 + if (unlikely(0xffff == unmasked)) {
24268 + /* 0xffff value hints at missing hardware,
24269 + * so don't do anything.
24270 + * FIXME: that's not very clean - maybe we are able to
24271 + * establish a flag which definitely tells us that some
24272 + * hardware is absent and which we could check here?
24273 + * Hmm, but other drivers do the very same thing... */
24274 + acxlog(L_IRQ, "IRQ type:FFFF - device removed? IRQ_NONE\n");
24278 + /* We will check only "interesting" IRQ types */
24279 + irqtype = unmasked & ~priv->irq_mask;
24281 + /* We are on a shared IRQ line and it wasn't our IRQ */
24282 + acxlog(L_IRQ, "IRQ type:%04X, mask:%04X - all are masked, IRQ_NONE\n",
24283 + unmasked, priv->irq_mask);
24287 + /* Done here because IRQ_NONEs taking three lines of log
24288 + ** drive me crazy */
24291 +#define IRQ_ITERATE 1
24293 +if (jiffies != priv->irq_last_jiffies) {
24294 + priv->irq_loops_this_jiffy = 0;
24295 + priv->irq_last_jiffies = jiffies;
24298 +/* safety condition; we'll normally abort loop below
24299 + * in case no IRQ type occurred */
24300 +while (--irqcount) {
24302 + /* ACK all IRQs asap */
24303 + acx_write_reg16(priv, IO_ACX_IRQ_ACK, 0xffff);
24305 + acxlog(L_IRQ, "IRQ type:%04X, mask:%04X, type & ~mask:%04X\n",
24306 + unmasked, priv->irq_mask, irqtype);
24308 + /* Handle most important IRQ types first */
24309 + if (irqtype & HOST_INT_RX_COMPLETE) {
24310 + acxlog(L_IRQ, "got Rx_Complete IRQ\n");
24311 + acx_l_process_rx_desc(priv);
24313 + if (irqtype & HOST_INT_TX_COMPLETE) {
24314 + acxlog(L_IRQ, "got Tx_Complete IRQ\n");
24315 + /* don't clean up on each Tx complete, wait a bit
24316 + * unless we're going towards full, in which case
24317 + * we do it immediately, too (otherwise we might lockup
24318 + * with a full Tx buffer if we go into
24319 + * acx_l_clean_tx_desc() at a time when we won't wakeup
24320 + * the net queue in there for some reason...) */
24321 + if (priv->tx_free <= TX_START_CLEAN) {
24322 +#if TX_CLEANUP_IN_SOFTIRQ
24323 + acx_schedule_after_interrupt_task(priv, ACX_AFTER_IRQ_TX_CLEANUP);
24325 + acx_l_clean_tx_desc(priv);
24330 + /* Less frequent ones */
24332 + | HOST_INT_CMD_COMPLETE
24334 + | HOST_INT_SCAN_COMPLETE
24336 + if (irqtype & HOST_INT_CMD_COMPLETE) {
24337 + acxlog(L_IRQ, "got Command_Complete IRQ\n");
24338 + /* save the state for the running issue_cmd() */
24339 + SET_BIT(priv->irq_status, HOST_INT_CMD_COMPLETE);
24341 + if (irqtype & HOST_INT_INFO) {
24342 + acx_l_handle_info_irq(priv);
24344 + if (irqtype & HOST_INT_SCAN_COMPLETE) {
24345 + acxlog(L_IRQ, "got Scan_Complete IRQ\n");
24346 + /* need to do that in process context */
24347 + acx_schedule_after_interrupt_task(priv, ACX_AFTER_IRQ_COMPLETE_SCAN);
24348 + /* remember that fw is not scanning anymore */
24349 + SET_BIT(priv->irq_status, HOST_INT_SCAN_COMPLETE);
24353 + /* These we just log, but either they happen rarely
24354 + * or we keep them masked out */
24356 + | HOST_INT_RX_DATA
24357 + /* | HOST_INT_TX_COMPLETE */
24358 + | HOST_INT_TX_XFER
24359 + /* | HOST_INT_RX_COMPLETE */
24361 + | HOST_INT_BEACON
24363 + | HOST_INT_KEY_NOT_FOUND
24364 + | HOST_INT_IV_ICV_FAILURE
24365 + /* | HOST_INT_CMD_COMPLETE */
24366 + /* | HOST_INT_INFO */
24367 + | HOST_INT_OVERFLOW
24368 + | HOST_INT_PROCESS_ERROR
24369 + /* | HOST_INT_SCAN_COMPLETE */
24370 + | HOST_INT_FCS_THRESHOLD
24371 + | HOST_INT_UNKNOWN
24373 + acx_log_unusual_irq(irqtype);
24377 + unmasked = acx_read_reg16(priv, IO_ACX_IRQ_STATUS_CLEAR);
24378 + irqtype = unmasked & ~priv->irq_mask;
24379 + /* Bail out if no new IRQ bits or if all are masked out */
24383 + if (unlikely(++priv->irq_loops_this_jiffy > MAX_IRQLOOPS_PER_JIFFY)) {
24384 + printk(KERN_ERR "acx: too many interrupts per jiffy!\n");
24385 + /* Looks like card floods us with IRQs! Try to stop that */
24386 + acx_write_reg16(priv, IO_ACX_IRQ_MASK, 0xffff);
24387 + /* This will short-circuit all future attempts to handle IRQ.
24388 + * We cant do much more... */
24389 + priv->irq_mask = 0;
24394 + /* Routine to perform blink with range */
24395 + if (unlikely(priv->led_power == 2))
24396 + acx_l_update_link_quality_led(priv);
24399 + /* acx_write_flush(priv); - not needed, last op was read anyway */
24400 + acx_unlock(priv, flags);
24402 + return IRQ_HANDLED;
24405 + acx_unlock(priv, flags);
24410 +/*----------------------------------------------------------------
24412 +*----------------------------------------------------------------*/
24414 +acx_l_power_led(wlandevice_t *priv, int enable)
24416 + u16 gpio_pled = IS_ACX111(priv) ? 0x0040 : 0x0800;
24418 + /* A hack. Not moving message rate limiting to priv->xxx
24419 + * (it's only a debug message after all) */
24420 + static int rate_limit = 0;
24422 + if (rate_limit++ < 3)
24423 + acxlog(L_IOCTL, "Please report in case toggling the power "
24424 + "LED doesn't work for your card!\n");
24426 + acx_write_reg16(priv, IO_ACX_GPIO_OUT,
24427 + acx_read_reg16(priv, IO_ACX_GPIO_OUT) & ~gpio_pled);
24429 + acx_write_reg16(priv, IO_ACX_GPIO_OUT,
24430 + acx_read_reg16(priv, IO_ACX_GPIO_OUT) | gpio_pled);
24434 +/***********************************************************************
24438 +/***********************************************************************
24441 +acx111pci_ioctl_info(
24442 + struct net_device *dev,
24443 + struct iw_request_info *info,
24444 + struct iw_param *vwrq,
24448 + wlandevice_t *priv = netdev_priv(dev);
24449 + rxdesc_t *rxdesc;
24450 + txdesc_t *txdesc;
24451 + rxhostdesc_t *rxhostdesc;
24452 + txhostdesc_t *txhostdesc;
24453 + struct acx111_ie_memoryconfig memconf;
24454 + struct acx111_ie_queueconfig queueconf;
24455 + unsigned long flags;
24457 + char memmap[0x34];
24458 + char rxconfig[0x8];
24459 + char fcserror[0x8];
24460 + char ratefallback[0x5];
24462 + if ( !(acx_debug & (L_IOCTL|L_DEBUG)) )
24464 + /* using printk() since we checked debug flag already */
24466 + acx_sem_lock(priv);
24468 + if (!IS_ACX111(priv)) {
24469 + printk("acx111-specific function called "
24470 + "with non-acx111 chip, aborting\n");
24474 + /* get Acx111 Memory Configuration */
24475 + memset(&memconf, 0, sizeof(memconf));
24476 + /* BTW, fails with 12 (Write only) error code.
24477 + ** Retained for easy testing of issue_cmd error handling :) */
24478 + acx_s_interrogate(priv, &memconf, ACX1xx_IE_QUEUE_CONFIG);
24480 + /* get Acx111 Queue Configuration */
24481 + memset(&queueconf, 0, sizeof(queueconf));
24482 + acx_s_interrogate(priv, &queueconf, ACX1xx_IE_MEMORY_CONFIG_OPTIONS);
24484 + /* get Acx111 Memory Map */
24485 + memset(memmap, 0, sizeof(memmap));
24486 + acx_s_interrogate(priv, &memmap, ACX1xx_IE_MEMORY_MAP);
24488 + /* get Acx111 Rx Config */
24489 + memset(rxconfig, 0, sizeof(rxconfig));
24490 + acx_s_interrogate(priv, &rxconfig, ACX1xx_IE_RXCONFIG);
24492 + /* get Acx111 fcs error count */
24493 + memset(fcserror, 0, sizeof(fcserror));
24494 + acx_s_interrogate(priv, &fcserror, ACX1xx_IE_FCS_ERROR_COUNT);
24496 + /* get Acx111 rate fallback */
24497 + memset(ratefallback, 0, sizeof(ratefallback));
24498 + acx_s_interrogate(priv, &ratefallback, ACX1xx_IE_RATE_FALLBACK);
24500 + /* force occurrence of a beacon interrupt */
24501 + /* TODO: comment why is this necessary */
24502 + acx_write_reg16(priv, IO_ACX_HINT_TRIG, HOST_INT_BEACON);
24504 + /* dump Acx111 Mem Configuration */
24505 + printk("dump mem config:\n"
24506 + "data read: %d, struct size: %d\n"
24507 + "Number of stations: %1X\n"
24508 + "Memory block size: %1X\n"
24509 + "tx/rx memory block allocation: %1X\n"
24510 + "count rx: %X / tx: %X queues\n"
24512 + "fragmentation %1X\n"
24513 + "Rx Queue 1 Count Descriptors: %X\n"
24514 + "Rx Queue 1 Host Memory Start: %X\n"
24515 + "Tx Queue 1 Count Descriptors: %X\n"
24516 + "Tx Queue 1 Attributes: %X\n",
24517 + memconf.len, (int) sizeof(memconf),
24518 + memconf.no_of_stations,
24519 + memconf.memory_block_size,
24520 + memconf.tx_rx_memory_block_allocation,
24521 + memconf.count_rx_queues, memconf.count_tx_queues,
24523 + memconf.fragmentation,
24524 + memconf.rx_queue1_count_descs,
24525 + acx2cpu(memconf.rx_queue1_host_rx_start),
24526 + memconf.tx_queue1_count_descs,
24527 + memconf.tx_queue1_attributes);
24529 + /* dump Acx111 Queue Configuration */
24530 + printk("dump queue head:\n"
24531 + "data read: %d, struct size: %d\n"
24532 + "tx_memory_block_address (from card): %X\n"
24533 + "rx_memory_block_address (from card): %X\n"
24534 + "rx1_queue address (from card): %X\n"
24535 + "tx1_queue address (from card): %X\n"
24536 + "tx1_queue attributes (from card): %X\n",
24537 + queueconf.len, (int) sizeof(queueconf),
24538 + queueconf.tx_memory_block_address,
24539 + queueconf.rx_memory_block_address,
24540 + queueconf.rx1_queue_address,
24541 + queueconf.tx1_queue_address,
24542 + queueconf.tx1_attributes);
24544 + /* dump Acx111 Mem Map */
24545 + printk("dump mem map:\n"
24546 + "data read: %d, struct size: %d\n"
24547 + "Code start: %X\n"
24549 + "WEP default key start: %X\n"
24550 + "WEP default key end: %X\n"
24551 + "STA table start: %X\n"
24552 + "STA table end: %X\n"
24553 + "Packet template start: %X\n"
24554 + "Packet template end: %X\n"
24555 + "Queue memory start: %X\n"
24556 + "Queue memory end: %X\n"
24557 + "Packet memory pool start: %X\n"
24558 + "Packet memory pool end: %X\n"
24561 + *((u16 *)&memmap[0x02]), (int) sizeof(memmap),
24562 + *((u32 *)&memmap[0x04]),
24563 + *((u32 *)&memmap[0x08]),
24564 + *((u32 *)&memmap[0x0C]),
24565 + *((u32 *)&memmap[0x10]),
24566 + *((u32 *)&memmap[0x14]),
24567 + *((u32 *)&memmap[0x18]),
24568 + *((u32 *)&memmap[0x1C]),
24569 + *((u32 *)&memmap[0x20]),
24570 + *((u32 *)&memmap[0x24]),
24571 + *((u32 *)&memmap[0x28]),
24572 + *((u32 *)&memmap[0x2C]),
24573 + *((u32 *)&memmap[0x30]),
24577 + /* dump Acx111 Rx Config */
24578 + printk("dump rx config:\n"
24579 + "data read: %d, struct size: %d\n"
24580 + "rx config: %X\n"
24581 + "rx filter config: %X\n",
24582 + *((u16 *)&rxconfig[0x02]), (int) sizeof(rxconfig),
24583 + *((u16 *)&rxconfig[0x04]),
24584 + *((u16 *)&rxconfig[0x06]));
24586 + /* dump Acx111 fcs error */
24587 + printk("dump fcserror:\n"
24588 + "data read: %d, struct size: %d\n"
24589 + "fcserrors: %X\n",
24590 + *((u16 *)&fcserror[0x02]), (int) sizeof(fcserror),
24591 + *((u32 *)&fcserror[0x04]));
24593 + /* dump Acx111 rate fallback */
24594 + printk("dump rate fallback:\n"
24595 + "data read: %d, struct size: %d\n"
24596 + "ratefallback: %X\n",
24597 + *((u16 *)&ratefallback[0x02]), (int) sizeof(ratefallback),
24598 + *((u8 *)&ratefallback[0x04]));
24600 + /* protect against IRQ */
24601 + acx_lock(priv, flags);
24603 + /* dump acx111 internal rx descriptor ring buffer */
24604 + rxdesc = priv->rxdesc_start;
24606 + /* loop over complete receive pool */
24607 + if (rxdesc) for (i = 0; i < RX_CNT; i++) {
24608 + printk("\ndump internal rxdesc %d:\n"
24611 + "acx mem pointer (dynamic) 0x%X\n"
24612 + "CTL (dynamic) 0x%X\n"
24613 + "Rate (dynamic) 0x%X\n"
24614 + "RxStatus (dynamic) 0x%X\n"
24615 + "Mod/Pre (dynamic) 0x%X\n",
24618 + acx2cpu(rxdesc->pNextDesc),
24619 + acx2cpu(rxdesc->ACXMemPtr),
24627 + /* dump host rx descriptor ring buffer */
24629 + rxhostdesc = priv->rxhostdesc_start;
24631 + /* loop over complete receive pool */
24632 + if (rxhostdesc) for (i = 0; i < RX_CNT; i++) {
24633 + printk("\ndump host rxdesc %d:\n"
24635 + "buffer mem pos 0x%X\n"
24636 + "buffer mem offset 0x%X\n"
24643 + acx2cpu(rxhostdesc->data_phy),
24644 + rxhostdesc->data_offset,
24645 + le16_to_cpu(rxhostdesc->Ctl_16),
24646 + le16_to_cpu(rxhostdesc->length),
24647 + acx2cpu(rxhostdesc->desc_phy_next),
24648 + rxhostdesc->Status);
24652 + /* dump acx111 internal tx descriptor ring buffer */
24653 + txdesc = priv->txdesc_start;
24655 + /* loop over complete transmit pool */
24656 + if (txdesc) for (i = 0; i < TX_CNT; i++) {
24657 + printk("\ndump internal txdesc %d:\n"
24661 + "acx mem pointer (dynamic) 0x%X\n"
24662 + "host mem pointer (dynamic) 0x%X\n"
24663 + "length (dynamic) 0x%X\n"
24664 + "CTL (dynamic) 0x%X\n"
24665 + "CTL2 (dynamic) 0x%X\n"
24666 + "Status (dynamic) 0x%X\n"
24667 + "Rate (dynamic) 0x%X\n",
24669 + (int) sizeof(struct txdesc),
24671 + acx2cpu(txdesc->pNextDesc),
24672 + acx2cpu(txdesc->AcxMemPtr),
24673 + acx2cpu(txdesc->HostMemPtr),
24674 + le16_to_cpu(txdesc->total_length),
24676 + txdesc->Ctl2_8, txdesc->error,
24677 + txdesc->u.r1.rate);
24678 + txdesc = move_txdesc(priv, txdesc, 1);
24681 + /* dump host tx descriptor ring buffer */
24683 + txhostdesc = priv->txhostdesc_start;
24685 + /* loop over complete host send pool */
24686 + if (txhostdesc) for (i = 0; i < TX_CNT * 2; i++) {
24687 + printk("\ndump host txdesc %d:\n"
24689 + "buffer mem pos 0x%X\n"
24690 + "buffer mem offset 0x%X\n"
24697 + acx2cpu(txhostdesc->data_phy),
24698 + txhostdesc->data_offset,
24699 + le16_to_cpu(txhostdesc->Ctl_16),
24700 + le16_to_cpu(txhostdesc->length),
24701 + acx2cpu(txhostdesc->desc_phy_next),
24702 + le32_to_cpu(txhostdesc->Status));
24706 + /* acx_write_reg16(priv, 0xb4, 0x4); */
24708 + acx_unlock(priv, flags);
24711 + acx_sem_unlock(priv);
24712 +#endif /* ACX_DEBUG */
24717 +/***********************************************************************
24720 +acx100pci_ioctl_set_phy_amp_bias(
24721 + struct net_device *dev,
24722 + struct iw_request_info *info,
24723 + struct iw_param *vwrq,
24726 + wlandevice_t *priv = netdev_priv(dev);
24727 + unsigned long flags;
24730 + if (!IS_ACX100(priv)) {
24732 + * Removing this check *might* damage
24733 + * hardware, since we're tweaking GPIOs here after all!!!
24734 + * You've been warned...
24736 + printk("acx: sorry, setting bias level for non-acx100 "
24737 + "is not supported yet\n");
24741 + if (*extra > 7) {
24742 + printk("acx: invalid bias parameter, range is 0-7\n");
24746 + acx_sem_lock(priv);
24748 + /* Need to lock accesses to [IO_ACX_GPIO_OUT]:
24749 + * IRQ handler uses it to update LED */
24750 + acx_lock(priv, flags);
24751 + gpio_old = acx_read_reg16(priv, IO_ACX_GPIO_OUT);
24752 + acx_write_reg16(priv, IO_ACX_GPIO_OUT, (gpio_old & 0xf8ff) | ((u16)*extra << 8));
24753 + acx_unlock(priv, flags);
24755 + acxlog(L_DEBUG, "gpio_old: 0x%04X\n", gpio_old);
24756 + printk("%s: PHY power amplifier bias: old:%d, new:%d\n",
24758 + (gpio_old & 0x0700) >> 8, (unsigned char)*extra);
24760 + acx_sem_unlock(priv);
24766 +/***************************************************************
24767 +** acxpci_l_alloc_tx
24768 +** Actually returns a txdesc_t* ptr
24771 +acxpci_l_alloc_tx(wlandevice_t* priv)
24773 + struct txdesc *txdesc;
24778 + txdesc = get_txdesc(priv, priv->tx_head);
24779 + ctl8 = txdesc->Ctl_8;
24780 + if (unlikely(DESC_CTL_HOSTOWN != (ctl8 & DESC_CTL_DONE))) {
24781 + /* whoops, descr at current index is not free, so probably
24782 + * ring buffer already full */
24783 + /* FIXME: this causes a deadlock situation (endless
24784 + * loop) in case the current descriptor remains busy,
24785 + * so handle it a bit better in the future!! */
24786 + printk("acx: BUG: tx_head->Ctl8=0x%02X, (0x%02X & "
24787 + "0x"DESC_CTL_DONE_STR") != 0x"DESC_CTL_HOSTOWN_STR
24788 + ": failed to find free tx descr\n",
24795 + acxlog(L_BUFT, "tx: got desc %u, %u remain\n",
24796 + priv->tx_head, priv->tx_free);
24799 + * This comment is probably not entirely correct, needs further discussion
24800 + * (restored commented-out code below to fix Tx ring buffer overflow,
24801 + * since it's much better to have a slightly less efficiently used ring
24802 + * buffer rather than one which easily overflows):
24804 + * This doesn't do anything other than limit our maximum number of
24805 + * buffers used at a single time (we might as well just declare
24806 + * TX_STOP_QUEUE less descriptors when we open up.) We should just let it
24807 + * slide here, and back off TX_STOP_QUEUE in acx_l_clean_tx_desc, when given the
24808 + * opportunity to let the queue start back up.
24810 + if (priv->tx_free < TX_STOP_QUEUE) {
24811 + acxlog(L_BUF, "stop queue (%u tx desc left)\n",
24813 + acx_stop_queue(priv->netdev, NULL);
24816 + /* returning current descriptor, so advance to next free one */
24817 + priv->tx_head = (priv->tx_head + 1) % TX_CNT;
24821 + return (tx_t*)txdesc;
24825 +/***********************************************************************
24828 +acxpci_l_get_txbuf(wlandevice_t *priv, tx_t* tx_opaque)
24830 + return acx_get_txhostdesc(priv, (txdesc_t*)tx_opaque)->data;
24834 +/***********************************************************************
24835 +** acxpci_l_tx_data
24837 +** Can be called from IRQ (rx -> (AP bridging or mgmt response) -> tx).
24838 +** Can be called from acx_i_start_xmit (data frames from net core).
24841 +acxpci_l_tx_data(wlandevice_t *priv, tx_t* tx_opaque, int len)
24843 + txdesc_t *txdesc = (txdesc_t*)tx_opaque;
24844 + txhostdesc_t *hostdesc1, *hostdesc2;
24846 + u8 Ctl_8, Ctl2_8;
24850 + /* fw doesn't tx such packets anyhow */
24851 + if (len < WLAN_HDR_A3_LEN)
24854 + hostdesc1 = acx_get_txhostdesc(priv, txdesc);
24855 + hostdesc2 = hostdesc1 + 1;
24857 + /* modify flag status in separate variable to be able to write it back
24858 + * in one big swoop later (also in order to have less device memory
24860 + Ctl_8 = txdesc->Ctl_8;
24861 + Ctl2_8 = txdesc->Ctl2_8;
24863 + /* DON'T simply set Ctl field to 0 here globally,
24864 + * it needs to maintain a consistent flag status (those are state flags!!),
24865 + * otherwise it may lead to severe disruption. Only set or reset particular
24866 + * flags at the exact moment this is needed...
24867 + * FIXME: what about Ctl2? Equally problematic? */
24869 + /* let chip do RTS/CTS handshaking before sending
24870 + * in case packet size exceeds threshold */
24871 + if (len > priv->rts_threshold)
24872 + SET_BIT(Ctl2_8, DESC_CTL2_RTS);
24874 + CLEAR_BIT(Ctl2_8, DESC_CTL2_RTS);
24877 + if (priv->wep_enabled)
24878 + SET_BIT(Ctl2_8, DESC_CTL2_WEP);
24880 + CLEAR_BIT(Ctl2_8, DESC_CTL2_WEP);
24883 + switch (priv->mode) {
24884 + case ACX_MODE_0_ADHOC:
24885 + case ACX_MODE_3_AP:
24886 + clt = acx_l_sta_list_get(priv, ((wlan_hdr_t*)hostdesc1->data)->a1);
24888 + case ACX_MODE_2_STA:
24889 + clt = priv->ap_client;
24892 +/* testing was done on acx111: */
24893 + case ACX_MODE_MONITOR:
24894 + SET_BIT(Ctl2_8, 0
24895 +/* sends CTS to self before packet */
24896 + + DESC_CTL2_SEQ /* don't increase sequence field */
24897 +/* not working (looks like good fcs is still added) */
24898 + + DESC_CTL2_FCS /* don't add the FCS */
24900 + + DESC_CTL2_MORE_FRAG
24902 + + DESC_CTL2_RETRY /* don't increase retry field */
24904 + + DESC_CTL2_POWER /* don't increase power mgmt. field */
24906 + + DESC_CTL2_WEP /* encrypt this frame */
24908 + + DESC_CTL2_DUR /* don't increase duration field */
24910 + /* fallthrough */
24912 + default: /* ACX_MODE_OFF, ACX_MODE_MONITOR */
24917 + if (unlikely(clt && !clt->rate_cur)) {
24918 + printk("acx: driver bug! bad ratemask\n");
24922 + /* used in tx cleanup routine for auto rate and accounting: */
24923 + acx_put_txc(priv, txdesc, clt);
24925 + txdesc->total_length = cpu_to_le16(len);
24926 + hostdesc2->length = cpu_to_le16(len - WLAN_HDR_A3_LEN);
24927 + if (IS_ACX111(priv)) {
24928 + u16 rate_cur = clt ? clt->rate_cur : priv->rate_bcast;
24929 + /* note that if !txdesc->do_auto, txrate->cur
24930 + ** has only one nonzero bit */
24931 + txdesc->u.r2.rate111 = cpu_to_le16(
24933 + /* WARNING: I was never able to make it work with prism54 AP.
24934 + ** It was falling down to 1Mbit where shortpre is not applicable,
24935 + ** and not working at all at "5,11 basic rates only" setting.
24936 + ** I even didn't see tx packets in radio packet capture.
24937 + ** Disabled for now --vda */
24938 + /*| ((clt->shortpre && clt->cur!=RATE111_1) ? RATE111_SHORTPRE : 0) */
24940 +#ifdef TODO_FIGURE_OUT_WHEN_TO_SET_THIS
24941 + /* should add this to rate111 above as necessary */
24942 + | (clt->pbcc511 ? RATE111_PBCC511 : 0)
24944 + hostdesc1->length = cpu_to_le16(len);
24945 + } else { /* ACX100 */
24946 + u8 rate_100 = clt ? clt->rate_100 : priv->rate_bcast100;
24947 + txdesc->u.r1.rate = rate_100;
24948 +#ifdef TODO_FIGURE_OUT_WHEN_TO_SET_THIS
24949 + if (clt->pbcc511) {
24950 + if (n == RATE100_5 || n == RATE100_11)
24951 + n |= RATE100_PBCC511;
24954 + if (clt->shortpre && (clt->cur != RATE111_1))
24955 + SET_BIT(Ctl_8, DESC_CTL_SHORT_PREAMBLE); /* set Short Preamble */
24957 + /* set autodma and reclaim and 1st mpdu */
24958 + SET_BIT(Ctl_8, DESC_CTL_AUTODMA | DESC_CTL_RECLAIM | DESC_CTL_FIRSTFRAG);
24959 + hostdesc1->length = cpu_to_le16(WLAN_HDR_A3_LEN);
24961 + /* don't need to clean ack/rts statistics here, already
24962 + * done on descr cleanup */
24964 + /* clears Ctl DESC_CTL_HOSTOWN bit, thus telling that the descriptors
24965 + * are now owned by the acx100; do this as LAST operation */
24966 + CLEAR_BIT(Ctl_8, DESC_CTL_HOSTOWN);
24967 + /* flush writes before we release hostdesc to the adapter here */
24969 + CLEAR_BIT(hostdesc1->Ctl_16, cpu_to_le16(DESC_CTL_HOSTOWN));
24970 + CLEAR_BIT(hostdesc2->Ctl_16, cpu_to_le16(DESC_CTL_HOSTOWN));
24972 + /* write back modified flags */
24973 + txdesc->Ctl2_8 = Ctl2_8;
24974 + txdesc->Ctl_8 = Ctl_8;
24976 + /* unused: txdesc->tx_time = cpu_to_le32(jiffies); */
24977 +//TODO: should it be a mmiowb() instead? we are protecting against race with write[bwl]()
24978 + /* flush writes before we tell the adapter that it's its turn now */
24980 + acx_write_reg16(priv, IO_ACX_INT_TRIG, INT_TRIG_TXPRC);
24981 + acx_write_flush(priv);
24983 + /* log the packet content AFTER sending it,
24984 + * in order to not delay sending any further than absolutely needed
24985 + * Do separate logs for acx100/111 to have human-readable rates */
24986 + if (unlikely(acx_debug & (L_XFER|L_DATA))) {
24987 + u16 fc = ((wlan_hdr_t*)hostdesc1->data)->fc;
24988 + if (IS_ACX111(priv))
24989 + printk("tx: pkt (%s): len %d "
24990 + "rate %04X%s status %u\n",
24991 + acx_get_packet_type_string(le16_to_cpu(fc)), len,
24992 + le16_to_cpu(txdesc->u.r2.rate111),
24993 + (le16_to_cpu(txdesc->u.r2.rate111) & RATE111_SHORTPRE) ? "(SPr)" : "",
24996 + printk("tx: pkt (%s): len %d rate %03u%s status %u\n",
24997 + acx_get_packet_type_string(fc), len,
24998 + txdesc->u.r1.rate,
24999 + (Ctl_8 & DESC_CTL_SHORT_PREAMBLE) ? "(SPr)" : "",
25002 + if (acx_debug & L_DATA) {
25003 + printk("tx: 802.11 [%d]: ", len);
25004 + acx_dump_bytes(hostdesc1->data, len);
25012 +/***********************************************************************
25015 +acx_l_handle_tx_error(wlandevice_t *priv, u8 error, unsigned int finger)
25017 + const char *err = "unknown error";
25019 + /* hmm, should we handle this as a mask
25020 + * of *several* bits?
25021 + * For now I think only caring about
25022 + * individual bits is ok... */
25025 + err = "no Tx due to error in other fragment";
25026 + priv->wstats.discard.fragment++;
25029 + err = "Tx aborted";
25030 + priv->stats.tx_aborted_errors++;
25033 + err = "Tx desc wrong parameters";
25034 + priv->wstats.discard.misc++;
25037 + err = "WEP key not found";
25038 + priv->wstats.discard.misc++;
25041 + err = "MSDU lifetime timeout? - try changing "
25042 + "'iwconfig retry lifetime XXX'";
25043 + priv->wstats.discard.misc++;
25046 + err = "excessive Tx retries due to either distance "
25047 + "too high or unable to Tx or Tx frame error - "
25048 + "try changing 'iwconfig txpower XXX' or "
25049 + "'sens'itivity or 'retry'";
25050 + priv->wstats.discard.retries++;
25051 + /* FIXME: set (GETSET_TX|GETSET_RX) here
25052 + * (this seems to recalib radio on ACX100)
25053 + * after some more jiffies passed??
25054 + * But OTOH Tx error 0x20 also seems to occur on
25055 + * overheating, so I'm not sure whether we
25056 + * actually want that, since people maybe won't notice
25057 + * then that their hardware is slowly getting
25059 + * Or is it still a safe long distance from utter
25060 + * radio non-functionality despite many radio
25062 + * to final destructive overheating of the hardware?
25063 + * In this case we really should do recalib here...
25064 + * I guess the only way to find out is to do a
25065 + * potentially fatal self-experiment :-\
25066 + * Or maybe only recalib in case we're using Tx
25067 + * rate auto (on errors switching to lower speed
25068 + * --> less heat?) or 802.11 power save mode? */
25070 + /* ok, just do it.
25071 + * ENABLE_TX|ENABLE_RX helps, so even do
25072 + * DISABLE_TX and DISABLE_RX in order to perhaps
25073 + * have more impact. */
25074 + if (++priv->retry_errors_msg_ratelimit % 4 == 0) {
25075 + if (priv->retry_errors_msg_ratelimit <= 20)
25076 + printk("%s: several excessive Tx "
25077 + "retry errors occurred, attempting "
25078 + "to recalibrate radio. Radio "
25079 + "drift might be caused by increasing "
25080 + "card temperature, please check the card "
25081 + "before it's too late!\n",
25082 + priv->netdev->name);
25083 + if (priv->retry_errors_msg_ratelimit == 20)
25084 + printk("disabling above "
25085 + "notification message\n");
25087 + acx_schedule_after_interrupt_task(priv, ACX_AFTER_IRQ_CMD_RADIO_RECALIB);
25091 + err = "Tx buffer overflow";
25092 + priv->stats.tx_fifo_errors++;
25095 + err = "DMA error";
25096 + priv->wstats.discard.misc++;
25099 + priv->stats.tx_errors++;
25100 + if (priv->stats.tx_errors <= 20)
25101 + printk("%s: tx error 0x%02X, buf %02u! (%s)\n",
25102 + priv->netdev->name, error, finger, err);
25104 + printk("%s: tx error 0x%02X, buf %02u!\n",
25105 + priv->netdev->name, error, finger);
25109 +/***********************************************************************
25111 +/* Theory of operation:
25112 +** client->rate_cap is a bitmask of rates client is capable of.
25113 +** client->rate_cfg is a bitmask of allowed (configured) rates.
25114 +** It is set as a result of iwconfig rate N [auto]
25115 +** or iwpriv set_rates "N,N,N N,N,N" commands.
25116 +** It can be fixed (e.g. 0x0080 == 18Mbit only),
25117 +** auto (0x00ff == 18Mbit or any lower value),
25118 +** and code handles any bitmask (0x1081 == try 54Mbit,18Mbit,1Mbit _only_).
25120 +** client->rate_cur is a value for rate111 field in tx descriptor.
25121 +** It is always set to txrate_cfg sans zero or more most significant
25122 +** bits. This routine handles selection of new rate_cur value depending on
25123 +** outcome of last tx event.
25125 +** client->rate_100 is a precalculated rate value for acx100
25126 +** (we can do without it, but will need to calculate it on each tx).
25128 +** You cannot configure mixed usage of 5.5 and/or 11Mbit rate
25129 +** with PBCC and CCK modulation. Either both at CCK or both at PBCC.
25130 +** In theory you can implement it, but so far it is considered not worth doing.
25132 +** 22Mbit, of course, is PBCC always. */
25134 +/* maps acx100 tx descr rate field to acx111 one */
25136 +rate100to111(u8 r)
25139 + case RATE100_1: return RATE111_1;
25140 + case RATE100_2: return RATE111_2;
25142 + case (RATE100_5 | RATE100_PBCC511): return RATE111_5;
25144 + case (RATE100_11 | RATE100_PBCC511): return RATE111_11;
25145 + case RATE100_22: return RATE111_22;
25147 + printk("acx: unexpected acx100 txrate: %u! "
25148 + "Please report\n", r);
25149 + return RATE111_2;
25155 +acx_l_handle_txrate_auto(wlandevice_t *priv, struct client *txc,
25156 + unsigned int idx, u8 rate100, u16 rate111, u8 error)
25159 + u16 cur = txc->rate_cur;
25160 + int slower_rate_was_used;
25162 + /* FIXME: need to implement some kind of rate success memory
25163 + * which stores the success percentage per rate, to be taken
25164 + * into account when considering allowing a new rate, since it
25165 + * doesn't really help to stupidly count fallback/stepup,
25166 + * since one invalid rate will spoil the party anyway
25167 + * (such as 22M in case of 11M-only peers) */
25169 + /* vda: hmm. current code will do this:
25170 + ** 1. send packets at 11 Mbit, stepup++
25171 + ** 2. will try to send at 22Mbit. hardware will see no ACK,
25172 + ** retries at 11Mbit, success. code notes that used rate
25173 + ** is lower. stepup = 0, fallback++
25174 + ** 3. repeat step 2 fallback_count times. Fall back to
25175 + ** 11Mbit. go to step 1.
25176 + ** If stepup_count is large (say, 16) and fallback_count
25177 + ** is small (3), this wouldn't be too bad wrt throughput */
25179 + /* do some preparations, i.e. calculate the one rate that was
25180 + * used to send this packet */
25181 + if (IS_ACX111(priv)) {
25182 + sent_rate = 1 << highest_bit(rate111 & RATE111_ALL);
25184 + sent_rate = rate100to111(rate100);
25186 + /* sent_rate has only one bit set now, corresponding to tx rate
25187 + * which was used by hardware to tx this particular packet */
25189 + /* now do the actual auto rate management */
25190 + acxlog(L_DEBUG, "tx: %sclient=%p/"MACSTR" used=%04X cur=%04X cfg=%04X "
25191 + "__=%u/%u ^^=%u/%u\n",
25192 + (txc->ignore_count > 0) ? "[IGN] " : "",
25193 + txc, MAC(txc->address), sent_rate, cur, txc->rate_cfg,
25194 + txc->fallback_count, priv->fallback_threshold,
25195 + txc->stepup_count, priv->stepup_threshold
25198 + /* we need to ignore old packets already in the tx queue since
25199 + * they use older rate bytes configured before our last rate change,
25200 + * otherwise our mechanism will get confused by interpreting old data.
25201 + * Do it here only, in order to have the logging above */
25202 + if (txc->ignore_count) {
25203 + txc->ignore_count--;
25207 + /* true only if the only nonzero bit in sent_rate is
25208 + ** less significant than highest nonzero bit in cur */
25209 + slower_rate_was_used = ( cur > ((sent_rate<<1)-1) );
25211 + if (slower_rate_was_used || (error & 0x30)) {
25212 + txc->stepup_count = 0;
25213 + if (++txc->fallback_count <= priv->fallback_threshold)
25215 + txc->fallback_count = 0;
25217 + /* clear highest 1 bit in cur */
25218 + sent_rate = RATE111_54;
25219 + while (!(cur & sent_rate)) sent_rate >>= 1;
25220 + CLEAR_BIT(cur, sent_rate);
25222 + if (cur) { /* we can't disable all rates! */
25223 + acxlog(L_XFER, "tx: falling back to ratemask %04X\n", cur);
25224 + txc->rate_cur = cur;
25225 + txc->ignore_count = TX_CNT - priv->tx_free;
25227 + } else if (!slower_rate_was_used) {
25228 + txc->fallback_count = 0;
25229 + if (++txc->stepup_count <= priv->stepup_threshold)
25231 + txc->stepup_count = 0;
25233 + /* sanitize. Sort of not needed, but I dont trust hw that much...
25234 + ** what if it can report bogus tx rates sometimes? */
25235 + while (!(cur & sent_rate)) sent_rate >>= 1;
25236 + /* try to find a higher sent_rate that isn't yet in our
25237 + * current set, but is an allowed cfg */
25240 + if (sent_rate > txc->rate_cfg)
25241 + /* no higher rates allowed by config */
25243 + if (!(cur & sent_rate) && (txc->rate_cfg & sent_rate))
25246 + /* not found, try higher one */
25248 + SET_BIT(cur, sent_rate);
25249 + acxlog(L_XFER, "tx: stepping up to ratemask %04X\n", cur);
25250 + txc->rate_cur = cur;
25251 + /* FIXME: totally bogus - we could be sending to many peers at once... */
25252 + txc->ignore_count = TX_CNT - priv->tx_free;
25255 + /* calculate acx100 style rate byte if needed */
25256 + if (IS_ACX100(priv)) {
25257 + txc->rate_100 = bitpos2rate100[highest_bit(cur)];
25262 +/*----------------------------------------------------------------
25263 +* acx_l_log_txbuffer
25264 +*----------------------------------------------------------------*/
25266 +static inline void acx_l_log_txbuffer(const wlandevice_t *priv) {}
25269 +acx_l_log_txbuffer(wlandevice_t *priv)
25271 + txdesc_t *txdesc;
25274 + /* no FN_ENTER here, we don't want that */
25275 + /* no locks here, since it's entirely non-critical code */
25276 + txdesc = priv->txdesc_start;
25277 + if (!txdesc) return;
25278 + for (i = 0; i < TX_CNT; i++) {
25279 + if ((txdesc->Ctl_8 & DESC_CTL_DONE) == DESC_CTL_DONE)
25280 + printk("tx: buf %d done\n", i);
25281 + txdesc = move_txdesc(priv, txdesc, 1);
25287 +/*----------------------------------------------------------------
25288 +* acx_l_clean_tx_desc
25290 +* This function resets the txdescs' status when the ACX100
25291 +* signals the TX done IRQ (txdescs have been processed), starting with
25292 +* the pool index of the descriptor which we would use next,
25293 +* in order to make sure that we can be as fast as possible
25294 +* in filling new txdescs.
25295 +* Oops, now we have our own index, so everytime we get called we know
25296 +* where the next packet to be cleaned is.
25297 +* Hmm, still need to loop through the whole ring buffer now,
25298 +* since we lost sync for some reason when ping flooding or so...
25299 +* (somehow we don't get the IRQ for acx_l_clean_tx_desc any more when
25300 +* too many packets are being sent!)
25301 +* FIXME: currently we only process one packet, but this gets out of
25302 +* sync for some reason when ping flooding, so we need to loop,
25303 +* but the previous smart loop implementation causes the ping latency
25304 +* to rise dramatically (~3000 ms), at least on CardBus PheeNet WL-0022.
25305 +* Dunno what to do :-\
25306 +*----------------------------------------------------------------*/
25308 +acx_l_clean_tx_desc(wlandevice_t *priv)
25310 + txdesc_t *txdesc;
25311 + struct client *txc;
25316 + u8 error, ack_failures, rts_failures, rts_ok, r100;
25320 + if (unlikely(acx_debug & L_DEBUG))
25321 + acx_l_log_txbuffer(priv);
25323 + acxlog(L_BUFT, "tx: cleaning up bufs from %u\n", priv->tx_tail);
25325 + finger = priv->tx_tail;
25327 + to_process = TX_CNT;
25329 + txdesc = get_txdesc(priv, finger);
25331 + /* abort if txdesc is not marked as "Tx finished" and "owned" */
25332 + if ((txdesc->Ctl_8 & DESC_CTL_DONE) != DESC_CTL_DONE) {
25333 + /* we do need to have at least one cleaned,
25334 + * otherwise we wouldn't get called in the first place
25340 + /* remember descr values... */
25341 + error = txdesc->error;
25342 + ack_failures = txdesc->ack_failures;
25343 + rts_failures = txdesc->rts_failures;
25344 + rts_ok = txdesc->rts_ok;
25345 + r100 = txdesc->u.r1.rate;
25346 + r111 = txdesc->u.r2.rate111;
25348 +#if WIRELESS_EXT > 13 /* wireless_send_event() and IWEVTXDROP are WE13 */
25349 + /* need to check for certain error conditions before we
25350 + * clean the descriptor: we still need valid descr data here */
25351 + if (unlikely(0x30 & error)) {
25352 + /* only send IWEVTXDROP in case of retry or lifetime exceeded;
25353 + * all other errors mean we screwed up locally */
25354 + union iwreq_data wrqu;
25356 + txhostdesc_t *hostdesc;
25358 + hostdesc = acx_get_txhostdesc(priv, txdesc);
25359 + hdr = (wlan_hdr_t *)hostdesc->data;
25360 + MAC_COPY(wrqu.addr.sa_data, hdr->a1);
25361 + wireless_send_event(priv->netdev, IWEVTXDROP, &wrqu, NULL);
25364 + /* ...and free the descr */
25365 + txdesc->error = 0;
25366 + txdesc->ack_failures = 0;
25367 + txdesc->rts_failures = 0;
25368 + txdesc->rts_ok = 0;
25369 + /* signal host owning it LAST, since ACX already knows that this
25370 + * descriptor is finished since it set Ctl_8 accordingly:
25371 + * if _OWN is set at the beginning instead, our own get_tx
25372 + * might choose a Tx desc that isn't fully cleared
25373 + * (in case of bad locking). */
25374 + txdesc->Ctl_8 = DESC_CTL_HOSTOWN;
25378 + if ((priv->tx_free >= TX_START_QUEUE)
25379 + && (priv->status == ACX_STATUS_4_ASSOCIATED)
25380 + && (acx_queue_stopped(priv->netdev))
25382 + acxlog(L_BUF, "tx: wake queue (avail. Tx desc %u)\n",
25384 + acx_wake_queue(priv->netdev, NULL);
25387 + /* do error checking, rate handling and logging
25388 + * AFTER having done the work, it's faster */
25390 + /* do rate handling */
25391 + txc = acx_get_txc(priv, txdesc);
25392 + if (txc && priv->rate_auto) {
25393 + acx_l_handle_txrate_auto(priv, txc, finger, r100, r111, error);
25396 + if (unlikely(error))
25397 + acx_l_handle_tx_error(priv, error, finger);
25399 + if (IS_ACX111(priv))
25400 + acxlog(L_BUFT, "tx: cleaned %u: !ACK=%u !RTS=%u RTS=%u r111=%04X\n",
25401 + finger, ack_failures, rts_failures, rts_ok, r111);
25403 + acxlog(L_BUFT, "tx: cleaned %u: !ACK=%u !RTS=%u RTS=%u rate=%u\n",
25404 + finger, ack_failures, rts_failures, rts_ok, r100);
25406 + /* update pointer for descr to be cleaned next */
25407 + finger = (finger + 1) % TX_CNT;
25408 + } while (--to_process);
25410 + /* remember last position */
25411 + priv->tx_tail = finger;
25413 + FN_EXIT1(num_cleaned);
25414 + return num_cleaned;
25417 +/* clean *all* Tx descriptors, and regardless of their previous state.
25418 + * Used for brute-force reset handling. */
25420 +acx_l_clean_tx_desc_emergency(wlandevice_t *priv)
25422 + txdesc_t *txdesc;
25427 + for (i = 0; i < TX_CNT; i++) {
25428 + txdesc = get_txdesc(priv, i);
25431 + txdesc->ack_failures = 0;
25432 + txdesc->rts_failures = 0;
25433 + txdesc->rts_ok = 0;
25434 + txdesc->error = 0;
25435 + txdesc->Ctl_8 = DESC_CTL_HOSTOWN;
25438 + priv->tx_free = TX_CNT;
25444 +/*----------------------------------------------------------------
25445 +* acx_l_log_rxbuffer
25447 +* Called from IRQ context only
25448 +*----------------------------------------------------------------*/
25450 +static inline void acx_l_log_rxbuffer(const wlandevice_t *priv) {}
25453 +acx_l_log_rxbuffer(const wlandevice_t *priv)
25455 + const struct rxhostdesc *rxhostdesc;
25458 + /* no FN_ENTER here, we don't want that */
25460 + rxhostdesc = priv->rxhostdesc_start;
25461 + if (!rxhostdesc) return;
25462 + for (i = 0; i < RX_CNT; i++) {
25463 + if ((rxhostdesc->Ctl_16 & cpu_to_le16(DESC_CTL_HOSTOWN))
25464 + && (rxhostdesc->Status & cpu_to_le32(DESC_STATUS_FULL)))
25465 + printk("rx: buf %d full\n", i);
25472 +/***************************************************************
25473 +** acx_l_process_rx_desc
25475 +** Called directly and only from the IRQ handler
25478 +acx_l_process_rx_desc(wlandevice_t *priv)
25480 + rxhostdesc_t *hostdesc;
25481 + /* unsigned int curr_idx; */
25482 + unsigned int count = 0;
25486 + if (unlikely(acx_debug & L_BUFR)) {
25487 + acx_l_log_rxbuffer(priv);
25490 + /* First, have a loop to determine the first descriptor that's
25491 + * full, just in case there's a mismatch between our current
25492 + * rx_tail and the full descriptor we're supposed to handle. */
25494 + /* curr_idx = priv->rx_tail; */
25495 + hostdesc = &priv->rxhostdesc_start[priv->rx_tail];
25496 + priv->rx_tail = (priv->rx_tail + 1) % RX_CNT;
25497 + if ((hostdesc->Ctl_16 & cpu_to_le16(DESC_CTL_HOSTOWN))
25498 + && (hostdesc->Status & cpu_to_le32(DESC_STATUS_FULL))) {
25503 + if (unlikely(count > RX_CNT)) {
25504 + /* hmm, no luck: all descriptors empty, bail out */
25509 + /* now process descriptors, starting with the first we figured out */
25511 + acxlog(L_BUFR, "rx: tail=%u Ctl_16=%04X Status=%08X\n",
25512 + priv->rx_tail, hostdesc->Ctl_16, hostdesc->Status);
25514 + acx_l_process_rxbuf(priv, hostdesc->data);
25516 + hostdesc->Status = 0;
25517 + /* flush all writes before adapter sees CTL_HOSTOWN change */
25519 + /* Host no longer owns this, needs to be LAST */
25520 + CLEAR_BIT(hostdesc->Ctl_16, cpu_to_le16(DESC_CTL_HOSTOWN));
25522 + /* ok, descriptor is handled, now check the next descriptor */
25523 + /* curr_idx = priv->rx_tail; */
25524 + hostdesc = &priv->rxhostdesc_start[priv->rx_tail];
25526 + /* if next descriptor is empty, then bail out */
25527 + /* FIXME: is this check really entirely correct?? */
25529 +//FIXME: inconsistent with check in prev while() loop
25530 + if (!(hostdesc->Ctl & cpu_to_le16(DESC_CTL_HOSTOWN))
25531 + && !(hostdesc->Status & cpu_to_le32(DESC_STATUS_FULL))) */
25532 + if (!(hostdesc->Status & cpu_to_le32(DESC_STATUS_FULL)))
25535 + priv->rx_tail = (priv->rx_tail + 1) % RX_CNT;
25542 +/*----------------------------------------------------------------
25543 +* acx_s_create_tx_host_desc_queue
25544 +*----------------------------------------------------------------*/
25545 +static inline void*
25546 +acx_alloc_coherent(struct pci_dev *hwdev, size_t size,
25547 + dma_addr_t *dma_handle, int flag)
25549 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 53)
25550 + return dma_alloc_coherent(hwdev == NULL ? NULL : &hwdev->dev,
25551 + size, dma_handle, flag);
25553 +#warning Using old PCI-specific DMA allocation, may fail with out-of-mem!
25554 +#warning Upgrade kernel if it does...
25555 + return pci_alloc_consistent(hwdev, size, dma_handle);
25560 +allocate(wlandevice_t *priv, size_t size, dma_addr_t *phy, const char *msg)
25562 + void *ptr = acx_alloc_coherent(priv->pdev, size, phy, GFP_KERNEL);
25564 + acxlog(L_DEBUG, "%s sz=%d adr=0x%p phy=0x%08llx\n",
25565 + msg, (int)size, ptr, (unsigned long long)*phy);
25566 + memset(ptr, 0, size);
25569 + printk(KERN_ERR "acx: %s allocation FAILED (%d bytes)\n",
25575 +acx_s_create_tx_host_desc_queue(wlandevice_t *priv)
25577 + txhostdesc_t *hostdesc;
25579 + dma_addr_t hostdesc_phy;
25580 + dma_addr_t txbuf_phy;
25585 + /* allocate TX buffer */
25586 + priv->txbuf_area_size = TX_CNT * WLAN_A4FR_MAXLEN_WEP_FCS;
25587 + priv->txbuf_start = allocate(priv, priv->txbuf_area_size,
25588 + &priv->txbuf_startphy, "txbuf_start");
25589 + if (!priv->txbuf_start)
25592 + /* allocate the TX host descriptor queue pool */
25593 + priv->txhostdesc_area_size = TX_CNT * 2*sizeof(txhostdesc_t);
25594 + priv->txhostdesc_start = allocate(priv, priv->txhostdesc_area_size,
25595 + &priv->txhostdesc_startphy, "txhostdesc_start");
25596 + if (!priv->txhostdesc_start)
25598 + /* check for proper alignment of TX host descriptor pool */
25599 + if ((long) priv->txhostdesc_start & 3) {
25600 + printk("acx: driver bug: dma alloc returns unaligned address\n");
25604 +/* Each tx frame buffer is accessed by hardware via
25605 +** txdesc -> txhostdesc(s) -> framebuffer(s)
25606 +** We use only one txhostdesc per txdesc, but it looks like
25607 +** acx111 is buggy: it accesses second txhostdesc
25608 +** (via hostdesc.desc_phy_next field) even if
25609 +** txdesc->length == hostdesc->length and thus
25610 +** entire packet was placed into first txhostdesc.
25611 +** Due to this bug acx111 hangs unless second txhostdesc
25612 +** has hostdesc.length = 3 (or larger)
25613 +** Storing NULL into hostdesc.desc_phy_next
25614 +** doesn't seem to help.
25616 +/* It is not known whether we need to have 'extra' second
25617 +** txhostdescs for acx100. Maybe it is acx111-only bug.
25619 + hostdesc = priv->txhostdesc_start;
25620 + hostdesc_phy = priv->txhostdesc_startphy;
25621 + txbuf = priv->txbuf_start;
25622 + txbuf_phy = priv->txbuf_startphy;
25625 +/* Works for xterasys xn2522g, does not for WG311v2 !!? */
25626 + for (i = 0; i < TX_CNT*2; i++) {
25627 + hostdesc_phy += sizeof(txhostdesc_t);
25629 + hostdesc->data_phy = cpu2acx(txbuf_phy);
25630 + /* hostdesc->data_offset = ... */
25631 + /* hostdesc->reserved = ... */
25632 + hostdesc->Ctl_16 = cpu_to_le16(DESC_CTL_HOSTOWN);
25633 + /* hostdesc->length = ... */
25634 + hostdesc->desc_phy_next = cpu2acx(hostdesc_phy);
25635 + hostdesc->pNext = ptr2acx(NULL);
25636 + /* hostdesc->Status = ... */
25637 + /* below: non-hardware fields */
25638 + hostdesc->data = txbuf;
25640 + txbuf += WLAN_A4FR_MAXLEN_WEP_FCS;
25641 + txbuf_phy += WLAN_A4FR_MAXLEN_WEP_FCS;
25643 + /* hostdesc->data_phy = ... */
25644 + /* hostdesc->data_offset = ... */
25645 + /* hostdesc->reserved = ... */
25646 + /* hostdesc->Ctl_16 = ... */
25647 + hostdesc->length = 3; /* bug workaround */
25648 + /* hostdesc->desc_phy_next = ... */
25649 + /* hostdesc->pNext = ... */
25650 + /* hostdesc->Status = ... */
25651 + /* below: non-hardware fields */
25652 + /* hostdesc->data = ... */
25657 + for (i = 0; i < TX_CNT*2; i++) {
25658 + hostdesc_phy += sizeof(txhostdesc_t);
25660 + hostdesc->data_phy = cpu2acx(txbuf_phy);
25661 + /* done by memset(0): hostdesc->data_offset = 0; */
25662 + /* hostdesc->reserved = ... */
25663 + hostdesc->Ctl_16 = cpu_to_le16(DESC_CTL_HOSTOWN);
25664 + /* hostdesc->length = ... */
25665 + hostdesc->desc_phy_next = cpu2acx(hostdesc_phy);
25666 + /* done by memset(0): hostdesc->pNext = ptr2acx(NULL); */
25667 + /* hostdesc->Status = ... */
25668 + /* below: non-hardware fields */
25669 + hostdesc->data = txbuf;
25671 + txbuf += WLAN_HDR_A3_LEN;
25672 + txbuf_phy += WLAN_HDR_A3_LEN;
25674 + hostdesc->data_phy = cpu2acx(txbuf_phy);
25675 + /* done by memset(0): hostdesc->data_offset = 0; */
25676 + /* hostdesc->reserved = ... */
25677 + hostdesc->Ctl_16 = cpu_to_le16(DESC_CTL_HOSTOWN);
25678 + /* hostdesc->length = ...; */
25679 + hostdesc->desc_phy_next = cpu2acx(hostdesc_phy);
25680 + /* done by memset(0): hostdesc->pNext = ptr2acx(NULL); */
25681 + /* hostdesc->Status = ... */
25682 + /* below: non-hardware fields */
25683 + hostdesc->data = txbuf;
25685 + txbuf += WLAN_A4FR_MAXLEN_WEP_FCS - WLAN_HDR_A3_LEN;
25686 + txbuf_phy += WLAN_A4FR_MAXLEN_WEP_FCS - WLAN_HDR_A3_LEN;
25691 + hostdesc->desc_phy_next = cpu2acx(priv->txhostdesc_startphy);
25696 + printk("acx: create_tx_host_desc_queue FAILED\n");
25697 + /* dealloc will be done by free function on error case */
25698 + FN_EXIT1(NOT_OK);
25703 +/***************************************************************
25704 +** acx_s_create_rx_host_desc_queue
25706 +/* the whole size of a data buffer (header plus data body)
25707 + * plus 32 bytes safety offset at the end */
25708 +#define RX_BUFFER_SIZE (sizeof(rxbuffer_t) + 32)
25711 +acx_s_create_rx_host_desc_queue(wlandevice_t *priv)
25713 + rxhostdesc_t *hostdesc;
25714 + rxbuffer_t *rxbuf;
25715 + dma_addr_t hostdesc_phy;
25716 + dma_addr_t rxbuf_phy;
25721 + /* allocate the RX host descriptor queue pool */
25722 + priv->rxhostdesc_area_size = RX_CNT * sizeof(rxhostdesc_t);
25723 + priv->rxhostdesc_start = allocate(priv, priv->rxhostdesc_area_size,
25724 + &priv->rxhostdesc_startphy, "rxhostdesc_start");
25725 + if (!priv->rxhostdesc_start)
25727 + /* check for proper alignment of RX host descriptor pool */
25728 + if ((long) priv->rxhostdesc_start & 3) {
25729 + printk("acx: driver bug: dma alloc returns unaligned address\n");
25733 + /* allocate Rx buffer pool which will be used by the acx
25734 + * to store the whole content of the received frames in it */
25735 + priv->rxbuf_area_size = RX_CNT * RX_BUFFER_SIZE;
25736 + priv->rxbuf_start = allocate(priv, priv->rxbuf_area_size,
25737 + &priv->rxbuf_startphy, "rxbuf_start");
25738 + if (!priv->rxbuf_start)
25741 + rxbuf = priv->rxbuf_start;
25742 + rxbuf_phy = priv->rxbuf_startphy;
25743 + hostdesc = priv->rxhostdesc_start;
25744 + hostdesc_phy = priv->rxhostdesc_startphy;
25746 + /* don't make any popular C programming pointer arithmetic mistakes
25747 + * here, otherwise I'll kill you...
25748 + * (and don't dare asking me why I'm warning you about that...) */
25749 + for (i = 0; i < RX_CNT; i++) {
25750 + hostdesc->data = rxbuf;
25751 + hostdesc->data_phy = cpu2acx(rxbuf_phy);
25752 + hostdesc->length = cpu_to_le16(RX_BUFFER_SIZE);
25753 + CLEAR_BIT(hostdesc->Ctl_16, cpu_to_le16(DESC_CTL_HOSTOWN));
25755 + rxbuf_phy += sizeof(rxbuffer_t);
25756 + hostdesc_phy += sizeof(rxhostdesc_t);
25757 + hostdesc->desc_phy_next = cpu2acx(hostdesc_phy);
25761 + hostdesc->desc_phy_next = cpu2acx(priv->rxhostdesc_startphy);
25765 + printk("acx: create_rx_host_desc_queue FAILED\n");
25766 + /* dealloc will be done by free function on error case */
25767 + FN_EXIT1(NOT_OK);
25772 +/***************************************************************
25773 +** acx_s_create_hostdesc_queues
25776 +acx_s_create_hostdesc_queues(wlandevice_t *priv)
25779 + result = acx_s_create_tx_host_desc_queue(priv);
25780 + if (OK != result) return result;
25781 + result = acx_s_create_rx_host_desc_queue(priv);
25786 +/***************************************************************
25787 +** acx_create_tx_desc_queue
25790 +acx_create_tx_desc_queue(wlandevice_t *priv, u32 tx_queue_start)
25792 + txdesc_t *txdesc;
25793 + txhostdesc_t *hostdesc;
25794 + dma_addr_t hostmemptr;
25800 + priv->txdesc_size = sizeof(txdesc_t);
25802 + if (IS_ACX111(priv)) {
25803 + /* the acx111 txdesc is 4 bytes larger */
25804 + priv->txdesc_size = sizeof(txdesc_t) + 4;
25807 + priv->txdesc_start = (txdesc_t *) (priv->iobase2 + tx_queue_start);
25809 + acxlog(L_DEBUG, "priv->iobase2=%p\n"
25810 + "tx_queue_start=%08X\n"
25811 + "priv->txdesc_start=%p\n",
25814 + priv->txdesc_start);
25816 + priv->tx_free = TX_CNT;
25817 + /* done by memset: priv->tx_head = 0; */
25818 + /* done by memset: priv->tx_tail = 0; */
25819 + txdesc = priv->txdesc_start;
25820 + mem_offs = tx_queue_start;
25821 + hostmemptr = priv->txhostdesc_startphy;
25822 + hostdesc = priv->txhostdesc_start;
25824 + if (IS_ACX111(priv)) {
25825 + /* ACX111 has a preinitialized Tx buffer! */
25826 + /* loop over whole send pool */
25827 + /* FIXME: do we have to do the hostmemptr stuff here?? */
25828 + for (i = 0; i < TX_CNT; i++) {
25829 + txdesc->HostMemPtr = ptr2acx(hostmemptr);
25830 + txdesc->Ctl_8 = DESC_CTL_HOSTOWN;
25831 + /* reserve two (hdr desc and payload desc) */
25833 + hostmemptr += 2 * sizeof(txhostdesc_t);
25834 + txdesc = move_txdesc(priv, txdesc, 1);
25837 + /* ACX100 Tx buffer needs to be initialized by us */
25838 + /* clear whole send pool. sizeof is safe here (we are acx100) */
25839 + memset(priv->txdesc_start, 0, TX_CNT * sizeof(txdesc_t));
25841 + /* loop over whole send pool */
25842 + for (i = 0; i < TX_CNT; i++) {
25843 + acxlog(L_DEBUG, "configure card tx descriptor: 0x%p, "
25844 + "size: 0x%X\n", txdesc, priv->txdesc_size);
25846 + /* pointer to hostdesc memory */
25847 + /* FIXME: type-incorrect assignment, might cause trouble
25848 + * in some cases */
25849 + txdesc->HostMemPtr = ptr2acx(hostmemptr);
25850 + /* initialise ctl */
25851 + txdesc->Ctl_8 = DESC_CTL_INIT;
25852 + txdesc->Ctl2_8 = 0;
25853 + /* point to next txdesc */
25854 + txdesc->pNextDesc = cpu2acx(mem_offs + priv->txdesc_size);
25855 + /* reserve two (hdr desc and payload desc) */
25857 + hostmemptr += 2 * sizeof(txhostdesc_t);
25858 + /* go to the next one */
25859 + mem_offs += priv->txdesc_size;
25860 + /* ++ is safe here (we are acx100) */
25863 + /* go back to the last one */
25865 + /* and point to the first making it a ring buffer */
25866 + txdesc->pNextDesc = cpu2acx(tx_queue_start);
25872 +/***************************************************************
25873 +** acx_create_rx_desc_queue
25876 +acx_create_rx_desc_queue(wlandevice_t *priv, u32 rx_queue_start)
25878 + rxdesc_t *rxdesc;
25884 + /* done by memset: priv->rx_tail = 0; */
25886 + /* ACX111 doesn't need any further config: preconfigures itself.
25887 + * Simply print ring buffer for debugging */
25888 + if (IS_ACX111(priv)) {
25889 + /* rxdesc_start already set here */
25891 + priv->rxdesc_start = (rxdesc_t *) ((u8 *)priv->iobase2 + rx_queue_start);
25893 + rxdesc = priv->rxdesc_start;
25894 + for (i = 0; i < RX_CNT; i++) {
25895 + acxlog(L_DEBUG, "rx descriptor %d @ 0x%p\n", i, rxdesc);
25896 + rxdesc = priv->rxdesc_start = (rxdesc_t *)
25897 + (priv->iobase2 + acx2cpu(rxdesc->pNextDesc));
25900 + /* we didn't pre-calculate rxdesc_start in case of ACX100 */
25901 + /* rxdesc_start should be right AFTER Tx pool */
25902 + priv->rxdesc_start = (rxdesc_t *)
25903 + ((u8 *) priv->txdesc_start + (TX_CNT * sizeof(txdesc_t)));
25904 + /* NB: sizeof(txdesc_t) above is valid because we know
25905 + ** we are in if(acx100) block. Beware of cut-n-pasting elsewhere!
25906 + ** acx111's txdesc is larger! */
25908 + memset(priv->rxdesc_start, 0, RX_CNT * sizeof(rxdesc_t));
25910 + /* loop over whole receive pool */
25911 + rxdesc = priv->rxdesc_start;
25912 + mem_offs = rx_queue_start;
25913 + for (i = 0; i < RX_CNT; i++) {
25914 + acxlog(L_DEBUG, "rx descriptor @ 0x%p\n", rxdesc);
25915 + rxdesc->Ctl_8 = DESC_CTL_RECLAIM | DESC_CTL_AUTODMA;
25916 + /* point to next rxdesc */
25917 + rxdesc->pNextDesc = cpu2acx(mem_offs + sizeof(rxdesc_t));
25918 + /* go to the next one */
25919 + mem_offs += sizeof(rxdesc_t);
25922 + /* go to the last one */
25925 + /* and point to the first making it a ring buffer */
25926 + rxdesc->pNextDesc = cpu2acx(rx_queue_start);
25932 +/***************************************************************
25933 +** acx_create_desc_queues
25936 +acx_create_desc_queues(wlandevice_t *priv, u32 tx_queue_start, u32 rx_queue_start)
25938 + acx_create_tx_desc_queue(priv, tx_queue_start);
25939 + acx_create_rx_desc_queue(priv, rx_queue_start);
25943 +/***************************************************************
25944 +** acxpci_s_proc_diag_output
25947 +acxpci_s_proc_diag_output(char *p, wlandevice_t *priv)
25949 + const char *rtl, *thd, *ttl;
25950 + rxhostdesc_t *rxhostdesc;
25951 + txdesc_t *txdesc;
25956 + p += sprintf(p, "** Rx buf **\n");
25957 + rxhostdesc = priv->rxhostdesc_start;
25958 + if (rxhostdesc) for (i = 0; i < RX_CNT; i++) {
25959 + rtl = (i == priv->rx_tail) ? " [tail]" : "";
25960 + if ((rxhostdesc->Ctl_16 & cpu_to_le16(DESC_CTL_HOSTOWN))
25961 + && (rxhostdesc->Status & cpu_to_le32(DESC_STATUS_FULL)) )
25962 + p += sprintf(p, "%02u FULL%s\n", i, rtl);
25964 + p += sprintf(p, "%02u empty%s\n", i, rtl);
25967 + p += sprintf(p, "** Tx buf (free %d, Linux netqueue %s) **\n", priv->tx_free,
25968 + acx_queue_stopped(priv->netdev) ? "STOPPED" : "running");
25969 + txdesc = priv->txdesc_start;
25970 + if (txdesc) for (i = 0; i < TX_CNT; i++) {
25971 + thd = (i == priv->tx_head) ? " [head]" : "";
25972 + ttl = (i == priv->tx_tail) ? " [tail]" : "";
25973 + if (txdesc->Ctl_8 & DESC_CTL_ACXDONE)
25974 + p += sprintf(p, "%02u DONE (%02X)%s%s\n", i, txdesc->Ctl_8, thd, ttl);
25976 + if (!(txdesc->Ctl_8 & DESC_CTL_HOSTOWN))
25977 + p += sprintf(p, "%02u TxWait (%02X)%s%s\n", i, txdesc->Ctl_8, thd, ttl);
25979 + p += sprintf(p, "%02u empty (%02X)%s%s\n", i, txdesc->Ctl_8, thd, ttl);
25980 + txdesc = move_txdesc(priv, txdesc, 1);
25984 + "** PCI data **\n"
25985 + "txbuf_start %p, txbuf_area_size %u, txbuf_startphy %08llx\n"
25986 + "txdesc_size %u, txdesc_start %p\n"
25987 + "txhostdesc_start %p, txhostdesc_area_size %u, txhostdesc_startphy %08llx\n"
25988 + "rxdesc_start %p\n"
25989 + "rxhostdesc_start %p, rxhostdesc_area_size %u, rxhostdesc_startphy %08llx\n"
25990 + "rxbuf_start %p, rxbuf_area_size %u, rxbuf_startphy %08llx\n",
25991 + priv->txbuf_start, priv->txbuf_area_size, (u64)priv->txbuf_startphy,
25992 + priv->txdesc_size, priv->txdesc_start,
25993 + priv->txhostdesc_start, priv->txhostdesc_area_size, (u64)priv->txhostdesc_startphy,
25994 + priv->rxdesc_start,
25995 + priv->rxhostdesc_start, priv->rxhostdesc_area_size, (u64)priv->rxhostdesc_startphy,
25996 + priv->rxbuf_start, priv->rxbuf_area_size, (u64)priv->rxbuf_startphy);
26003 +/***********************************************************************
26006 +acx_proc_eeprom_output(char *buf, wlandevice_t *priv)
26013 + for (i = 0; i < 0x400; i++) {
26014 + acx_read_eeprom_offset(priv, i, p++);
26017 + FN_EXIT1(p - buf);
26022 +/***********************************************************************
26025 +acx_set_interrupt_mask(wlandevice_t *priv)
26027 + if (IS_ACX111(priv)) {
26028 + priv->irq_mask = (u16) ~(0
26029 + /* | HOST_INT_RX_DATA */
26030 + | HOST_INT_TX_COMPLETE
26031 + /* | HOST_INT_TX_XFER */
26032 + | HOST_INT_RX_COMPLETE
26033 + /* | HOST_INT_DTIM */
26034 + /* | HOST_INT_BEACON */
26035 + /* | HOST_INT_TIMER */
26036 + /* | HOST_INT_KEY_NOT_FOUND */
26037 + | HOST_INT_IV_ICV_FAILURE
26038 + | HOST_INT_CMD_COMPLETE
26040 + /* | HOST_INT_OVERFLOW */
26041 + /* | HOST_INT_PROCESS_ERROR */
26042 + | HOST_INT_SCAN_COMPLETE
26043 + | HOST_INT_FCS_THRESHOLD
26044 + /* | HOST_INT_UNKNOWN */
26046 + priv->irq_mask_off = (u16)~( HOST_INT_CMD_COMPLETE ); /* 0xfdff */
26048 + priv->irq_mask = (u16) ~(0
26049 + /* | HOST_INT_RX_DATA */
26050 + | HOST_INT_TX_COMPLETE
26051 + /* | HOST_INT_TX_XFER */
26052 + | HOST_INT_RX_COMPLETE
26053 + /* | HOST_INT_DTIM */
26054 + /* | HOST_INT_BEACON */
26055 + /* | HOST_INT_TIMER */
26056 + /* | HOST_INT_KEY_NOT_FOUND */
26057 + /* | HOST_INT_IV_ICV_FAILURE */
26058 + | HOST_INT_CMD_COMPLETE
26060 + /* | HOST_INT_OVERFLOW */
26061 + /* | HOST_INT_PROCESS_ERROR */
26062 + | HOST_INT_SCAN_COMPLETE
26063 + /* | HOST_INT_FCS_THRESHOLD */
26064 + /* | HOST_INT_UNKNOWN */
26066 + priv->irq_mask_off = (u16)~( HOST_INT_UNKNOWN ); /* 0x7fff */
26071 +/***********************************************************************
26074 +acx100_s_set_tx_level(wlandevice_t *priv, u8 level_dbm)
26076 + /* since it can be assumed that at least the Maxim radio has a
26077 + * maximum power output of 20dBm and since it also can be
26078 + * assumed that these values drive the DAC responsible for
26079 + * setting the linear Tx level, I'd guess that these values
26080 + * should be the corresponding linear values for a dBm value,
26081 + * in other words: calculate the values from that formula:
26082 + * Y [dBm] = 10 * log (X [mW])
26083 + * then scale the 0..63 value range onto the 1..100mW range (0..20 dBm)
26084 + * and you're done...
26085 + * Hopefully that's ok, but you never know if we're actually
26086 + * right... (especially since Windows XP doesn't seem to show
26087 + * actual Tx dBm values :-P) */
26089 + /* NOTE: on Maxim, value 30 IS 30mW, and value 10 IS 10mW - so the
26090 + * values are EXACTLY mW!!! Not sure about RFMD and others,
26092 + static const u8 dbm2val_maxim[21] = {
26100 + static const u8 dbm2val_rfmd[21] = {
26110 + switch (priv->radio_type) {
26111 + case RADIO_MAXIM_0D:
26112 + table = &dbm2val_maxim[0];
26114 + case RADIO_RFMD_11:
26115 + case RADIO_RALINK_15:
26116 + table = &dbm2val_rfmd[0];
26119 + printk("%s: unknown/unsupported radio type, "
26120 + "cannot modify tx power level yet!\n",
26121 + priv->netdev->name);
26124 + printk("%s: changing radio power level to %u dBm (%u)\n",
26125 + priv->netdev->name, level_dbm, table[level_dbm]);
26126 + acxpci_s_write_phy_reg(priv, 0x11, table[level_dbm]);
26131 +/*----------------------------------------------------------------
26132 +* acx_e_init_module
26134 +* Module initialization routine, called once at module load time.
26138 +* ~0 - failure, module is unloaded.
26141 +* process thread (insmod or modprobe)
26142 +----------------------------------------------------------------*/
26144 +acxpci_e_init_module(void)
26150 +#if (ACX_IO_WIDTH==32)
26151 + printk("acx: compiled to use 32bit I/O access. "
26152 + "I/O timing issues might occur, such as "
26153 + "non-working firmware upload. Report them\n");
26155 + printk("acx: compiled to use 16bit I/O access only "
26156 + "(compatibility mode)\n");
26159 +#ifdef __LITTLE_ENDIAN
26160 + acxlog(L_INIT, "running on a little-endian CPU\n");
26162 + acxlog(L_INIT, "running on a BIG-ENDIAN CPU\n");
26164 + acxlog(L_INIT, "PCI module " WLAN_RELEASE " initialized, "
26165 + "waiting for cards to probe...\n");
26167 + res = pci_module_init(&acx_pci_drv_id);
26173 +/*----------------------------------------------------------------
26174 +* acx_e_cleanup_module
26176 +* Called at module unload time. This is our last chance to
26177 +* clean up after ourselves.
26181 +----------------------------------------------------------------*/
26183 +acxpci_e_cleanup_module(void)
26185 + struct net_device *dev;
26186 + unsigned long flags;
26190 + /* Since the whole module is about to be unloaded,
26191 + * we recursively shutdown all cards we handled instead
26192 + * of doing it in remove_pci() (which will be activated by us
26193 + * via pci_unregister_driver at the end).
26194 + * remove_pci() might just get called after a card eject,
26195 + * that's why hardware operations have to be done here instead
26196 + * when the hardware is available. */
26198 + down(&root_acx_dev_sem);
26200 + dev = root_acx_dev.newest;
26201 + while (dev != NULL) {
26202 + /* doh, netdev_priv() doesn't have const! */
26203 + wlandevice_t *priv = netdev_priv(dev);
26205 + acx_sem_lock(priv);
26207 + /* disable both Tx and Rx to shut radio down properly */
26208 + acx_s_issue_cmd(priv, ACX1xx_CMD_DISABLE_TX, NULL, 0);
26209 + acx_s_issue_cmd(priv, ACX1xx_CMD_DISABLE_RX, NULL, 0);
26212 + /* put the eCPU to sleep to save power
26213 + * Halting is not possible currently,
26214 + * since not supported by all firmware versions */
26215 + acx_s_issue_cmd(priv, ACX100_CMD_SLEEP, NULL, 0);
26217 + acx_lock(priv, flags);
26219 + /* disable power LED to save power :-) */
26220 + acxlog(L_INIT, "switching off power LED to save power :-)\n");
26221 + acx_l_power_led(priv, 0);
26223 + /* stop our eCPU */
26224 + if (IS_ACX111(priv)) {
26225 + /* FIXME: does this actually keep halting the eCPU?
26226 + * I don't think so...
26228 + acx_l_reset_mac(priv);
26233 + temp = acx_read_reg16(priv, IO_ACX_ECPU_CTRL) | 0x1;
26234 + acx_write_reg16(priv, IO_ACX_ECPU_CTRL, temp);
26235 + acx_write_flush(priv);
26238 + acx_unlock(priv, flags);
26240 + acx_sem_unlock(priv);
26242 + dev = priv->prev_nd;
26245 + up(&root_acx_dev_sem);
26247 + /* now let the PCI layer recursively remove
26248 + * all PCI related things (acx_e_remove_pci()) */
26249 + pci_unregister_driver(&acx_pci_drv_id);
26253 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
26254 --- linux-2.6.14-omap2/drivers/net/wireless/tiacx/setrate.c 1970-01-01 02:00:00.000000000 +0200
26255 +++ linux-h6300-omap2-2.6.14.3/drivers/net/wireless/tiacx/setrate.c 2005-09-28 23:54:23.000000000 +0300
26257 +/* TODO: stop #including, move into wireless.c
26258 + * until then, keep in sync copies in prism54/ and acx/ dirs
26259 + * code+data size: less than 1k */
26282 + DOT11_MOD_CCKOFDM,
26285 +static const u8 ratelist[] = { 1,2,5,11,22,33,6,9,12,18,24,36,48,54 };
26286 +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 };
26287 +static const u8 default_modulation[] = {
26304 +static /* TODO: remove 'static' when moved to wireless.c */
26306 +rate_mbit2enum(int n) {
26308 + while(i<sizeof(ratelist)) {
26309 + if(n==ratelist[i]) return i;
26316 +get_modulation(int r_enum, char suffix) {
26317 + if(suffix==',' || suffix==' ' || suffix=='\0') {
26318 + /* could shorten default_mod by 8 bytes:
26319 + if(r_enum>=DOT11_RATE_6) return DOT11_MOD_OFDM; */
26320 + return default_modulation[r_enum];
26322 + if(suffix=='c') {
26323 + if(r_enum<DOT11_RATE_5 || r_enum>DOT11_RATE_11) return -EINVAL;
26324 + return DOT11_MOD_CCK;
26326 + if(suffix=='p') {
26327 + if(r_enum<DOT11_RATE_5 || r_enum>DOT11_RATE_33) return -EINVAL;
26328 + return DOT11_MOD_PBCC;
26330 + if(suffix=='o') {
26331 + if(r_enum<DOT11_RATE_6) return -EINVAL;
26332 + return DOT11_MOD_OFDM;
26334 + if(suffix=='d') {
26335 + if(r_enum<DOT11_RATE_6) return -EINVAL;
26336 + return DOT11_MOD_CCKOFDM;
26343 +fill_ratevector(const char **pstr, u8 *vector, int size,
26344 + int (*supported)(int mbit, int mod, void *opaque), void *opaque, int or_mask)
26346 + unsigned long rate_mbit;
26347 + int rate_enum,mod;
26348 + const char *str = *pstr;
26352 + rate_mbit = simple_strtoul(str, (char**)&str, 10);
26353 + if(rate_mbit>INT_MAX) return -EINVAL;
26355 + rate_enum = rate_mbit2enum(rate_mbit);
26356 + if(rate_enum<0) return rate_enum;
26359 + mod = get_modulation(rate_enum, c);
26360 + if(mod<0) return mod;
26362 + if(c>='a' && c<='z') c = *++str;
26363 + if(c!=',' && c!=' ' && c!='\0') return -EINVAL;
26366 + int r = supported(rate_mbit, mod, opaque);
26370 + *vector++ = dot11ratebyte[rate_enum] | or_mask;
26374 + } while(size>0 && c==',');
26376 + if(size<1) return -E2BIG;
26377 + *vector=0; /* TODO: sort, remove dups? */
26383 +static /* TODO: remove 'static' when moved to wireless.c */
26385 +fill_ratevectors(const char *str, u8 *brate, u8 *orate, int size,
26386 + int (*supported)(int mbit, int mod, void *opaque), void *opaque)
26390 + r = fill_ratevector(&str, brate, size, supported, opaque, 0x80);
26396 + r = fill_ratevector(&str, orate, size, supported, opaque, 0);
26398 + /* TODO: sanitize, e.g. remove/error on rates already in basic rate set? */
26407 +/* TODO: use u64 masks? */
26410 +fill_ratemask(const char **pstr, u32* mask,
26411 + int (*supported)(int mbit, int mod,void *opaque),
26412 + u32 (*gen_mask)(int mbit, int mod,void *opaque),
26415 + unsigned long rate_mbit;
26416 + int rate_enum,mod;
26418 + const char *str = *pstr;
26422 + rate_mbit = simple_strtoul(str, (char**)&str, 10);
26423 + if(rate_mbit>INT_MAX) return -EINVAL;
26425 + rate_enum = rate_mbit2enum(rate_mbit);
26426 + if(rate_enum<0) return rate_enum;
26429 + mod = get_modulation(rate_enum, c);
26430 + if(mod<0) return mod;
26432 + if(c>='a' && c<='z') c = *++str;
26433 + if(c!=',' && c!=' ' && c!='\0') return -EINVAL;
26436 + int r = supported(rate_mbit, mod, opaque);
26440 + m |= gen_mask(rate_mbit, mod, opaque);
26449 +static /* TODO: remove 'static' when moved to wireless.c */
26451 +fill_ratemasks(const char *str, u32 *bmask, u32 *omask,
26452 + int (*supported)(int mbit, int mod,void *opaque),
26453 + u32 (*gen_mask)(int mbit, int mod,void *opaque),
26458 + r = fill_ratemask(&str, bmask, supported, gen_mask, opaque);
26463 + r = fill_ratemask(&str, omask, supported, gen_mask, opaque);
26470 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
26471 --- linux-2.6.14-omap2/drivers/net/wireless/tiacx/usb.c 1970-01-01 02:00:00.000000000 +0200
26472 +++ linux-h6300-omap2-2.6.14.3/drivers/net/wireless/tiacx/usb.c 2005-09-28 23:54:23.000000000 +0300
26474 +/***********************************************************************
26475 +** Copyright (C) 2003 ACX100 Open Source Project
26477 +** The contents of this file are subject to the Mozilla Public
26478 +** License Version 1.1 (the "License"); you may not use this file
26479 +** except in compliance with the License. You may obtain a copy of
26480 +** the License at http://www.mozilla.org/MPL/
26482 +** Software distributed under the License is distributed on an "AS
26483 +** IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
26484 +** implied. See the License for the specific language governing
26485 +** rights and limitations under the License.
26487 +** Alternatively, the contents of this file may be used under the
26488 +** terms of the GNU Public License version 2 (the "GPL"), in which
26489 +** case the provisions of the GPL are applicable instead of the
26490 +** above. If you wish to allow the use of your version of this file
26491 +** only under the terms of the GPL and not to allow others to use
26492 +** your version of this file under the MPL, indicate your decision
26493 +** by deleting the provisions above and replace them with the notice
26494 +** and other provisions required by the GPL. If you do not delete
26495 +** the provisions above, a recipient may use your version of this
26496 +** file under either the MPL or the GPL.
26497 +** ---------------------------------------------------------------------
26498 +** Inquiries regarding the ACX100 Open Source Project can be
26499 +** made directly to:
26501 +** acx100-users@lists.sf.net
26502 +** http://acx100.sf.net
26503 +** ---------------------------------------------------------------------
26506 +/***********************************************************************
26507 +** USB support for TI ACX100 based devices. Many parts are taken from
26508 +** the PCI driver.
26511 +** Martin Wawro <martin.wawro AT uni-dortmund.de>
26512 +** Andreas Mohr <andi AT lisas.de>
26515 +** - Note that this driver relies on a native little-endian byteformat
26519 +** callback functions called by USB core are running in interrupt context
26520 +** and thus have names with _i_.
26524 +#include <linux/version.h>
26525 +#include <linux/config.h>
26526 +#include <linux/types.h>
26527 +#include <linux/module.h>
26528 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
26529 +#include <linux/moduleparam.h>
26531 +#include <linux/kernel.h>
26532 +#include <linux/usb.h>
26533 +#include <linux/netdevice.h>
26534 +#include <linux/rtnetlink.h>
26535 +#include <linux/etherdevice.h>
26536 +#include <linux/wireless.h>
26537 +#if WIRELESS_EXT >= 13
26538 +#include <net/iw_handler.h>
26543 +/* number of endpoints of an interface */
26544 +#define NUM_EP(intf) (intf)->altsetting[0].desc.bNumEndpoints
26545 +#define EP(intf, nr) (intf)->altsetting[0].endpoint[(nr)].desc
26546 +#define GET_DEV(udev) usb_get_dev((udev))
26547 +#define PUT_DEV(udev) usb_put_dev((udev))
26548 +#define SET_NETDEV_OWNER(ndev, owner) /* not needed anymore ??? */
26550 +#define QUEUE_BULK 0
26551 +#define ZERO_PACKET URB_ZERO_PACKET
26554 +submit_urb(struct urb *urb, int mem_flags)
26556 + return usb_submit_urb(urb, mem_flags);
26558 +static inline struct urb*
26559 +alloc_urb(int iso_pk, int mem_flags)
26561 + return usb_alloc_urb(iso_pk, mem_flags);
26565 +/***********************************************************************
26567 +#define ACX100_VENDOR_ID 0x2001
26568 +#define ACX100_PRODUCT_ID_UNBOOTED 0x3B01
26569 +#define ACX100_PRODUCT_ID_BOOTED 0x3B00
26571 +/* RX-Timeout: NONE (request waits forever) */
26572 +#define ACX100_USB_RX_TIMEOUT (0)
26574 +#define ACX100_USB_TX_TIMEOUT (4*HZ)
26576 +#define USB_CTRL_HARD_TIMEOUT 5500 /* steps in ms */
26579 +/***********************************************************************
26582 +static int acx100usb_e_probe(struct usb_interface *, const struct usb_device_id *);
26583 +static void acx100usb_e_disconnect(struct usb_interface *);
26584 +static void acx100usb_i_complete_tx(struct urb *, struct pt_regs *);
26585 +static void acx100usb_i_complete_rx(struct urb *, struct pt_regs *);
26586 +static int acx100usb_e_open(struct net_device *);
26587 +static int acx100usb_e_close(struct net_device *);
26588 +static void acx100usb_i_set_rx_mode(struct net_device *);
26589 +static int acx100usb_e_init_network_device(struct net_device *);
26590 +static int acx100usb_boot(struct usb_device *);
26592 +static struct net_device_stats * acx_e_get_stats(struct net_device *);
26593 +static struct iw_statistics *acx_e_get_wireless_stats(struct net_device *);
26595 +static void acx100usb_l_poll_rx(wlandevice_t *, int number);
26597 +static void acx100usb_i_tx_timeout(struct net_device *);
26599 +/* static void dump_device(struct usb_device *); */
26600 +/* static void dump_device_descriptor(struct usb_device_descriptor *); */
26601 +/* static void dump_config_descriptor(struct usb_config_descriptor *); */
26603 +/***********************************************************************
26606 +#define TXBUFSIZE sizeof(usb_txbuffer_t)
26607 +//// Bogus! We CANNOT pretend that rxbuffer_t is larger than it is.
26608 +/* make it a multiply of 64 */
26609 +/* #define RXBUFSIZE ((sizeof(rxbuffer_t)+63) & ~63) */
26610 +#define RXBUFSIZE sizeof(rxbuffer_t)
26612 +static const struct usb_device_id
26613 +acx100usb_ids[] = {
26614 + { USB_DEVICE(ACX100_VENDOR_ID, ACX100_PRODUCT_ID_BOOTED) },
26615 + { USB_DEVICE(ACX100_VENDOR_ID, ACX100_PRODUCT_ID_UNBOOTED) },
26620 +/* USB driver data structure as required by the kernel's USB core */
26621 +static struct usb_driver
26622 +acx100usb_driver = {
26623 + .name = "acx_usb",
26624 + .owner = THIS_MODULE,
26625 + .probe = acx100usb_e_probe,
26626 + .disconnect = acx100usb_e_disconnect,
26627 + .id_table = acx100usb_ids
26631 +/***********************************************************************
26634 +** ldd3 ch13 says:
26635 +** When the function is usb_kill_urb, the urb lifecycle is stopped. This
26636 +** function is usually used when the device is disconnected from the system,
26637 +** in the disconnect callback. For some drivers, the usb_unlink_urb function
26638 +** should be used to tell the USB core to stop an urb. This function does not
26639 +** wait for the urb to be fully stopped before returning to the caller.
26640 +** This is useful for stoppingthe urb while in an interrupt handler or when
26641 +** a spinlock is held, as waiting for a urb to fully stop requires the ability
26642 +** for the USB core to put the calling process to sleep. This function requires
26643 +** that the URB_ASYNC_UNLINK flag value be set in the urb that is being asked
26644 +** to be stopped in order to work properly.
26646 +** URB_ASYNC_UNLINK is osolete, usb_unlink_urb will always be
26647 +** asynchronuos while usb_kill_urb is synchronuos and should be called
26648 +** directly. -> drivers/usb/core/urb.c
26650 +** In light of this, timeout is just for paranoid reasons...
26653 +acx_unlink_and_free_urb(struct urb* urb)
26658 + if (urb->status == -EINPROGRESS) {
26659 + int timeout = 10;
26661 + usb_unlink_urb(urb);
26662 + while (--timeout && urb->status == -EINPROGRESS) {
26665 + /* if (!timeout) then what?? */
26668 + /* just a refcounted kfree, safe undef lock */
26669 + usb_free_urb(urb);
26673 +/***********************************************************************
26677 +acx100usb_pstatus(int val)
26679 + static char status[20];
26682 + sprintf(status, "errno %d", -val);
26684 + sprintf(status, "length %d", val);
26688 +#endif /* ACX_DEBUG */
26691 +/***********************************************************************
26692 +** EEPROM and PHY read/write helpers
26694 +/***********************************************************************
26695 +** acxusb_s_read_phy_reg
26698 +acxusb_s_read_phy_reg(wlandevice_t *priv, u32 reg, u8 *charbuf)
26700 + mem_read_write_t mem;
26704 + mem.addr = cpu_to_le16(reg);
26705 + mem.type = cpu_to_le16(0x82);
26706 + mem.len = cpu_to_le32(4);
26707 + acx_s_issue_cmd(priv, ACX1xx_CMD_MEM_READ, &mem, sizeof(mem) - 4);
26708 + *charbuf = mem.data;
26709 + acxlog(L_DEBUG, "radio PHY at 0x%04X = 0x%02X\n", *charbuf, reg);
26716 +/***********************************************************************
26719 +acxusb_s_write_phy_reg(wlandevice_t *priv, u32 reg, u8 value)
26721 + mem_read_write_t mem;
26725 + mem.addr = cpu_to_le16(reg);
26726 + mem.type = cpu_to_le16(0x82);
26727 + mem.len = cpu_to_le32(4);
26728 + mem.data = value;
26729 +//FIXME: maybe sizeof() - 4?
26730 + acx_s_issue_cmd(priv, ACX1xx_CMD_MEM_WRITE, &mem, sizeof(mem));
26731 + acxlog(L_DEBUG, "radio PHY write 0x%02X at 0x%04X\n", value, reg);
26738 +/***********************************************************************
26739 +** acx_s_issue_cmd_timeo
26740 +** Excecutes a command in the command mailbox
26742 +** buffer = a pointer to the data.
26743 +** The data must not include 4 byte command header
26746 +/* TODO: ideally we shall always know how much we need
26747 +** and this shall be 0 */
26748 +#define BOGUS_SAFETY_PADDING 0x40
26751 +#define FUNC "issue_cmd"
26755 +acxusb_s_issue_cmd_timeo(
26756 + wlandevice_t *priv,
26760 + unsigned timeout)
26764 +acxusb_s_issue_cmd_timeo_debug(
26765 + wlandevice_t *priv,
26769 + unsigned timeout,
26770 + const char* cmdstr)
26773 + /* USB ignores timeout param */
26775 + struct usb_device *usbdev;
26777 + u16 cmd ACX_PACKED;
26778 + u16 status ACX_PACKED;
26779 + u8 data[1] ACX_PACKED;
26781 + const char *devname;
26782 + int acklen, blocklen, inpipe, outpipe;
26788 + devname = priv->netdev->name;
26789 + if (!devname || !devname[0])
26792 + acxlog(L_CTL, FUNC"(cmd:%s,buflen:%u,type:0x%04X)\n",
26794 + buffer ? le16_to_cpu(((acx_ie_generic_t *)buffer)->type) : -1);
26796 + loc = kmalloc(buflen + 4 + BOGUS_SAFETY_PADDING, GFP_KERNEL);
26798 + printk("%s: "FUNC"(): no memory for data buffer\n", devname);
26802 + /* get context from wlandevice */
26803 + usbdev = priv->usbdev;
26805 + /* check which kind of command was issued */
26806 + loc->cmd = cpu_to_le16(cmd);
26809 +/* NB: buflen == frmlen + 4
26811 +** Interrogate: write 8 bytes: (cmd,status,rid,frmlen), then
26812 +** read (cmd,status,rid,frmlen,data[frmlen]) back
26814 +** Configure: write (cmd,status,rid,frmlen,data[frmlen])
26816 +** Possibly bogus special handling of ACX1xx_IE_SCAN_STATUS removed
26819 + /* now write the parameters of the command if needed */
26820 + acklen = buflen + 4 + BOGUS_SAFETY_PADDING;
26821 + blocklen = buflen;
26822 + if (buffer && buflen) {
26823 + /* if it's an INTERROGATE command, just pass the length
26824 + * of parameters to read, as data */
26825 + if (cmd == ACX1xx_CMD_INTERROGATE) {
26827 + acklen = buflen + 4;
26829 + memcpy(loc->data, buffer, blocklen);
26831 + blocklen += 4; /* account for cmd,status */
26833 + /* obtain the I/O pipes */
26834 + outpipe = usb_sndctrlpipe(usbdev, 0);
26835 + inpipe = usb_rcvctrlpipe(usbdev, 0);
26836 + acxlog(L_CTL, "ctrl inpipe=0x%X outpipe=0x%X\n", inpipe, outpipe);
26837 + acxlog(L_CTL, "sending USB control msg (out) (blocklen=%d)\n", blocklen);
26838 + if (acx_debug & L_DATA)
26839 + acx_dump_bytes(loc, blocklen);
26841 + result = usb_control_msg(usbdev, outpipe,
26842 + ACX_USB_REQ_CMD, /* request */
26843 + USB_TYPE_VENDOR|USB_DIR_OUT, /* requesttype */
26846 + loc, /* dataptr */
26847 + blocklen, /* size */
26848 + USB_CTRL_HARD_TIMEOUT /* timeout in ms */
26850 + acxlog(L_CTL, "wrote %d bytes\n", result);
26851 + if (result < 0) {
26855 + /* check for device acknowledge */
26856 + acxlog(L_CTL, "sending USB control msg (in) (acklen=%d)\n", acklen);
26857 + loc->status = 0; /* delete old status flag -> set to IDLE */
26858 +//shall we zero out the rest?
26859 + result = usb_control_msg(usbdev, inpipe,
26860 + ACX_USB_REQ_CMD, /* request */
26861 + USB_TYPE_VENDOR|USB_DIR_IN, /* requesttype */
26864 + loc, /* dataptr */
26865 + acklen, /* size */
26866 + USB_CTRL_HARD_TIMEOUT /* timeout in ms */
26868 + if (result < 0) {
26869 + printk("%s: "FUNC"(): USB read error %d\n", devname, result);
26872 + if (acx_debug & L_CTL) {
26873 + printk("read %d bytes: ", result);
26874 + acx_dump_bytes(loc, result);
26877 +//check for result==buflen+4? Was seen:
26878 +//interrogate(type:ACX100_IE_DOT11_ED_THRESHOLD,len:4)
26879 +//issue_cmd(cmd:ACX1xx_CMD_INTERROGATE,buflen:8,type:4111)
26880 +//ctrl inpipe=0x80000280 outpipe=0x80000200
26881 +//sending USB control msg (out) (blocklen=8)
26882 +//01 00 00 00 0F 10 04 00
26884 +//sending USB control msg (in) (acklen=12) sizeof(loc->data
26885 +//read 4 bytes <==== MUST BE 12!!
26887 + cmd_status = le16_to_cpu(loc->status);
26888 + if (cmd_status != 1) {
26889 + printk("%s: "FUNC"(): cmd_status is not SUCCESS: %d (%s)\n",
26890 + devname, cmd_status, acx_cmd_status_str(cmd_status));
26891 + /* TODO: goto bad; ? */
26893 + if ((cmd == ACX1xx_CMD_INTERROGATE) && buffer && buflen) {
26894 + memcpy(buffer, loc->data, buflen);
26895 + acxlog(L_CTL, "response frame: cmd=0x%04X status=%d\n",
26896 + le16_to_cpu(loc->cmd),
26904 + /* Give enough info so that callers can avoid
26905 + ** printing their own diagnostic messages */
26907 + printk("%s: "FUNC"(cmd:%s) FAILED\n", devname, cmdstr);
26909 + printk("%s: "FUNC"(cmd:0x%04X) FAILED\n", devname, cmd);
26912 + FN_EXIT1(NOT_OK);
26917 +/***********************************************************************
26918 +** acx100usb_e_probe()
26921 +** dev -> Pointer to usb_device structure that may or may not be claimed
26922 +** ifNum -> Interface number
26923 +** devID -> Device ID (vendor and product specific stuff)
26924 +************************************************************************
26926 +** (void *) Pointer to (custom) driver context or NULL if we are not interested
26927 +** or unable to handle the offered device.
26930 +** This function is invoked by the kernel's USB core whenever a new device is
26931 +** attached to the system or the module is loaded. It is presented a usb_device
26932 +** structure from which information regarding the device is obtained and evaluated.
26933 +** In case this driver is able to handle one of the offered devices, it returns
26934 +** a non-null pointer to a driver context and thereby claims the device.
26937 +acx_netdev_init(struct net_device *dev) {}
26940 +acx100usb_e_probe(struct usb_interface *intf, const struct usb_device_id *devID)
26942 + struct usb_device *usbdev = interface_to_usbdev(intf);
26943 + wlandevice_t *priv = NULL;
26944 + struct net_device *dev = NULL;
26945 + struct usb_config_descriptor *config;
26946 + struct usb_endpoint_descriptor *epdesc;
26947 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11)
26948 + struct usb_host_endpoint *ep;
26950 + struct usb_interface_descriptor *ifdesc;
26952 + int numconfigs, numfaces, numep;
26958 + /* First check if this is the "unbooted" hardware */
26959 + if ((usbdev->descriptor.idVendor == ACX100_VENDOR_ID)
26960 + && (usbdev->descriptor.idProduct == ACX100_PRODUCT_ID_UNBOOTED)) {
26961 + /* Boot the device (i.e. upload the firmware) */
26962 + acx100usb_boot(usbdev);
26964 + /* OK, we are done with booting. Normally, the
26965 + ** ID for the unbooted device should disappear
26966 + ** and it will not need a driver anyway...so
26969 + acxlog(L_INIT, "finished booting, returning from probe()\n");
26970 + result = OK; /* success */
26974 + if ((usbdev->descriptor.idVendor != ACX100_VENDOR_ID)
26975 + || (usbdev->descriptor.idProduct != ACX100_PRODUCT_ID_BOOTED)) {
26979 + /* Ok, so it's our device and it is already booted */
26981 + /* Allocate memory for a network device */
26982 + dev = alloc_netdev(sizeof(wlandevice_t), "wlan%d", acx_netdev_init);
26983 + /* (NB: memsets to 0 entire area) */
26985 + msg = "acx: no memory for netdev\n";
26988 + dev->init = (void *)&acx100usb_e_init_network_device;
26990 + /* Setup private driver context */
26991 + priv = netdev_priv(dev);
26992 + priv->netdev = dev;
26993 + priv->dev_type = DEVTYPE_USB;
26994 + priv->chip_type = CHIPTYPE_ACX100;
26995 + /* FIXME: should be read from register (via firmware) using standard ACX code */
26996 + priv->radio_type = RADIO_MAXIM_0D;
26997 + priv->usbdev = usbdev;
26999 + spin_lock_init(&priv->lock); /* initial state: unlocked */
27000 + sema_init(&priv->sem, 1); /* initial state: 1 (upped) */
27002 + /* Initialize the device context and also check
27003 + ** if this is really the hardware we know about.
27004 + ** If not sure, at least notify the user that he
27005 + ** may be in trouble...
27007 + numconfigs = (int)usbdev->descriptor.bNumConfigurations;
27008 + if (numconfigs != 1)
27009 + printk("acx: number of configurations is %d, "
27010 + "this driver only knows how to handle 1, "
27011 + "be prepared for surprises\n", numconfigs);
27013 + config = &usbdev->config->desc;
27014 + numfaces = config->bNumInterfaces;
27015 + if (numfaces != 1)
27016 + printk("acx: number of interfaces is %d, "
27017 + "this driver only knows how to handle 1, "
27018 + "be prepared for surprises\n", numfaces);
27020 + ifdesc = &intf->altsetting->desc;
27021 + numep = ifdesc->bNumEndpoints;
27022 + acxlog(L_DEBUG, "# of endpoints: %d\n", numep);
27024 + /* obtain information about the endpoint
27025 + ** addresses, begin with some default values
27027 + priv->bulkoutep = 1;
27028 + priv->bulkinep = 1;
27029 + for (i = 0; i < numep; i++) {
27030 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11)
27031 + ep = usbdev->ep_in[i];
27034 + epdesc = &ep->desc;
27036 + epdesc = usb_epnum_to_ep_desc(usbdev, i);
27040 + if (epdesc->bmAttributes & USB_ENDPOINT_XFER_BULK) {
27041 + if (epdesc->bEndpointAddress & 0x80)
27042 + priv->bulkinep = epdesc->bEndpointAddress & 0xF;
27044 + priv->bulkoutep = epdesc->bEndpointAddress & 0xF;
27047 + acxlog(L_DEBUG, "bulkout ep: 0x%X\n", priv->bulkoutep);
27048 + acxlog(L_DEBUG, "bulkin ep: 0x%X\n", priv->bulkinep);
27050 + /* Set the packet-size equivalent to the buffer size */
27051 + /* already done by memset: priv->rxtruncsize = 0; */
27052 + acxlog(L_DEBUG, "TXBUFSIZE=%d RXBUFSIZE=%d\n",
27053 + (int) TXBUFSIZE, (int) RXBUFSIZE);
27055 + priv->tx_free = ACX100_USB_NUM_BULK_URBS;
27056 + /* already done by memset:
27057 + for (i = 0; i < ACX100_USB_NUM_BULK_URBS; i++) {
27058 + priv->usb_tx[i].busy = 0;
27062 + /* Setup URBs for bulk-in/out messages */
27063 + for (i = 0; i < ACX100_USB_NUM_BULK_URBS; i++) {
27064 + priv->bulkrx_urbs[i] = alloc_urb(0, GFP_KERNEL);
27065 + if (!priv->bulkrx_urbs[i]) {
27066 + msg = "acx: no memory for input URB\n";
27069 + priv->bulkrx_urbs[i]->status = 0;
27071 + priv->usb_tx[i].urb = alloc_urb(0, GFP_KERNEL);
27072 + if (!priv->usb_tx[i].urb) {
27073 + msg = "acx: no memory for output URB\n";
27076 + priv->usb_tx[i].urb->status = 0;
27078 + priv->usb_tx[i].priv = priv;
27081 + usb_set_intfdata(intf, priv);
27082 + SET_NETDEV_DEV(dev, &intf->dev);
27084 + /* Register the network device */
27085 + acxlog(L_INIT, "registering network device\n");
27086 + result = register_netdev(dev);
27087 + if (result != 0) {
27088 + msg = "acx: failed to register network device "
27089 + "for USB WLAN (errcode=%d)\n";
27092 +#ifdef CONFIG_PROC_FS
27093 + if (OK != acx_proc_register_entries(dev)) {
27094 + printk("acx: /proc registration failed\n");
27098 + printk("acx: USB module " WLAN_RELEASE " loaded successfully\n");
27101 + great_inquisitor(priv);
27104 + /* Everything went OK, we are happy now */
27109 + printk(msg, result);
27112 + for (i = 0; i < ACX100_USB_NUM_BULK_URBS; i++) {
27113 + usb_free_urb(priv->bulkrx_urbs[i]);
27114 + usb_free_urb(priv->usb_tx[i].urb);
27116 + free_netdev(dev);
27118 + result = -ENOMEM;
27123 + /* no device we could handle, return error. */
27127 + FN_EXIT1(result);
27132 +/***********************************************************************
27133 +** acx100usb_e_disconnect():
27135 +** dev -> Pointer to usb_device structure handled by this module
27136 +** devContext -> Pointer to own device context (acx100usb_context)
27137 +************************************************************************
27139 +** This function is invoked whenever the user pulls the plug from the USB
27140 +** device or the module is removed from the kernel. In these cases, the
27141 +** network devices have to be taken down and all allocated memory has
27145 +acx100usb_e_disconnect(struct usb_interface *intf)
27147 + wlandevice_t *priv = usb_get_intfdata(intf);
27148 + unsigned long flags;
27153 + /* No WLAN device...no sense */
27158 + * We get the sem *after* FLUSH to avoid a deadlock.
27159 + * See pci.c:acx_s_down() for deails.
27161 + FLUSH_SCHEDULED_WORK();
27162 + acx_sem_lock(priv);
27164 + acx_lock(priv, flags);
27166 + /* I wonder if above is enough to prevent tx/rx callbacks
27167 + ** to start queue again? Like this:
27168 + ** complete_rx -> acx_l_process_rxbuf -> associated -> acx_start_queue()
27171 + /* This device exists no more. */
27172 + usb_set_intfdata(intf, NULL);
27174 + /* stop the transmit queue */
27175 + if (priv->netdev) {
27176 + acx_stop_queue(priv->netdev, "on USB disconnect");
27177 +#ifdef CONFIG_PROC_FS
27178 + acx_proc_unregister_entries(priv->netdev);
27182 + /* now abort pending URBs and free them */
27183 + for (i = 0; i < ACX100_USB_NUM_BULK_URBS; i++) {
27184 + acx_unlink_and_free_urb(priv->bulkrx_urbs[i]);
27185 + acx_unlink_and_free_urb(priv->usb_tx[i].urb);
27188 + acx_unlock(priv, flags);
27189 + acx_sem_unlock(priv);
27191 + /* Unregister the network devices */
27192 + if (priv->netdev) {
27193 + unregister_netdev(priv->netdev);
27194 + free_netdev(priv->netdev);
27201 +/***********************************************************************
27202 +** acx100usb_boot():
27204 +** usbdev -> Pointer to kernel's usb_device structure
27205 +** endpoint -> Address of the endpoint for control transfers
27206 +************************************************************************
27208 +** (int) Errorcode or 0 on success
27211 +** This function triggers the loading of the firmware image from harddisk
27212 +** and then uploads the firmware to the USB device. After uploading the
27213 +** firmware and transmitting the checksum, the device resets and appears
27214 +** as a new device on the USB bus (the device we can finally deal with)
27217 +acx100usb_boot(struct usb_device *usbdev)
27219 + static const char filename[] = "tiacx100usb";
27221 + char *firmware = NULL;
27223 + unsigned int offset;
27224 + unsigned int len, inpipe, outpipe;
27231 + usbbuf = kmalloc(ACX100_USB_RWMEM_MAXLEN, GFP_KERNEL);
27233 + printk(KERN_ERR "acx: no memory for USB transfer buffer ("
27234 + STRING(ACX100_USB_RWMEM_MAXLEN)" bytes)\n");
27235 + result = -ENOMEM;
27238 + firmware = (char *)acx_s_read_fw(&usbdev->dev, filename, &size);
27243 + acxlog(L_INIT, "firmware size: %d bytes\n", size);
27245 + /* Obtain the I/O pipes */
27246 + outpipe = usb_sndctrlpipe(usbdev, 0);
27247 + inpipe = usb_rcvctrlpipe(usbdev, 0);
27249 + /* now upload the firmware, slice the data into blocks */
27251 + while (offset < size) {
27252 + len = size - offset;
27253 + if (len >= ACX100_USB_RWMEM_MAXLEN) {
27254 + len = ACX100_USB_RWMEM_MAXLEN;
27256 + acxlog(L_INIT, "uploading firmware (%d bytes, offset=%d)\n",
27259 + memcpy(usbbuf, firmware + offset, len);
27260 + result = usb_control_msg(usbdev, outpipe,
27261 + ACX_USB_REQ_UPLOAD_FW,
27262 + USB_TYPE_VENDOR|USB_DIR_OUT,
27263 + size - 8, /* value */
27265 + usbbuf, /* dataptr */
27267 + 3000 /* timeout in ms */
27270 + if (result < 0) {
27272 + printk(KERN_ERR "acx: error %d (%s) during upload "
27273 + "of firmware, aborting\n", result,
27274 + acx100usb_pstatus(result));
27276 + printk(KERN_ERR "acx: error %d during upload "
27277 + "of firmware, aborting\n", result);
27283 + /* finally, send the checksum and reboot the device */
27284 + checksum = le32_to_cpu(*(u32 *)firmware);
27285 + /* is this triggers the reboot? */
27286 + result = usb_control_msg(usbdev, outpipe,
27287 + ACX_USB_REQ_UPLOAD_FW,
27288 + USB_TYPE_VENDOR|USB_DIR_OUT,
27289 + checksum & 0xffff, /* value */
27290 + checksum >> 16, /* index */
27291 + NULL, /* dataptr */
27293 + 3000 /* timeout in ms */
27295 + if (result < 0) {
27296 + printk(KERN_ERR "acx: error %d during tx of checksum, "
27297 + "aborting\n", result);
27300 + result = usb_control_msg(usbdev, inpipe,
27301 + ACX_USB_REQ_ACK_CS,
27302 + USB_TYPE_VENDOR|USB_DIR_IN,
27303 + checksum & 0xffff, /* value */
27304 + checksum >> 16, /* index */
27305 + usbbuf, /* dataptr */
27307 + 3000 /* timeout in ms */
27309 + if (result < 0) {
27310 + printk(KERN_ERR "acx: error %d during ACK of checksum, "
27311 + "aborting\n", result);
27314 + if (*usbbuf != 0x10) {
27316 + printk(KERN_ERR "acx: invalid checksum?\n");
27317 + result = -EINVAL;
27325 + FN_EXIT1(result);
27330 +/***********************************************************************
27331 +** acx100usb_e_init_network_device():
27333 +** dev -> Pointer to network device
27334 +************************************************************************
27336 +** Basic setup of a network device for use with the WLAN device.
27339 +acx100usb_e_init_network_device(struct net_device *dev)
27341 + wlandevice_t *priv;
27346 + /* Setup the device and stop the queue */
27347 + ether_setup(dev);
27348 + acx_stop_queue(dev, "on init");
27350 + priv = netdev_priv(dev);
27352 + acx_sem_lock(priv);
27354 + /* put the ACX100 out of sleep mode */
27355 + acx_s_issue_cmd(priv, ACX1xx_CMD_WAKE, NULL, 0);
27357 + /* Register the callbacks for the network device functions */
27358 + dev->open = &acx100usb_e_open;
27359 + dev->stop = &acx100usb_e_close;
27360 + dev->hard_start_xmit = (void *)&acx_i_start_xmit;
27361 + dev->get_stats = (void *)&acx_e_get_stats;
27362 + dev->get_wireless_stats = (void *)&acx_e_get_wireless_stats;
27363 +#if WIRELESS_EXT >= 13
27364 + dev->wireless_handlers = (struct iw_handler_def *)&acx_ioctl_handler_def;
27366 + dev->do_ioctl = (void *)&acx_e_ioctl_old;
27368 + dev->set_multicast_list = (void *)&acx100usb_i_set_rx_mode;
27369 +#ifdef HAVE_TX_TIMEOUT
27370 + dev->tx_timeout = &acx100usb_i_tx_timeout;
27371 + dev->watchdog_timeo = 4 * HZ;
27373 + result = acx_s_init_mac(dev);
27374 + if (OK != result)
27376 + result = acx_s_set_defaults(priv);
27377 + if (OK != result) {
27378 + printk("%s: acx_set_defaults FAILED\n", dev->name);
27382 + SET_MODULE_OWNER(dev);
27384 + acx_sem_unlock(priv);
27386 + FN_EXIT1(result);
27391 +/***********************************************************************
27392 +** acx100usb_e_open
27393 +** This function is called when the user sets up the network interface.
27394 +** It initializes a management timer, sets up the USB card and starts
27395 +** the network tx queue and USB receive.
27398 +acx100usb_e_open(struct net_device *dev)
27400 + wlandevice_t *priv = netdev_priv(dev);
27401 + unsigned long flags;
27406 + acx_sem_lock(priv);
27408 + /* put the ACX100 out of sleep mode */
27409 + acx_s_issue_cmd(priv, ACX1xx_CMD_WAKE, NULL, 0);
27411 + acx_init_task_scheduler(priv);
27413 + init_timer(&priv->mgmt_timer);
27414 + priv->mgmt_timer.function = acx_i_timer;
27415 + priv->mgmt_timer.data = (unsigned long)priv;
27417 + /* set ifup to 1, since acx_start needs it */
27418 + SET_BIT(priv->dev_state_mask, ACX_STATE_IFACE_UP);
27419 + acx_s_start(priv);
27421 + acx_start_queue(dev, "on open");
27423 + acx_lock(priv, flags);
27424 + for (i = 0; i < ACX100_USB_NUM_BULK_URBS; i++) {
27425 + acx100usb_l_poll_rx(priv, i);
27427 + acx_unlock(priv, flags);
27429 + WLAN_MOD_INC_USE_COUNT;
27431 + acx_sem_unlock(priv);
27438 +/***********************************************************************
27439 +** acx100usb_l_poll_rx
27440 +** This function initiates a bulk-in USB transfer (in case the interface
27444 +acx100usb_l_poll_rx(wlandevice_t *priv, int number)
27446 + struct usb_device *usbdev;
27447 + rxbuffer_t *inbuf;
27448 + acx_usb_bulk_context_t *rxcon;
27449 + struct urb *rxurb;
27451 + unsigned int inpipe;
27455 + if (!(priv->dev_state_mask & ACX_STATE_IFACE_UP)) {
27459 + rxcon = &priv->rxcons[number];
27460 + inbuf = &priv->bulkins[number];
27461 + rxurb = priv->bulkrx_urbs[number];
27462 + usbdev = priv->usbdev;
27464 + rxcon->device = priv;
27465 + rxcon->number = number;
27466 + inpipe = usb_rcvbulkpipe(usbdev, priv->bulkinep);
27467 + if (rxurb->status == -EINPROGRESS) {
27468 + printk(KERN_ERR "acx: error, rx triggered while rx urb in progress\n");
27469 + /* FIXME: this is nasty, receive is being cancelled by this code
27470 + * on the other hand, this should not happen anyway...
27472 + usb_unlink_urb(rxurb);
27474 + rxurb->actual_length = 0;
27475 + usb_fill_bulk_urb(rxurb, usbdev, inpipe,
27476 + inbuf, /* dataptr */
27477 + RXBUFSIZE, /* size */
27478 + acx100usb_i_complete_rx, /* handler */
27479 + rxcon /* handler param */
27481 + rxurb->transfer_flags = QUEUE_BULK;
27483 + /* ATOMIC: we may be called from complete_rx() usb callback */
27484 + errcode = submit_urb(rxurb, GFP_ATOMIC);
27485 + /* FIXME: evaluate the error code! */
27486 + acxlog(L_USBRXTX, "SUBMIT RX (%d) inpipe=0x%X size=%d errcode=%d\n",
27487 + number, inpipe, (int) RXBUFSIZE, errcode);
27494 +/***********************************************************************
27495 +** acx100usb_i_complete_rx():
27497 +** urb -> Pointer to USB request block
27498 +** regs -> Pointer to register-buffer for syscalls (see asm/ptrace.h)
27499 +************************************************************************
27501 +** This function is invoked by USB subsystem whenever a bulk receive
27502 +** request returns.
27503 +** The received data is then committed to the network stack and the next
27504 +** USB receive is triggered.
27507 +acx100usb_i_complete_rx(struct urb *urb, struct pt_regs *regs)
27509 + wlandevice_t *priv;
27511 + rxbuffer_t *inbuf;
27512 + unsigned long flags;
27513 + int size, number, remsize, packetsize;
27517 + if (!urb->context) {
27518 + printk(KERN_ERR "acx: error, urb context was NULL\n");
27519 + goto end; /* at least try to prevent the worst */
27522 + priv = ((acx_usb_bulk_context_t *)urb->context)->device;
27524 + acx_lock(priv, flags);
27526 + /* TODO: we maybe need to check whether urb was unlinked
27527 + ** (happens on disconnect and close, see there). How? */
27529 + number = ((acx_usb_bulk_context_t *)urb->context)->number;
27530 + size = urb->actual_length;
27533 + acxlog(L_USBRXTX, "RETURN RX (%d) status=%d size=%d\n",
27534 + number, urb->status, size);
27536 + inbuf = &priv->bulkins[number];
27539 + /* check if the transfer was aborted */
27540 + switch (urb->status) {
27541 + case 0: /* No error */
27544 + printk(KERN_ERR "acx: error in rx, data overrun -> emergency stop\n");
27545 + /* LOCKING BUG! acx100usb_e_close(priv->netdev); */
27547 + case -ECONNRESET:
27550 + priv->stats.rx_errors++;
27551 + printk("acx: rx error (urb status=%d)\n", urb->status);
27556 + printk("acx: warning, encountered zerolength rx packet\n");
27558 + if (urb->transfer_buffer != inbuf)
27561 + /* check if previous frame was truncated
27562 + ** FIXME: this code can only handle truncation
27563 + ** of consecutive packets!
27565 + if (priv->rxtruncsize) {
27568 + ptr = &priv->rxtruncbuf;
27569 + packetsize = RXBUF_BYTES_RCVD(ptr) + RXBUF_HDRSIZE;
27570 + if (acx_debug & L_USBRXTX) {
27571 + printk("handling truncated frame (truncsize=%d size=%d "
27572 + "packetsize(from trunc)=%d)\n",
27573 + priv->rxtruncsize, size, packetsize);
27574 + acx_dump_bytes(ptr, RXBUF_HDRSIZE);
27575 + acx_dump_bytes(inbuf, RXBUF_HDRSIZE);
27578 + /* bytes needed for rxtruncbuf completion: */
27579 + tail_size = packetsize - priv->rxtruncsize;
27581 + if (size < tail_size) {
27582 + /* there is not enough data to complete this packet,
27583 + ** simply append the stuff to the truncation buffer
27585 + memcpy(((char *)ptr) + priv->rxtruncsize, inbuf, size);
27586 + priv->rxtruncsize += size;
27589 + /* ok, this data completes the previously
27590 + ** truncated packet. copy it into a descriptor
27591 + ** and give it to the rest of the stack */
27593 + /* append tail to previously truncated part
27594 + ** NB: priv->rxtruncbuf (pointed to by ptr) can't
27595 + ** overflow because this is already checked before
27596 + ** truncation buffer was filled. See below,
27597 + ** "if (packetsize > sizeof(rxbuffer_t))..." code */
27598 + memcpy(((char *)ptr) + priv->rxtruncsize, inbuf, tail_size);
27600 + if (acx_debug & L_USBRXTX) {
27601 + printk("full trailing packet + 12 bytes:\n");
27602 + acx_dump_bytes(inbuf, tail_size + RXBUF_HDRSIZE);
27604 + acx_l_process_rxbuf(priv, ptr);
27605 + priv->rxtruncsize = 0;
27606 + ptr = (rxbuffer_t *) (((char *)inbuf) + tail_size);
27607 + remsize -= tail_size;
27609 + acxlog(L_USBRXTX, "post-merge size=%d remsize=%d\n",
27613 + /* size = USB data block size
27614 + ** remsize = unprocessed USB bytes left
27615 + ** ptr = current pos in USB data block
27617 + while (remsize) {
27618 + if (remsize < RXBUF_HDRSIZE) {
27619 + printk("acx: truncated rx header (%d bytes)!\n",
27623 + packetsize = RXBUF_BYTES_RCVD(ptr) + RXBUF_HDRSIZE;
27624 + acxlog(L_USBRXTX, "packet with packetsize=%d\n", packetsize);
27625 + if (packetsize > sizeof(rxbuffer_t)) {
27626 + printk("acx: packet exceeds max wlan "
27627 + "frame size (%d > %d). size=%d\n",
27628 + packetsize, (int) sizeof(rxbuffer_t), size);
27629 + /* FIXME: put some real error-handling in here! */
27633 + /* skip null packets (does this really happen?!) */
27634 + if (packetsize == RXBUF_HDRSIZE) {
27635 + remsize -= RXBUF_HDRSIZE;
27636 + if (acx_debug & L_USBRXTX) {
27637 + printk("acx: null packet, new remsize=%d. "
27638 + "header follows:\n", remsize);
27639 + acx_dump_bytes(ptr, RXBUF_HDRSIZE);
27641 + ptr = (rxbuffer_t *)(((char *)ptr) + RXBUF_HDRSIZE);
27645 + if (packetsize > remsize) {
27646 + /* frame truncation handling */
27647 + if (acx_debug & L_USBRXTX) {
27648 + printk("need to truncate packet, "
27649 + "packetsize=%d remsize=%d "
27651 + packetsize, remsize, size);
27652 + acx_dump_bytes(ptr, RXBUF_HDRSIZE);
27654 + memcpy(&priv->rxtruncbuf, ptr, remsize);
27655 + priv->rxtruncsize = remsize;
27657 + } else { /* packetsize <= remsize */
27658 + /* now handle the received data */
27659 + acx_l_process_rxbuf(priv, ptr);
27661 + ptr = (rxbuffer_t *)(((char *)ptr) + packetsize);
27662 + remsize -= packetsize;
27663 + if ((acx_debug & L_USBRXTX) && remsize) {
27664 + printk("more than one packet in buffer, "
27665 + "second packet hdr follows\n");
27666 + acx_dump_bytes(ptr, RXBUF_HDRSIZE);
27672 + /* look for the next rx */
27673 + if (priv->dev_state_mask & ACX_STATE_IFACE_UP) {
27674 + /* receive of frame completed, now look for the next one */
27675 + acx100usb_l_poll_rx(priv, number);
27679 + acx_unlock(priv, flags);
27685 +/***********************************************************************
27686 +** acx100usb_i_complete_tx():
27688 +** urb -> Pointer to USB request block
27689 +** regs -> Pointer to register-buffer for syscalls (see asm/ptrace.h)
27690 +************************************************************************
27692 +** This function is invoked upon termination of a USB transfer. As the
27693 +** USB device is only capable of sending a limited amount of bytes per
27694 +** transfer to the bulk-out endpoint, this routine checks if there are
27695 +** more bytes to send and triggers subsequent transfers. In case the
27696 +** transfer size exactly matches the maximum bulk-out size, it triggers
27697 +** a transfer of a null-frame, telling the card that this is it. Upon
27698 +** completion of a frame, it checks whether the Tx ringbuffer contains
27699 +** more data to send and invokes the Tx routines if this is the case.
27700 +** If there are no more occupied Tx descriptors, the Tx Mutex is unlocked
27701 +** and the network queue is switched back to life again.
27703 +** FIXME: unlike PCI code, we do not analyze tx rate used, retries, etc...
27704 +** Thus we have no automatic rate control in USB!
27707 +acx100usb_i_complete_tx(struct urb *urb, struct pt_regs *regs)
27709 + wlandevice_t *priv;
27711 + unsigned long flags;
27715 + if (!urb->context) {
27716 + printk(KERN_ERR "acx: error, NULL context in tx completion callback\n");
27717 + /* FIXME: real error-handling code must go here! */
27721 + tx = (usb_tx_t *)urb->context;
27724 + acx_lock(priv, flags);
27726 + /* TODO: we maybe need to check whether urb was unlinked
27727 + ** (happens on disconnect and close, see there). How? */
27729 + acxlog(L_USBRXTX, "RETURN TX (%p): status=%d size=%d\n",
27730 + tx, urb->status, urb->actual_length);
27732 + /* handle USB transfer errors */
27733 + switch (urb->status) {
27734 + case 0: /* No error */
27736 + case -ECONNRESET:
27738 + /* FIXME: real error-handling code here please */
27740 + printk(KERN_ERR "acx: tx error, urb status=%d\n", urb->status);
27741 + /* FIXME: real error-handling code here please */
27744 + /* free the URB and check for more data */
27749 + acx_unlock(priv, flags);
27755 +/***********************************************************************
27756 +** acx100usb_e_close():
27758 +** This function stops the network functionality of the interface (invoked
27759 +** when the user calls ifconfig <wlan> down). The tx queue is halted and
27760 +** the device is marked as down. In case there were any pending USB bulk
27761 +** transfers, these are unlinked (asynchronously). The module in-use count
27762 +** is also decreased in this function.
27765 +acx100usb_e_close(struct net_device *dev)
27767 + wlandevice_t *priv = netdev_priv(dev);
27768 + unsigned long flags;
27773 +#if WE_STILL_DONT_CARE_ABOUT_IT
27774 + /* Transmit a disassociate frame */
27776 + acx_l_transmit_disassoc(priv, &client);
27781 + * We get the sem *after* FLUSH to avoid a deadlock.
27782 + * See pci.c:acx_s_down() for deails.
27784 + FLUSH_SCHEDULED_WORK();
27785 + acx_sem_lock(priv);
27787 + /* stop the transmit queue, mark the device as DOWN */
27788 + acx_lock(priv, flags);
27789 + acx_stop_queue(dev, "on iface stop");
27790 + CLEAR_BIT(priv->dev_state_mask, ACX_STATE_IFACE_UP);
27792 + /* I wonder if above is enough to prevent tx/rx callbacks
27793 + ** to start queue again? Like this:
27794 + ** complete_rx -> acx_l_process_rxbuf -> associated -> acx_start_queue()
27797 + /* stop pending rx/tx urb transfers */
27798 + for (i = 0; i < ACX100_USB_NUM_BULK_URBS; i++) {
27799 + acx_unlink_and_free_urb(priv->bulkrx_urbs[i]);
27800 + acx_unlink_and_free_urb(priv->usb_tx[i].urb);
27802 + acx_unlock(priv, flags);
27804 + /* disable rx and tx */
27805 + acx_s_issue_cmd(priv, ACX1xx_CMD_DISABLE_TX, NULL, 0);
27806 + acx_s_issue_cmd(priv, ACX1xx_CMD_DISABLE_RX, NULL, 0);
27808 + /* power down the device */
27809 + acx_s_issue_cmd(priv, ACX1xx_CMD_SLEEP, NULL, 0);
27811 + acx_sem_unlock(priv);
27813 + /* decrease module-in-use count (if necessary) */
27815 + WLAN_MOD_DEC_USE_COUNT;
27822 +/***************************************************************
27823 +** acxusb_l_alloc_tx
27824 +** Actually returns a usb_tx_t* ptr
27827 +acxusb_l_alloc_tx(wlandevice_t* priv)
27830 + usb_tx_t *tx = NULL;
27834 + for (i = 0; i < ACX100_USB_NUM_BULK_URBS; i++) {
27835 + if (!priv->usb_tx[i].busy) {
27836 + tx = &priv->usb_tx[i];
27841 + if (i >= ACX100_USB_NUM_BULK_URBS) {
27842 + printk("acx: tx buffers full\n");
27847 + return (tx_t*)tx;
27851 +/***************************************************************
27854 +acxusb_l_get_txbuf(wlandevice_t *priv, tx_t* tx_opaque)
27856 + usb_tx_t* tx = (usb_tx_t*)tx_opaque;
27857 + return &tx->bulkout.data;
27861 +/***************************************************************
27862 +** acxusb_l_tx_data
27864 +** Can be called from IRQ (rx -> (AP bridging or mgmt response) -> tx).
27865 +** Can be called from acx_i_start_xmit (data frames from net core).
27868 +acxusb_l_tx_data(wlandevice_t *priv, tx_t* tx_opaque, int wlanpkt_len)
27870 + struct usb_device *usbdev;
27871 + struct urb* txurb;
27873 + usb_txbuffer_t* txbuf;
27875 + wlan_hdr_t* whdr;
27876 + unsigned int outpipe;
27882 + tx = ((usb_tx_t *)tx_opaque);
27884 + txbuf = &tx->bulkout;
27885 + whdr = (wlan_hdr_t *)txbuf->data;
27888 + acxlog(L_DEBUG, "using buf#%d free=%d len=%d\n",
27889 + (int)(tx - priv->usb_tx),
27890 + priv->tx_free, wlanpkt_len);
27892 + switch (priv->mode) {
27893 + case ACX_MODE_0_ADHOC:
27894 + case ACX_MODE_3_AP:
27895 + clt = acx_l_sta_list_get(priv, whdr->a1);
27897 + case ACX_MODE_2_STA:
27898 + clt = priv->ap_client;
27900 + default: /* ACX_MODE_OFF, ACX_MODE_MONITOR */
27905 + if (unlikely(clt && !clt->rate_cur)) {
27906 + printk("acx: driver bug! bad ratemask\n");
27910 + /* used in tx cleanup routine for auto rate and accounting: */
27911 +//TODO: currently unused - fix that
27914 + rate100 = clt ? clt->rate_100 : priv->rate_bcast100;
27916 + /* fill the USB transfer header */
27917 + txbuf->desc = cpu_to_le16(USB_TXBUF_TXDESC);
27918 + txbuf->MPDUlen = cpu_to_le16(wlanpkt_len);
27919 + txbuf->ctrl1 = 0;
27920 + txbuf->ctrl2 = 0;
27921 + txbuf->hostData = cpu_to_le32(wlanpkt_len | (rate100 << 24));
27922 + if (1 == priv->preamble_cur)
27923 + SET_BIT(txbuf->ctrl1, DESC_CTL_SHORT_PREAMBLE);
27924 + SET_BIT(txbuf->ctrl1, DESC_CTL_FIRSTFRAG);
27925 + txbuf->txRate = rate100;
27926 + txbuf->index = 1;
27927 + txbuf->dataLength = cpu_to_le16(wlanpkt_len);
27929 + if ( (WF_FC_FTYPEi & whdr->fc) == WF_FTYPE_DATAi )
27930 + SET_BIT(txbuf->hostData, cpu_to_le32(USB_TXBUF_HD_ISDATA));
27931 + if (mac_is_directed(whdr->a1))
27932 + SET_BIT(txbuf->hostData, cpu_to_le32(USB_TXBUF_HD_DIRECTED));
27933 + else if (mac_is_bcast(whdr->a1))
27934 + SET_BIT(txbuf->hostData, cpu_to_le32(USB_TXBUF_HD_BROADCAST));
27936 + if (acx_debug & L_DATA) {
27937 + printk("dump of bulk out urb:\n");
27938 + acx_dump_bytes(txbuf, wlanpkt_len + USB_TXBUF_HDRSIZE);
27941 + if (txurb->status == -EINPROGRESS) {
27942 + printk("acx: trying to submit tx urb while already in progress\n");
27945 + /* now schedule the USB transfer */
27946 + usbdev = priv->usbdev;
27947 + outpipe = usb_sndbulkpipe(usbdev, priv->bulkoutep);
27948 +//can be removed, please try & test:
27951 + usb_fill_bulk_urb(txurb, usbdev, outpipe,
27952 + txbuf, /* dataptr */
27953 + wlanpkt_len + USB_TXBUF_HDRSIZE, /* size */
27954 + acx100usb_i_complete_tx, /* handler */
27955 + tx /* handler param */
27958 + txurb->transfer_flags = QUEUE_BULK|ZERO_PACKET;
27959 + ucode = submit_urb(txurb, GFP_ATOMIC);
27960 + acxlog(L_USBRXTX, "SUBMIT TX (%p): outpipe=0x%X buf=%p txsize=%d "
27961 + "errcode=%d\n", tx, outpipe, txbuf,
27962 + wlanpkt_len + USB_TXBUF_HDRSIZE, ucode);
27965 + printk(KERN_ERR "acx: submit_urb() error=%d txsize=%d\n",
27966 + ucode, wlanpkt_len + USB_TXBUF_HDRSIZE);
27968 + /* on error, just mark the frame as done and update
27969 + ** the statistics
27971 + priv->stats.tx_errors++;
27980 +/***********************************************************************
27982 +static struct net_device_stats*
27983 +acx_e_get_stats(netdevice_t *dev)
27985 + wlandevice_t *priv = netdev_priv(dev);
27986 + return &priv->stats;
27990 +/***********************************************************************
27992 +static struct iw_statistics*
27993 +acx_e_get_wireless_stats(netdevice_t *dev)
27995 + wlandevice_t *priv = netdev_priv(dev);
27998 + return &priv->wstats;
28002 +/***********************************************************************
28005 +acx100usb_i_set_rx_mode(struct net_device *dev)
28010 +/***********************************************************************
28012 +#ifdef HAVE_TX_TIMEOUT
28014 +acx100usb_i_tx_timeout(struct net_device *dev)
28016 + wlandevice_t *priv = netdev_priv(dev);
28017 + unsigned long flags;
28022 + acx_lock(priv, flags);
28023 + /* unlink the URBs */
28024 + for (i = 0; i < ACX100_USB_NUM_BULK_URBS; i++) {
28025 + if (priv->usb_tx[i].urb->status == -EINPROGRESS)
28026 + usb_unlink_urb(priv->usb_tx[i].urb);
28028 + /* TODO: stats update */
28029 + acx_unlock(priv, flags);
28036 +/***********************************************************************
28039 +** This function is invoked upon loading of the kernel module.
28040 +** It registers itself at the kernel's USB subsystem.
28042 +** Returns: Errorcode on failure, 0 on success
28045 +acxusb_e_init_module(void)
28047 + acxlog(L_INIT, "USB module " WLAN_RELEASE " initialized, "
28048 + "probing for devices...\n");
28049 + return usb_register(&acx100usb_driver);
28054 +/***********************************************************************
28055 +** cleanup_module():
28057 +** This function is invoked as last step of the module unloading. It simply
28058 +** deregisters this module at the kernel's USB subsystem.
28061 +acxusb_e_cleanup_module()
28063 + usb_deregister(&acx100usb_driver);
28067 +/***********************************************************************
28074 +dump_device(struct usb_device *usbdev)
28077 + struct usb_config_descriptor *cd;
28079 + printk("acx device dump:\n");
28080 + printk(" devnum: %d\n", usbdev->devnum);
28081 + printk(" speed: %d\n", usbdev->speed);
28082 + printk(" tt: 0x%X\n", (unsigned int)(usbdev->tt));
28083 + printk(" ttport: %d\n", (unsigned int)(usbdev->ttport));
28084 + printk(" toggle[0]: 0x%X toggle[1]: 0x%X\n", (unsigned int)(usbdev->toggle[0]), (unsigned int)(usbdev->toggle[1]));
28085 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 8)
28086 + /* halted removed in 2.6.9-rc1 */
28087 + /* DOH, Canbreak... err... Mandrake decided to do their very own very
28088 + * special version "2.6.8.1" which already includes this change, so we
28089 + * need to blacklist that version already (i.e. 2.6.8) */
28090 + printk(" halted[0]: 0x%X halted[1]: 0x%X\n", usbdev->halted[0], usbdev->halted[1]);
28092 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11)
28093 + /* This saw a change after 2.6.10 */
28094 + printk(" ep_in wMaxPacketSize: ");
28095 + for (i = 0; i < 16; ++i)
28096 + printk("%d ", usbdev->ep_in[i]->desc.wMaxPacketSize);
28098 + printk(" ep_out wMaxPacketSize: ");
28099 + for (i = 0; i < 15; ++i)
28100 + printk("%d ", usbdev->ep_out[i]->desc.wMaxPacketSize);
28103 + printk(" epmaxpacketin: ");
28104 + for (i = 0; i < 16; i++)
28105 + printk("%d ", usbdev->epmaxpacketin[i]);
28107 + printk(" epmaxpacketout: ");
28108 + for (i = 0; i < 16; i++)
28109 + printk("%d ", usbdev->epmaxpacketout[i]);
28112 + printk(" parent: 0x%X\n", (unsigned int)usbdev->parent);
28113 + printk(" bus: 0x%X\n", (unsigned int)usbdev->bus);
28115 + printk(" configs: ");
28116 + for (i = 0; i < usbdev->descriptor.bNumConfigurations; i++)
28117 + printk("0x%X ", usbdev->config[i]);
28120 + printk(" actconfig: %p\n", usbdev->actconfig);
28121 + dump_device_descriptor(&usbdev->descriptor);
28123 + cd = &usbdev->config->desc;
28124 + dump_config_descriptor(cd);
28128 +/***********************************************************************
28131 +dump_config_descriptor(struct usb_config_descriptor *cd)
28133 + printk("Configuration Descriptor:\n");
28135 + printk("NULL\n");
28138 + printk(" bLength: %d (0x%X)\n", cd->bLength, cd->bLength);
28139 + printk(" bDescriptorType: %d (0x%X)\n", cd->bDescriptorType, cd->bDescriptorType);
28140 + printk(" bNumInterfaces: %d (0x%X)\n", cd->bNumInterfaces, cd->bNumInterfaces);
28141 + printk(" bConfigurationValue: %d (0x%X)\n", cd->bConfigurationValue, cd->bConfigurationValue);
28142 + printk(" iConfiguration: %d (0x%X)\n", cd->iConfiguration, cd->iConfiguration);
28143 + printk(" bmAttributes: %d (0x%X)\n", cd->bmAttributes, cd->bmAttributes);
28144 + /* printk(" MaxPower: %d (0x%X)\n", cd->bMaxPower, cd->bMaxPower); */
28149 +dump_device_descriptor(struct usb_device_descriptor *dd)
28151 + printk("Device Descriptor:\n");
28153 + printk("NULL\n");
28156 + printk(" bLength: %d (0x%X)\n", dd->bLength, dd->bLength);
28157 + printk(" bDescriptortype: %d (0x%X)\n", dd->bDescriptorType, dd->bDescriptorType);
28158 + printk(" bcdUSB: %d (0x%X)\n", dd->bcdUSB, dd->bcdUSB);
28159 + printk(" bDeviceClass: %d (0x%X)\n", dd->bDeviceClass, dd->bDeviceClass);
28160 + printk(" bDeviceSubClass: %d (0x%X)\n", dd->bDeviceSubClass, dd->bDeviceSubClass);
28161 + printk(" bDeviceProtocol: %d (0x%X)\n", dd->bDeviceProtocol, dd->bDeviceProtocol);
28162 + printk(" bMaxPacketSize0: %d (0x%X)\n", dd->bMaxPacketSize0, dd->bMaxPacketSize0);
28163 + printk(" idVendor: %d (0x%X)\n", dd->idVendor, dd->idVendor);
28164 + printk(" idProduct: %d (0x%X)\n", dd->idProduct, dd->idProduct);
28165 + printk(" bcdDevice: %d (0x%X)\n", dd->bcdDevice, dd->bcdDevice);
28166 + printk(" iManufacturer: %d (0x%X)\n", dd->iManufacturer, dd->iManufacturer);
28167 + printk(" iProduct: %d (0x%X)\n", dd->iProduct, dd->iProduct);
28168 + printk(" iSerialNumber: %d (0x%X)\n", dd->iSerialNumber, dd->iSerialNumber);
28169 + printk(" bNumConfigurations: %d (0x%X)\n", dd->bNumConfigurations, dd->bNumConfigurations);
28171 +#endif /* UNUSED */
28173 +#endif /* ACX_DEBUG */
28174 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
28175 --- linux-2.6.14-omap2/drivers/net/wireless/tiacx/wlan.c 1970-01-01 02:00:00.000000000 +0200
28176 +++ linux-h6300-omap2-2.6.14.3/drivers/net/wireless/tiacx/wlan.c 2005-09-28 23:54:23.000000000 +0300
28178 +/***********************************************************************
28179 +** Copyright (C) 2003 ACX100 Open Source Project
28181 +** The contents of this file are subject to the Mozilla Public
28182 +** License Version 1.1 (the "License"); you may not use this file
28183 +** except in compliance with the License. You may obtain a copy of
28184 +** the License at http://www.mozilla.org/MPL/
28186 +** Software distributed under the License is distributed on an "AS
28187 +** IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
28188 +** implied. See the License for the specific language governing
28189 +** rights and limitations under the License.
28191 +** Alternatively, the contents of this file may be used under the
28192 +** terms of the GNU Public License version 2 (the "GPL"), in which
28193 +** case the provisions of the GPL are applicable instead of the
28194 +** above. If you wish to allow the use of your version of this file
28195 +** only under the terms of the GPL and not to allow others to use
28196 +** your version of this file under the MPL, indicate your decision
28197 +** by deleting the provisions above and replace them with the notice
28198 +** and other provisions required by the GPL. If you do not delete
28199 +** the provisions above, a recipient may use your version of this
28200 +** file under either the MPL or the GPL.
28201 +** ---------------------------------------------------------------------
28202 +** Inquiries regarding the ACX100 Open Source Project can be
28203 +** made directly to:
28205 +** acx100-users@lists.sf.net
28206 +** http://acx100.sf.net
28207 +** ---------------------------------------------------------------------
28210 +/***********************************************************************
28211 +** This code is based on elements which are
28212 +** Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
28213 +** info@linux-wlan.com
28214 +** http://www.linux-wlan.com
28217 +#include <linux/config.h>
28218 +#include <linux/version.h>
28220 +#include <linux/types.h>
28221 +#include <linux/if_arp.h>
28222 +#include <linux/wireless.h>
28223 +#if WIRELESS_EXT >= 13
28224 +#include <net/iw_handler.h>
28230 +/***********************************************************************
28232 +#define LOG_BAD_EID(hdr,len,ie_ptr) acx_log_bad_eid(hdr, len, ((wlan_ie_t*)ie_ptr))
28234 +#define IE_EID(ie_ptr) (((wlan_ie_t*)(ie_ptr))->eid)
28235 +#define IE_LEN(ie_ptr) (((wlan_ie_t*)(ie_ptr))->len)
28236 +#define OFFSET(hdr,off) (WLAN_HDR_A3_DATAP(hdr) + (off))
28239 +/***********************************************************************
28240 +** wlan_mgmt_decode_XXX
28242 +** Given a complete frame in f->hdr, sets the pointers in f to
28243 +** the areas that correspond to the parts of the frame.
28246 +** 1) f->len and f->hdr are already set
28247 +** 2) f->len is the length of the MAC header + data, the FCS
28248 +** is NOT included
28249 +** 3) all members except len and hdr are zero
28251 +** f frame structure
28257 +** frame structure members are pointing at their
28258 +** respective portions of the frame buffer.
28261 +wlan_mgmt_decode_beacon(wlan_fr_beacon_t * f)
28264 + u8 *end = (u8*)f->hdr + f->len;
28266 + f->type = WLAN_FSTYPE_BEACON;
28268 + /*-- Fixed Fields ----*/
28269 + f->ts = (u64 *) OFFSET(f->hdr, WLAN_BEACON_OFF_TS);
28270 + f->bcn_int = (u16 *) OFFSET(f->hdr, WLAN_BEACON_OFF_BCN_INT);
28271 + f->cap_info = (u16 *) OFFSET(f->hdr, WLAN_BEACON_OFF_CAPINFO);
28273 + /*-- Information elements */
28274 + ie_ptr = OFFSET(f->hdr, WLAN_BEACON_OFF_SSID);
28275 + while (ie_ptr < end) {
28276 + switch (IE_EID(ie_ptr)) {
28277 + case WLAN_EID_SSID:
28278 + f->ssid = (wlan_ie_ssid_t *) ie_ptr;
28280 + case WLAN_EID_SUPP_RATES:
28281 + f->supp_rates = (wlan_ie_supp_rates_t *) ie_ptr;
28283 + case WLAN_EID_EXT_RATES:
28284 + f->ext_rates = (wlan_ie_supp_rates_t *) ie_ptr;
28286 + case WLAN_EID_FH_PARMS:
28287 + f->fh_parms = (wlan_ie_fh_parms_t *) ie_ptr;
28289 + case WLAN_EID_DS_PARMS:
28290 + f->ds_parms = (wlan_ie_ds_parms_t *) ie_ptr;
28292 + case WLAN_EID_CF_PARMS:
28293 + f->cf_parms = (wlan_ie_cf_parms_t *) ie_ptr;
28295 + case WLAN_EID_IBSS_PARMS:
28296 + f->ibss_parms = (wlan_ie_ibss_parms_t *) ie_ptr;
28298 + case WLAN_EID_TIM:
28299 + f->tim = (wlan_ie_tim_t *) ie_ptr;
28301 + case WLAN_EID_ERP_INFO:
28302 + f->erp = (wlan_ie_erp_t *) ie_ptr;
28304 + case WLAN_EID_COUNTRY:
28305 + /* was seen: 07 06 47 42 20 01 0D 14 */
28306 + case WLAN_EID_NONERP:
28307 + /* was seen from WRT54GS with OpenWrt: 2F 01 07 */
28308 + case WLAN_EID_GENERIC:
28309 + /* WPA: hostap code:
28310 + if (pos[1] >= 4 &&
28311 + pos[2] == 0x00 && pos[3] == 0x50 &&
28312 + pos[4] == 0xf2 && pos[5] == 1) {
28314 + wpa_len = pos[1] + 2;
28316 + TI x4 mode: seen DD 04 08 00 28 00
28317 + (08 00 28 is TI's OUI)
28318 + last byte is probably 0/1 - disabled/enabled
28320 + case WLAN_EID_RSN:
28321 + /* hostap does something with it:
28323 + rsn_len = pos[1] + 2;
28327 + LOG_BAD_EID(f->hdr, f->len, ie_ptr);
28330 + ie_ptr = ie_ptr + 2 + IE_LEN(ie_ptr);
28336 +void wlan_mgmt_decode_ibssatim(wlan_fr_ibssatim_t * f)
28338 + f->type = WLAN_FSTYPE_ATIM;
28339 + /*-- Fixed Fields ----*/
28340 + /*-- Information elements */
28342 +#endif /* UNUSED */
28345 +wlan_mgmt_decode_disassoc(wlan_fr_disassoc_t * f)
28347 + f->type = WLAN_FSTYPE_DISASSOC;
28349 + /*-- Fixed Fields ----*/
28350 + f->reason = (u16 *) OFFSET(f->hdr, WLAN_DISASSOC_OFF_REASON);
28352 + /*-- Information elements */
28357 +wlan_mgmt_decode_assocreq(wlan_fr_assocreq_t * f)
28360 + u8 *end = (u8*)f->hdr + f->len;
28363 + f->type = WLAN_FSTYPE_ASSOCREQ;
28365 + /*-- Fixed Fields ----*/
28366 + f->cap_info = (u16 *) OFFSET(f->hdr, WLAN_ASSOCREQ_OFF_CAP_INFO);
28367 + f->listen_int = (u16 *) OFFSET(f->hdr, WLAN_ASSOCREQ_OFF_LISTEN_INT);
28369 + /*-- Information elements */
28370 + ie_ptr = OFFSET(f->hdr, WLAN_ASSOCREQ_OFF_SSID);
28371 + while (ie_ptr < end) {
28372 + switch (IE_EID(ie_ptr)) {
28373 + case WLAN_EID_SSID:
28374 + f->ssid = (wlan_ie_ssid_t *) ie_ptr;
28376 + case WLAN_EID_SUPP_RATES:
28377 + f->supp_rates = (wlan_ie_supp_rates_t *) ie_ptr;
28379 + case WLAN_EID_EXT_RATES:
28380 + f->ext_rates = (wlan_ie_supp_rates_t *) ie_ptr;
28383 + LOG_BAD_EID(f->hdr, f->len, ie_ptr);
28386 + ie_ptr = ie_ptr + 2 + IE_LEN(ie_ptr);
28392 +wlan_mgmt_decode_assocresp(wlan_fr_assocresp_t * f)
28394 + f->type = WLAN_FSTYPE_ASSOCRESP;
28396 + /*-- Fixed Fields ----*/
28397 + f->cap_info = (u16 *) OFFSET(f->hdr, WLAN_ASSOCRESP_OFF_CAP_INFO);
28398 + f->status = (u16 *) OFFSET(f->hdr, WLAN_ASSOCRESP_OFF_STATUS);
28399 + f->aid = (u16 *) OFFSET(f->hdr, WLAN_ASSOCRESP_OFF_AID);
28401 + /*-- Information elements */
28402 + f->supp_rates = (wlan_ie_supp_rates_t *)
28403 + OFFSET(f->hdr, WLAN_ASSOCRESP_OFF_SUPP_RATES);
28408 +wlan_mgmt_decode_reassocreq(wlan_fr_reassocreq_t * f)
28411 + u8 *end = (u8*)f->hdr + f->len;
28413 + f->type = WLAN_FSTYPE_REASSOCREQ;
28415 + /*-- Fixed Fields ----*/
28416 + f->cap_info = (u16 *) OFFSET(f->hdr, WLAN_REASSOCREQ_OFF_CAP_INFO);
28417 + f->listen_int = (u16 *) OFFSET(f->hdr, WLAN_REASSOCREQ_OFF_LISTEN_INT);
28418 + f->curr_ap = (u8 *) OFFSET(f->hdr, WLAN_REASSOCREQ_OFF_CURR_AP);
28420 + /*-- Information elements */
28421 + ie_ptr = OFFSET(f->hdr, WLAN_REASSOCREQ_OFF_SSID);
28422 + while (ie_ptr < end) {
28423 + switch (IE_EID(ie_ptr)) {
28424 + case WLAN_EID_SSID:
28425 + f->ssid = (wlan_ie_ssid_t *) ie_ptr;
28427 + case WLAN_EID_SUPP_RATES:
28428 + f->supp_rates = (wlan_ie_supp_rates_t *) ie_ptr;
28430 + case WLAN_EID_EXT_RATES:
28431 + f->ext_rates = (wlan_ie_supp_rates_t *) ie_ptr;
28434 + LOG_BAD_EID(f->hdr, f->len, ie_ptr);
28437 + ie_ptr = ie_ptr + 2 + IE_LEN(ie_ptr);
28443 +wlan_mgmt_decode_reassocresp(wlan_fr_reassocresp_t * f)
28445 + f->type = WLAN_FSTYPE_REASSOCRESP;
28447 + /*-- Fixed Fields ----*/
28448 + f->cap_info = (u16 *) OFFSET(f->hdr, WLAN_REASSOCRESP_OFF_CAP_INFO);
28449 + f->status = (u16 *) OFFSET(f->hdr, WLAN_REASSOCRESP_OFF_STATUS);
28450 + f->aid = (u16 *) OFFSET(f->hdr, WLAN_REASSOCRESP_OFF_AID);
28452 + /*-- Information elements */
28453 + f->supp_rates = (wlan_ie_supp_rates_t *)
28454 + OFFSET(f->hdr, WLAN_REASSOCRESP_OFF_SUPP_RATES);
28459 +wlan_mgmt_decode_probereq(wlan_fr_probereq_t * f)
28462 + u8 *end = (u8*)f->hdr + f->len;
28464 + f->type = WLAN_FSTYPE_PROBEREQ;
28466 + /*-- Fixed Fields ----*/
28468 + /*-- Information elements */
28469 + ie_ptr = OFFSET(f->hdr, WLAN_PROBEREQ_OFF_SSID);
28470 + while (ie_ptr < end) {
28471 + switch (IE_EID(ie_ptr)) {
28472 + case WLAN_EID_SSID:
28473 + f->ssid = (wlan_ie_ssid_t *) ie_ptr;
28475 + case WLAN_EID_SUPP_RATES:
28476 + f->supp_rates = (wlan_ie_supp_rates_t *) ie_ptr;
28478 + case WLAN_EID_EXT_RATES:
28479 + f->ext_rates = (wlan_ie_supp_rates_t *) ie_ptr;
28482 + LOG_BAD_EID(f->hdr, f->len, ie_ptr);
28485 + ie_ptr = ie_ptr + 2 + IE_LEN(ie_ptr);
28490 +/* TODO: decoding of beacon and proberesp can be merged (similar structure) */
28492 +wlan_mgmt_decode_proberesp(wlan_fr_proberesp_t * f)
28495 + u8 *end = (u8*)f->hdr + f->len;
28497 + f->type = WLAN_FSTYPE_PROBERESP;
28499 + /*-- Fixed Fields ----*/
28500 + f->ts = (u64 *) OFFSET(f->hdr, WLAN_PROBERESP_OFF_TS);
28501 + f->bcn_int = (u16 *) OFFSET(f->hdr, WLAN_PROBERESP_OFF_BCN_INT);
28502 + f->cap_info = (u16 *) OFFSET(f->hdr, WLAN_PROBERESP_OFF_CAP_INFO);
28504 + /*-- Information elements */
28505 + ie_ptr = OFFSET(f->hdr, WLAN_PROBERESP_OFF_SSID);
28506 + while (ie_ptr < end) {
28507 + switch (IE_EID(ie_ptr)) {
28508 + case WLAN_EID_SSID:
28509 + f->ssid = (wlan_ie_ssid_t *) ie_ptr;
28511 + case WLAN_EID_SUPP_RATES:
28512 + f->supp_rates = (wlan_ie_supp_rates_t *) ie_ptr;
28514 + case WLAN_EID_EXT_RATES:
28515 + f->ext_rates = (wlan_ie_supp_rates_t *) ie_ptr;
28517 + case WLAN_EID_FH_PARMS:
28518 + f->fh_parms = (wlan_ie_fh_parms_t *) ie_ptr;
28520 + case WLAN_EID_DS_PARMS:
28521 + f->ds_parms = (wlan_ie_ds_parms_t *) ie_ptr;
28523 + case WLAN_EID_CF_PARMS:
28524 + f->cf_parms = (wlan_ie_cf_parms_t *) ie_ptr;
28526 + case WLAN_EID_IBSS_PARMS:
28527 + f->ibss_parms = (wlan_ie_ibss_parms_t *) ie_ptr;
28530 + LOG_BAD_EID(f->hdr, f->len, ie_ptr);
28534 + ie_ptr = ie_ptr + 2 + IE_LEN(ie_ptr);
28540 +wlan_mgmt_decode_authen(wlan_fr_authen_t * f)
28543 + u8 *end = (u8*)f->hdr + f->len;
28545 + f->type = WLAN_FSTYPE_AUTHEN;
28547 + /*-- Fixed Fields ----*/
28548 + f->auth_alg = (u16 *) OFFSET(f->hdr, WLAN_AUTHEN_OFF_AUTH_ALG);
28549 + f->auth_seq = (u16 *) OFFSET(f->hdr, WLAN_AUTHEN_OFF_AUTH_SEQ);
28550 + f->status = (u16 *) OFFSET(f->hdr, WLAN_AUTHEN_OFF_STATUS);
28552 + /*-- Information elements */
28553 + ie_ptr = OFFSET(f->hdr, WLAN_AUTHEN_OFF_CHALLENGE);
28554 + if ((ie_ptr < end) && (IE_EID(ie_ptr) == WLAN_EID_CHALLENGE)) {
28555 + f->challenge = (wlan_ie_challenge_t *) ie_ptr;
28561 +wlan_mgmt_decode_deauthen(wlan_fr_deauthen_t * f)
28563 + f->type = WLAN_FSTYPE_DEAUTHEN;
28565 + /*-- Fixed Fields ----*/
28566 + f->reason = (u16 *) OFFSET(f->hdr, WLAN_DEAUTHEN_OFF_REASON);
28568 + /*-- Information elements */
28570 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
28571 --- linux-2.6.14-omap2/drivers/net/wireless/tiacx/wlan_compat.h 1970-01-01 02:00:00.000000000 +0200
28572 +++ linux-h6300-omap2-2.6.14.3/drivers/net/wireless/tiacx/wlan_compat.h 2005-09-28 23:54:23.000000000 +0300
28574 +/***********************************************************************
28575 +** Copyright (C) 2003 ACX100 Open Source Project
28577 +** The contents of this file are subject to the Mozilla Public
28578 +** License Version 1.1 (the "License"); you may not use this file
28579 +** except in compliance with the License. You may obtain a copy of
28580 +** the License at http://www.mozilla.org/MPL/
28582 +** Software distributed under the License is distributed on an "AS
28583 +** IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
28584 +** implied. See the License for the specific language governing
28585 +** rights and limitations under the License.
28587 +** Alternatively, the contents of this file may be used under the
28588 +** terms of the GNU Public License version 2 (the "GPL"), in which
28589 +** case the provisions of the GPL are applicable instead of the
28590 +** above. If you wish to allow the use of your version of this file
28591 +** only under the terms of the GPL and not to allow others to use
28592 +** your version of this file under the MPL, indicate your decision
28593 +** by deleting the provisions above and replace them with the notice
28594 +** and other provisions required by the GPL. If you do not delete
28595 +** the provisions above, a recipient may use your version of this
28596 +** file under either the MPL or the GPL.
28597 +** ---------------------------------------------------------------------
28598 +** Inquiries regarding the ACX100 Open Source Project can be
28599 +** made directly to:
28601 +** acx100-users@lists.sf.net
28602 +** http://acx100.sf.net
28603 +** ---------------------------------------------------------------------
28606 +/***********************************************************************
28607 +** This code is based on elements which are
28608 +** Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
28609 +** info@linux-wlan.com
28610 +** http://www.linux-wlan.com
28613 +/*=============================================================*/
28614 +/*------ Establish Platform Identity --------------------------*/
28615 +/*=============================================================*/
28617 +/* WLAN_CPU_FAMILY */
28618 +#define WLAN_Ix86 1
28619 +#define WLAN_PPC 2
28620 +#define WLAN_Ix96 3
28621 +#define WLAN_ARM 4
28622 +#define WLAN_ALPHA 5
28623 +#define WLAN_MIPS 6
28624 +#define WLAN_HPPA 7
28625 +#define WLAN_SPARC 8
28627 +#define WLAN_x86_64 10
28628 +/* WLAN_CPU_CORE */
28629 +#define WLAN_I386CORE 1
28630 +#define WLAN_PPCCORE 2
28631 +#define WLAN_I296 3
28632 +#define WLAN_ARMCORE 4
28633 +#define WLAN_ALPHACORE 5
28634 +#define WLAN_MIPSCORE 6
28635 +#define WLAN_HPPACORE 7
28636 +/* WLAN_CPU_PART */
28637 +#define WLAN_I386PART 1
28638 +#define WLAN_MPC860 2
28639 +#define WLAN_MPC823 3
28640 +#define WLAN_I296SA 4
28641 +#define WLAN_PPCPART 5
28642 +#define WLAN_ARMPART 6
28643 +#define WLAN_ALPHAPART 7
28644 +#define WLAN_MIPSPART 8
28645 +#define WLAN_HPPAPART 9
28646 +/* WLAN_SYSARCH */
28647 +#define WLAN_PCAT 1
28648 +#define WLAN_MBX 2
28649 +#define WLAN_RPX 3
28650 +#define WLAN_LWARCH 4
28651 +#define WLAN_PMAC 5
28652 +#define WLAN_SKIFF 6
28653 +#define WLAN_BITSY 7
28654 +#define WLAN_ALPHAARCH 7
28655 +#define WLAN_MIPSARCH 9
28656 +#define WLAN_HPPAARCH 10
28657 +/* WLAN_HOSTIF (generally set on the command line, not detected) */
28658 +#define WLAN_PCMCIA 1
28659 +#define WLAN_ISA 2
28660 +#define WLAN_PCI 3
28661 +#define WLAN_USB 4
28662 +#define WLAN_PLX 5
28664 +/* Note: the PLX HOSTIF above refers to some vendors implementations for */
28665 +/* PCI. It's a PLX chip that is a PCI to PCMCIA adapter, but it */
28666 +/* isn't a real PCMCIA host interface adapter providing all the */
28667 +/* card&socket services. */
28669 +#ifdef __powerpc__
28675 +#if (defined(CONFIG_PPC) || defined(CONFIG_8xx))
28681 +#if defined(__x86_64__)
28682 + #define WLAN_CPU_FAMILY WLAN_x86_64
28683 + #define WLAN_SYSARCH WLAN_PCAT
28684 +#elif defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__)
28685 + #define WLAN_CPU_FAMILY WLAN_Ix86
28686 + #define WLAN_CPU_CORE WLAN_I386CORE
28687 + #define WLAN_CPU_PART WLAN_I386PART
28688 + #define WLAN_SYSARCH WLAN_PCAT
28689 +#elif defined(__ppc__)
28690 + #define WLAN_CPU_FAMILY WLAN_PPC
28691 + #define WLAN_CPU_CORE WLAN_PPCCORE
28692 + #if defined(CONFIG_MBX)
28693 + #define WLAN_CPU_PART WLAN_MPC860
28694 + #define WLAN_SYSARCH WLAN_MBX
28695 + #elif defined(CONFIG_RPXLITE)
28696 + #define WLAN_CPU_PART WLAN_MPC823
28697 + #define WLAN_SYSARCH WLAN_RPX
28698 + #elif defined(CONFIG_RPXCLASSIC)
28699 + #define WLAN_CPU_PART WLAN_MPC860
28700 + #define WLAN_SYSARCH WLAN_RPX
28702 + #define WLAN_CPU_PART WLAN_PPCPART
28703 + #define WLAN_SYSARCH WLAN_PMAC
28705 +#elif defined(__arm__)
28706 + #define WLAN_CPU_FAMILY WLAN_ARM
28707 + #define WLAN_CPU_CORE WLAN_ARMCORE
28708 + #define WLAN_CPU_PART WLAN_ARM_PART
28709 + #define WLAN_SYSARCH WLAN_SKIFF
28710 +#elif defined(__alpha__)
28711 + #define WLAN_CPU_FAMILY WLAN_ALPHA
28712 + #define WLAN_CPU_CORE WLAN_ALPHACORE
28713 + #define WLAN_CPU_PART WLAN_ALPHAPART
28714 + #define WLAN_SYSARCH WLAN_ALPHAARCH
28715 +#elif defined(__mips__)
28716 + #define WLAN_CPU_FAMILY WLAN_MIPS
28717 + #define WLAN_CPU_CORE WLAN_MIPSCORE
28718 + #define WLAN_CPU_PART WLAN_MIPSPART
28719 + #define WLAN_SYSARCH WLAN_MIPSARCH
28720 +#elif defined(__hppa__)
28721 + #define WLAN_CPU_FAMILY WLAN_HPPA
28722 + #define WLAN_CPU_CORE WLAN_HPPACORE
28723 + #define WLAN_CPU_PART WLAN_HPPAPART
28724 + #define WLAN_SYSARCH WLAN_HPPAARCH
28725 +#elif defined(__sparc__)
28726 + #define WLAN_CPU_FAMILY WLAN_SPARC
28727 + #define WLAN_SYSARCH WLAN_SPARC
28728 +#elif defined(__sh__)
28729 + #define WLAN_CPU_FAMILY WLAN_SH
28730 + #define WLAN_SYSARCH WLAN_SHARCH
28731 + #ifndef __LITTLE_ENDIAN__
28732 + #define __LITTLE_ENDIAN__
28735 + #error "No CPU identified!"
28739 + Some big endian machines implicitly do all I/O in little endian mode.
28742 + Linux/PPC on PowerMacs (PCI)
28743 + Arm/Intel Xscale (PCI)
28745 + This may also affect PLX boards and other BE &| PPC platforms;
28746 + as new ones are discovered, add them below.
28749 +#if ((WLAN_SYSARCH == WLAN_SKIFF) || (WLAN_SYSARCH == WLAN_PMAC))
28750 +#define REVERSE_ENDIAN
28753 +/*=============================================================*/
28754 +/*------ Hardware Portability Macros --------------------------*/
28755 +/*=============================================================*/
28756 +#if (WLAN_CPU_FAMILY == WLAN_PPC)
28757 +#define wlan_inw(a) in_be16((unsigned short *)((a)+_IO_BASE))
28758 +#define wlan_inw_le16_to_cpu(a) inw((a))
28759 +#define wlan_outw(v,a) out_be16((unsigned short *)((a)+_IO_BASE), (v))
28760 +#define wlan_outw_cpu_to_le16(v,a) outw((v),(a))
28762 +#define wlan_inw(a) inw((a))
28763 +#define wlan_inw_le16_to_cpu(a) __cpu_to_le16(inw((a)))
28764 +#define wlan_outw(v,a) outw((v),(a))
28765 +#define wlan_outw_cpu_to_le16(v,a) outw(__cpu_to_le16((v)),(a))
28768 +/*=============================================================*/
28769 +/*------ Bit settings -----------------------------------------*/
28770 +/*=============================================================*/
28771 +#define ieee2host16(n) __le16_to_cpu(n)
28772 +#define ieee2host32(n) __le32_to_cpu(n)
28773 +#define host2ieee16(n) __cpu_to_le16(n)
28774 +#define host2ieee32(n) __cpu_to_le32(n)
28776 +/* for constants */
28777 +#ifdef __LITTLE_ENDIAN
28778 + #define IEEE16(a,n) a = n, a##i = n,
28780 + #ifdef __BIG_ENDIAN
28781 + /* shifts would produce gcc warnings. Oh well... */
28782 + #define IEEE16(a,n) a = n, a##i = ((n&0xff)*256 + ((n&0xff00)/256)),
28784 + #error give me endianness or give me death
28788 +/*=============================================================*/
28789 +/*------ Compiler Portability Macros --------------------------*/
28790 +/*=============================================================*/
28791 +#define __WLAN_ATTRIB_PACK__ __attribute__ ((packed))
28792 +#define __WLAN_PRAGMA_PACK1__
28793 +#define __WLAN_PRAGMA_PACKDFLT__
28795 +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,38))
28796 + typedef struct device netdevice_t;
28797 +#elif (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,4))
28798 + typedef struct net_device netdevice_t;
28800 + #undef netdevice_t
28801 + typedef struct net_device netdevice_t;
28804 +#ifdef WIRELESS_EXT
28805 +#if (WIRELESS_EXT < 13)
28806 +struct iw_request_info {
28807 + __u16 cmd; /* Wireless Extension command */
28808 + __u16 flags; /* More to come ;-) */
28813 +/* Interrupt handler backwards compatibility stuff */
28816 +#define IRQ_HANDLED
28817 +typedef void irqreturn_t;
28821 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,41) /* more or less */
28822 +#define WLAN_MOD_INC_USE_COUNT MOD_INC_USE_COUNT
28823 +#define WLAN_MOD_DEC_USE_COUNT MOD_DEC_USE_COUNT
28825 +#define WLAN_MOD_INC_USE_COUNT
28826 +#define WLAN_MOD_DEC_USE_COUNT
28829 +#ifndef ARPHRD_IEEE80211_PRISM
28830 +#define ARPHRD_IEEE80211_PRISM 802
28833 +#define ETH_P_80211_RAW (ETH_P_ECONET + 1)
28835 +/*============================================================================*
28837 + *============================================================================*/
28838 +#define WLAN_IEEE_OUI_LEN 3
28840 +#define WLAN_ETHHDR_LEN 14
28841 +#define WLAN_ETHCONV_ENCAP 1
28842 +#define WLAN_ETHCONV_RFC1042 2
28843 +#define WLAN_ETHCONV_8021h 3
28844 +#define WLAN_MIN_ETHFRM_LEN 60
28845 +#define WLAN_MAX_ETHFRM_LEN 1514
28848 +/*============================================================================*
28850 + *============================================================================*/
28852 +/* local ether header type */
28853 +typedef struct wlan_ethhdr {
28854 + u8 daddr[ETH_ALEN] __WLAN_ATTRIB_PACK__;
28855 + u8 saddr[ETH_ALEN] __WLAN_ATTRIB_PACK__;
28856 + u16 type __WLAN_ATTRIB_PACK__;
28859 +/* local llc header type */
28860 +typedef struct wlan_llc {
28861 + u8 dsap __WLAN_ATTRIB_PACK__;
28862 + u8 ssap __WLAN_ATTRIB_PACK__;
28863 + u8 ctl __WLAN_ATTRIB_PACK__;
28866 +/* local snap header type */
28867 +typedef struct wlan_snap {
28868 + u8 oui[WLAN_IEEE_OUI_LEN] __WLAN_ATTRIB_PACK__;
28869 + u16 type __WLAN_ATTRIB_PACK__;
28871 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
28872 --- linux-2.6.14-omap2/drivers/net/wireless/tiacx/wlan_hdr.h 1970-01-01 02:00:00.000000000 +0200
28873 +++ linux-h6300-omap2-2.6.14.3/drivers/net/wireless/tiacx/wlan_hdr.h 2005-09-28 23:54:23.000000000 +0300
28875 +/***********************************************************************
28876 +** Copyright (C) 2003 ACX100 Open Source Project
28878 +** The contents of this file are subject to the Mozilla Public
28879 +** License Version 1.1 (the "License"); you may not use this file
28880 +** except in compliance with the License. You may obtain a copy of
28881 +** the License at http://www.mozilla.org/MPL/
28883 +** Software distributed under the License is distributed on an "AS
28884 +** IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
28885 +** implied. See the License for the specific language governing
28886 +** rights and limitations under the License.
28888 +** Alternatively, the contents of this file may be used under the
28889 +** terms of the GNU Public License version 2 (the "GPL"), in which
28890 +** case the provisions of the GPL are applicable instead of the
28891 +** above. If you wish to allow the use of your version of this file
28892 +** only under the terms of the GPL and not to allow others to use
28893 +** your version of this file under the MPL, indicate your decision
28894 +** by deleting the provisions above and replace them with the notice
28895 +** and other provisions required by the GPL. If you do not delete
28896 +** the provisions above, a recipient may use your version of this
28897 +** file under either the MPL or the GPL.
28898 +** ---------------------------------------------------------------------
28899 +** Inquiries regarding the ACX100 Open Source Project can be
28900 +** made directly to:
28902 +** acx100-users@lists.sf.net
28903 +** http://acx100.sf.net
28904 +** ---------------------------------------------------------------------
28907 +/***********************************************************************
28908 +** This code is based on elements which are
28909 +** Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
28910 +** info@linux-wlan.com
28911 +** http://www.linux-wlan.com
28916 +Here are all 11b/11g/11a rates and modulations:
28936 + B - DBPSK (Differential Binary Phase Shift Keying)
28937 + Q - DQPSK (Differential Quaternary Phase Shift Keying)
28938 + C - CCK (Complementary Code Keying, a form of DSSS
28939 + (Direct Sequence Spread Spectrum) modulation)
28940 + O - OFDM (Orthogonal Frequency Division Multiplexing)
28943 + d - CCK-OFDM (also known as DSSS-OFDM)
28944 + p - PBCC (Packet Binary Convolutional Coding)
28946 +The term CCK-OFDM may be used interchangeably with DSSS-OFDM
28947 +(the IEEE 802.11g-2003 standard uses the latter terminology).
28948 +In the CCK-OFDM, the PLCP header of the frame uses the CCK form of DSSS,
28949 +while the PLCP payload (the MAC frame) is modulated using OFDM.
28951 +Basically, you must use CCK-OFDM if you have mixed 11b/11g environment,
28952 +or else (pure OFDM) 11b equipment may not realize that AP
28953 +is sending a packet and start sending its own one.
28954 +Sadly, looks like acx111 does not support CCK-OFDM, only pure OFDM.
28956 +Re PBCC: avoid using it. It makes sense only if you have
28957 +TI "11b+" hardware. You _must_ use PBCC in order to reach 22Mbps on it.
28961 +Long preamble (at 1Mbit rate, takes 144 us):
28963 + 2 bytes 0xF3A0 (lsb sent first)
28964 +PLCP header follows (at 1Mbit also):
28965 + 1 byte Signal: speed, in 0.1Mbit units, except for:
28966 + 33Mbit: 33 (instead of 330 - doesn't fit in octet)
28967 + all CCK-OFDM rates: 30
28970 + 2: 1=locked clock
28972 + 5: Length Extension (PBCC 22,33Mbit (11g only)) <-
28973 + 6: Length Extension (PBCC 22,33Mbit (11g only)) <- BLACK MAGIC HERE
28974 + 7: Length Extension <-
28975 + 2 bytes Length (time needed to tx this frame)
28976 + a) 5.5 Mbit/s CCK
28977 + Length = octets*8/5.5, rounded up to integer
28979 + Length = octets*8/11, rounded up to integer
28981 + 0 = rounding took less than 8/11
28982 + 1 = rounding took more than or equal to 8/11
28983 + c) 5.5 Mbit/s PBCC
28984 + Length = (octets+1)*8/5.5, rounded up to integer
28985 + d) 11 Mbit/s PBCC
28986 + Length = (octets+1)*8/11, rounded up to integer
28988 + 0 = rounding took less than 8/11
28989 + 1 = rounding took more than or equal to 8/11
28990 + e) 22 Mbit/s PBCC
28991 + Length = (octets+1)*8/22, rounded up to integer
28992 + Service bits 6,7:
28993 + 00 = rounding took less than 8/22ths
28994 + 01 = rounding took 8/22...15/22ths
28995 + 10 = rounding took 16/22ths or more.
28996 + f) 33 Mbit/s PBCC
28997 + Length = (octets+1)*8/33, rounded up to integer
28998 + Service bits 5,6,7:
28999 + 000 rounding took less than 8/33
29000 + 001 rounding took 8/33...15/33
29001 + 010 rounding took 16/33...23/33
29002 + 011 rounding took 24/33...31/33
29003 + 100 rounding took 32/33 or more
29006 +PSDU follows (up to 2346 bytes at selected rate)
29008 +While Signal value alone is not enough to determine rate and modulation,
29009 +Signal+Service is always sufficient.
29011 +Short preamble (at 1Mbit rate, takes 72 us):
29013 + 2 bytes 0x05CF (lsb sent first)
29014 +PLCP header follows *at 2Mbit/s*. Format is the same as in long preamble.
29015 +PSDU follows (up to 2346 bytes at selected rate)
29017 +OFDM preamble is completely different, uses OFDM
29018 +modulation from the start and thus easily identifiable.
29023 +/***********************************************************************
29027 +#define WLAN_HDR_A3_LEN 24
29028 +#define WLAN_HDR_A4_LEN 30
29030 +** 3 bytes: Initialization Vector (24 bits)
29031 +** 1 byte: 0..5: padding, must be 0; 6..7: key selector (0-3)
29033 +#define WLAN_WEP_IV_LEN 4
29034 +/* 802.11 says 2312 but looks like 2312 is a max size of _WEPed data_ */
29035 +#define WLAN_DATA_MAXLEN 2304
29036 +#define WLAN_WEP_ICV_LEN 4
29037 +#define WLAN_FCS_LEN 4
29038 +#define WLAN_A3FR_MAXLEN (WLAN_HDR_A3_LEN + WLAN_DATA_MAXLEN)
29039 +#define WLAN_A4FR_MAXLEN (WLAN_HDR_A4_LEN + WLAN_DATA_MAXLEN)
29040 +#define WLAN_A3FR_MAXLEN_FCS (WLAN_HDR_A3_LEN + WLAN_DATA_MAXLEN + 4)
29041 +#define WLAN_A4FR_MAXLEN_FCS (WLAN_HDR_A4_LEN + WLAN_DATA_MAXLEN + 4)
29042 +#define WLAN_A3FR_MAXLEN_WEP (WLAN_A3FR_MAXLEN + 8)
29043 +#define WLAN_A4FR_MAXLEN_WEP (WLAN_A4FR_MAXLEN + 8)
29044 +#define WLAN_A3FR_MAXLEN_WEP_FCS (WLAN_A3FR_MAXLEN_FCS + 8)
29045 +#define WLAN_A4FR_MAXLEN_WEP_FCS (WLAN_A4FR_MAXLEN_FCS + 8)
29047 +#define WLAN_BSS_TS_LEN 8
29048 +#define WLAN_SSID_MAXLEN 32
29049 +#define WLAN_BEACON_FR_MAXLEN (WLAN_HDR_A3_LEN + 334)
29050 +#define WLAN_ATIM_FR_MAXLEN (WLAN_HDR_A3_LEN + 0)
29051 +#define WLAN_DISASSOC_FR_MAXLEN (WLAN_HDR_A3_LEN + 2)
29052 +#define WLAN_ASSOCREQ_FR_MAXLEN (WLAN_HDR_A3_LEN + 48)
29053 +#define WLAN_ASSOCRESP_FR_MAXLEN (WLAN_HDR_A3_LEN + 16)
29054 +#define WLAN_REASSOCREQ_FR_MAXLEN (WLAN_HDR_A3_LEN + 54)
29055 +#define WLAN_REASSOCRESP_FR_MAXLEN (WLAN_HDR_A3_LEN + 16)
29056 +#define WLAN_PROBEREQ_FR_MAXLEN (WLAN_HDR_A3_LEN + 44)
29057 +#define WLAN_PROBERESP_FR_MAXLEN (WLAN_HDR_A3_LEN + 78)
29058 +#define WLAN_AUTHEN_FR_MAXLEN (WLAN_HDR_A3_LEN + 261)
29059 +#define WLAN_DEAUTHEN_FR_MAXLEN (WLAN_HDR_A3_LEN + 2)
29060 +#define WLAN_CHALLENGE_IE_LEN 130
29061 +#define WLAN_CHALLENGE_LEN 128
29062 +#define WLAN_WEP_MAXKEYLEN 13
29063 +#define WLAN_WEP_NKEYS 4
29065 +/*--- Frame Control Field -------------------------------------*/
29067 +#define WLAN_FTYPE_MGMT 0x00
29068 +#define WLAN_FTYPE_CTL 0x01
29069 +#define WLAN_FTYPE_DATA 0x02
29071 +/* Frame subtypes */
29073 +#define WLAN_FSTYPE_ASSOCREQ 0x00
29074 +#define WLAN_FSTYPE_ASSOCRESP 0x01
29075 +#define WLAN_FSTYPE_REASSOCREQ 0x02
29076 +#define WLAN_FSTYPE_REASSOCRESP 0x03
29077 +#define WLAN_FSTYPE_PROBEREQ 0x04
29078 +#define WLAN_FSTYPE_PROBERESP 0x05
29079 +#define WLAN_FSTYPE_BEACON 0x08
29080 +#define WLAN_FSTYPE_ATIM 0x09
29081 +#define WLAN_FSTYPE_DISASSOC 0x0a
29082 +#define WLAN_FSTYPE_AUTHEN 0x0b
29083 +#define WLAN_FSTYPE_DEAUTHEN 0x0c
29086 +#define WLAN_FSTYPE_PSPOLL 0x0a
29087 +#define WLAN_FSTYPE_RTS 0x0b
29088 +#define WLAN_FSTYPE_CTS 0x0c
29089 +#define WLAN_FSTYPE_ACK 0x0d
29090 +#define WLAN_FSTYPE_CFEND 0x0e
29091 +#define WLAN_FSTYPE_CFENDCFACK 0x0f
29094 +#define WLAN_FSTYPE_DATAONLY 0x00
29095 +#define WLAN_FSTYPE_DATA_CFACK 0x01
29096 +#define WLAN_FSTYPE_DATA_CFPOLL 0x02
29097 +#define WLAN_FSTYPE_DATA_CFACK_CFPOLL 0x03
29098 +#define WLAN_FSTYPE_NULL 0x04
29099 +#define WLAN_FSTYPE_CFACK 0x05
29100 +#define WLAN_FSTYPE_CFPOLL 0x06
29101 +#define WLAN_FSTYPE_CFACK_CFPOLL 0x07
29103 +/*--- FC Constants v. 2.0 ------------------------------------*/
29104 +/* Each constant is defined twice: WF_CONST is in host */
29105 +/* byteorder, WF_CONSTi is in ieee byteorder. */
29107 +/* printf("the frame subtype is %X", WF_FC_FTYPEi & rx.fc); */
29108 +/* tx.fc = WF_FTYPE_CTLi | WF_FSTYPE_RTSi; */
29109 +/*------------------------------------------------------------*/
29112 +/*--- Frame Control Field -------------------------------------*/
29113 +/* Protocol version: always 0 for current 802.11 standards */
29114 +IEEE16(WF_FC_PVER, 0x0003)
29115 +IEEE16(WF_FC_FTYPE, 0x000c)
29116 +IEEE16(WF_FC_FSTYPE, 0x00f0)
29117 +IEEE16(WF_FC_TODS, 0x0100)
29118 +IEEE16(WF_FC_FROMDS, 0x0200)
29119 +IEEE16(WF_FC_FROMTODS, 0x0300)
29120 +IEEE16(WF_FC_MOREFRAG, 0x0400)
29121 +IEEE16(WF_FC_RETRY, 0x0800)
29122 +/* Indicates PS mode in which STA will be after successful completion
29123 +** of current frame exchange sequence. Always 0 for AP frames */
29124 +IEEE16(WF_FC_PWRMGT, 0x1000)
29125 +/* What MoreData=1 means:
29126 +** From AP to STA in PS mode: don't sleep yet, I have more frames for you
29127 +** From Contention-Free (CF) Pollable STA in response to a CF-Poll:
29128 +** STA has buffered frames for transmission in response to next CF-Poll
29129 +** Bcast/mcast frames transmitted from AP:
29130 +** when additional bcast/mcast frames remain to be transmitted by AP
29131 +** during this beacon interval
29132 +** In all other cases MoreData=0 */
29133 +IEEE16(WF_FC_MOREDATA, 0x2000)
29134 +IEEE16(WF_FC_ISWEP, 0x4000)
29135 +IEEE16(WF_FC_ORDER, 0x8000)
29138 +IEEE16(WF_FTYPE_MGMT, 0x00)
29139 +IEEE16(WF_FTYPE_CTL, 0x04)
29140 +IEEE16(WF_FTYPE_DATA, 0x08)
29142 +/* Frame subtypes */
29144 +IEEE16(WF_FSTYPE_ASSOCREQ, 0x00)
29145 +IEEE16(WF_FSTYPE_ASSOCRESP, 0x10)
29146 +IEEE16(WF_FSTYPE_REASSOCREQ, 0x20)
29147 +IEEE16(WF_FSTYPE_REASSOCRESP, 0x30)
29148 +IEEE16(WF_FSTYPE_PROBEREQ, 0x40)
29149 +IEEE16(WF_FSTYPE_PROBERESP, 0x50)
29150 +IEEE16(WF_FSTYPE_BEACON, 0x80)
29151 +IEEE16(WF_FSTYPE_ATIM, 0x90)
29152 +IEEE16(WF_FSTYPE_DISASSOC, 0xa0)
29153 +IEEE16(WF_FSTYPE_AUTHEN, 0xb0)
29154 +IEEE16(WF_FSTYPE_DEAUTHEN, 0xc0)
29157 +IEEE16(WF_FSTYPE_PSPOLL, 0xa0)
29158 +IEEE16(WF_FSTYPE_RTS, 0xb0)
29159 +IEEE16(WF_FSTYPE_CTS, 0xc0)
29160 +IEEE16(WF_FSTYPE_ACK, 0xd0)
29161 +IEEE16(WF_FSTYPE_CFEND, 0xe0)
29162 +IEEE16(WF_FSTYPE_CFENDCFACK, 0xf0)
29165 +IEEE16(WF_FSTYPE_DATAONLY, 0x00)
29166 +IEEE16(WF_FSTYPE_DATA_CFACK, 0x10)
29167 +IEEE16(WF_FSTYPE_DATA_CFPOLL, 0x20)
29168 +IEEE16(WF_FSTYPE_DATA_CFACK_CFPOLL, 0x30)
29169 +IEEE16(WF_FSTYPE_NULL, 0x40)
29170 +IEEE16(WF_FSTYPE_CFACK, 0x50)
29171 +IEEE16(WF_FSTYPE_CFPOLL, 0x60)
29172 +IEEE16(WF_FSTYPE_CFACK_CFPOLL, 0x70)
29176 +/***********************************************************************
29180 +/*--- Duration Macros ----------------------------------------*/
29181 +/* Macros to get/set the bitfields of the Duration Field */
29182 +/* - the duration value is only valid when bit15 is zero */
29183 +/* - the firmware handles these values, so I'm not going */
29184 +/* these macros right now. */
29185 +/*------------------------------------------------------------*/
29187 +/*--- Sequence Control Macros -------------------------------*/
29188 +/* Macros to get/set the bitfields of the Sequence Control */
29190 +/*------------------------------------------------------------*/
29191 +#define WLAN_GET_SEQ_FRGNUM(n) ((u16)(n) & 0x000f)
29192 +#define WLAN_GET_SEQ_SEQNUM(n) (((u16)(n) & 0xfff0) >> 4)
29194 +/*--- Data ptr macro -----------------------------------------*/
29195 +/* Creates a u8* to the data portion of a frame */
29196 +/* Assumes you're passing in a ptr to the beginning of the hdr*/
29197 +/*------------------------------------------------------------*/
29198 +#define WLAN_HDR_A3_DATAP(p) (((u8*)(p)) + WLAN_HDR_A3_LEN)
29199 +#define WLAN_HDR_A4_DATAP(p) (((u8*)(p)) + WLAN_HDR_A4_LEN)
29202 +/***********************************************************************
29206 +/* 802.11 header type
29208 +** Note the following:
29209 +** a1 *always* is receiver's mac or bcast/mcast
29210 +** a2 *always* is transmitter's mac, if a2 exists
29211 +** seq: [0:3] frag#, [4:15] seq# - used for dup detection
29212 +** (dups from retries have same seq#) */
29213 +typedef struct wlan_hdr {
29214 + u16 fc __WLAN_ATTRIB_PACK__;
29215 + u16 dur __WLAN_ATTRIB_PACK__;
29216 + u8 a1[ETH_ALEN] __WLAN_ATTRIB_PACK__;
29217 + u8 a2[ETH_ALEN] __WLAN_ATTRIB_PACK__;
29218 + u8 a3[ETH_ALEN] __WLAN_ATTRIB_PACK__;
29219 + u16 seq __WLAN_ATTRIB_PACK__;
29220 + u8 a4[ETH_ALEN] __WLAN_ATTRIB_PACK__;
29223 +/* Separate structs for use if frame type is known */
29224 +typedef struct wlan_hdr_a3 {
29225 + u16 fc __WLAN_ATTRIB_PACK__;
29226 + u16 dur __WLAN_ATTRIB_PACK__;
29227 + u8 a1[ETH_ALEN] __WLAN_ATTRIB_PACK__;
29228 + u8 a2[ETH_ALEN] __WLAN_ATTRIB_PACK__;
29229 + u8 a3[ETH_ALEN] __WLAN_ATTRIB_PACK__;
29230 + u16 seq __WLAN_ATTRIB_PACK__;
29233 +typedef struct wlan_hdr_mgmt {
29234 + u16 fc __WLAN_ATTRIB_PACK__;
29235 + u16 dur __WLAN_ATTRIB_PACK__;
29236 + u8 da[ETH_ALEN] __WLAN_ATTRIB_PACK__;
29237 + u8 sa[ETH_ALEN] __WLAN_ATTRIB_PACK__;
29238 + u8 bssid[ETH_ALEN] __WLAN_ATTRIB_PACK__;
29239 + u16 seq __WLAN_ATTRIB_PACK__;
29240 +} wlan_hdr_mgmt_t;
29242 +#ifdef NOT_NEEDED_YET
29243 +typedef struct { /* ad-hoc peer->peer (to/from DS = 0/0) */
29244 + u16 fc __WLAN_ATTRIB_PACK__;
29245 + u16 dur __WLAN_ATTRIB_PACK__;
29246 + u8 da[ETH_ALEN] __WLAN_ATTRIB_PACK__;
29247 + u8 sa[ETH_ALEN] __WLAN_ATTRIB_PACK__;
29248 + u8 bssid[ETH_ALEN] __WLAN_ATTRIB_PACK__;
29249 + u16 seq __WLAN_ATTRIB_PACK__;
29251 +typedef struct { /* ap->sta (to/from DS = 0/1) */
29252 + u16 fc __WLAN_ATTRIB_PACK__;
29253 + u16 dur __WLAN_ATTRIB_PACK__;
29254 + u8 da[ETH_ALEN] __WLAN_ATTRIB_PACK__;
29255 + u8 bssid[ETH_ALEN] __WLAN_ATTRIB_PACK__;
29256 + u8 sa[ETH_ALEN] __WLAN_ATTRIB_PACK__;
29257 + u16 seq __WLAN_ATTRIB_PACK__;
29259 +typedef struct { /* sta->ap (to/from DS = 1/0) */
29260 + u16 fc __WLAN_ATTRIB_PACK__;
29261 + u16 dur __WLAN_ATTRIB_PACK__;
29262 + u8 bssid[ETH_ALEN] __WLAN_ATTRIB_PACK__;
29263 + u8 sa[ETH_ALEN] __WLAN_ATTRIB_PACK__;
29264 + u8 da[ETH_ALEN] __WLAN_ATTRIB_PACK__;
29265 + u16 seq __WLAN_ATTRIB_PACK__;
29267 +typedef struct { /* wds->wds (to/from DS = 1/1), the only 4addr pkt */
29268 + u16 fc __WLAN_ATTRIB_PACK__;
29269 + u16 dur __WLAN_ATTRIB_PACK__;
29270 + u8 ra[ETH_ALEN] __WLAN_ATTRIB_PACK__;
29271 + u8 ta[ETH_ALEN] __WLAN_ATTRIB_PACK__;
29272 + u8 da[ETH_ALEN] __WLAN_ATTRIB_PACK__;
29273 + u16 seq __WLAN_ATTRIB_PACK__;
29274 + u8 sa[ETH_ALEN] __WLAN_ATTRIB_PACK__;
29276 +typedef struct { /* all management packets */
29277 + u16 fc __WLAN_ATTRIB_PACK__;
29278 + u16 dur __WLAN_ATTRIB_PACK__;
29279 + u8 da[ETH_ALEN] __WLAN_ATTRIB_PACK__;
29280 + u8 sa[ETH_ALEN] __WLAN_ATTRIB_PACK__;
29281 + u8 bssid[ETH_ALEN] __WLAN_ATTRIB_PACK__;
29282 + u16 seq __WLAN_ATTRIB_PACK__;
29284 +typedef struct { /* has no body, just a FCS */
29285 + u16 fc __WLAN_ATTRIB_PACK__;
29286 + u16 dur __WLAN_ATTRIB_PACK__;
29287 + u8 ra[ETH_ALEN] __WLAN_ATTRIB_PACK__;
29288 + u8 ta[ETH_ALEN] __WLAN_ATTRIB_PACK__;
29290 +typedef struct { /* has no body, just a FCS */
29291 + u16 fc __WLAN_ATTRIB_PACK__;
29292 + u16 dur __WLAN_ATTRIB_PACK__;
29293 + u8 ra[ETH_ALEN] __WLAN_ATTRIB_PACK__;
29295 +typedef struct { /* has no body, just a FCS */
29296 + u16 fc __WLAN_ATTRIB_PACK__;
29297 + u16 dur __WLAN_ATTRIB_PACK__;
29298 + u8 ra[ETH_ALEN] __WLAN_ATTRIB_PACK__;
29300 +typedef struct { /* has no body, just a FCS */
29301 + u16 fc __WLAN_ATTRIB_PACK__;
29302 + /* NB: this one holds Assoc ID in dur field: */
29303 + u16 aid __WLAN_ATTRIB_PACK__;
29304 + u8 bssid[ETH_ALEN] __WLAN_ATTRIB_PACK__;
29305 + u8 ta[ETH_ALEN] __WLAN_ATTRIB_PACK__;
29307 +typedef struct { /* has no body, just a FCS */
29308 + u16 fc __WLAN_ATTRIB_PACK__;
29309 + u16 dur __WLAN_ATTRIB_PACK__;
29310 + u8 ra[ETH_ALEN] __WLAN_ATTRIB_PACK__;
29311 + u8 bssid[ETH_ALEN] __WLAN_ATTRIB_PACK__;
29313 +typedef struct { /* has no body, just a FCS */
29314 + u16 fc __WLAN_ATTRIB_PACK__;
29315 + u16 dur __WLAN_ATTRIB_PACK__;
29316 + u8 ra[ETH_ALEN] __WLAN_ATTRIB_PACK__;
29317 + u8 bssid[ETH_ALEN] __WLAN_ATTRIB_PACK__;
29321 +/* Prism header emulation (monitor mode) */
29322 +typedef struct wlanitem_u32 {
29323 + u32 did __WLAN_ATTRIB_PACK__;
29324 + u16 status __WLAN_ATTRIB_PACK__;
29325 + u16 len __WLAN_ATTRIB_PACK__;
29326 + u32 data __WLAN_ATTRIB_PACK__;
29328 +#define WLANITEM_STATUS_data_ok 0
29329 +#define WLANITEM_STATUS_no_value 1
29330 +#define WLANITEM_STATUS_invalid_itemname 2
29331 +#define WLANITEM_STATUS_invalid_itemdata 3
29332 +#define WLANITEM_STATUS_missing_itemdata 4
29333 +#define WLANITEM_STATUS_incomplete_itemdata 5
29334 +#define WLANITEM_STATUS_invalid_msg_did 6
29335 +#define WLANITEM_STATUS_invalid_mib_did 7
29336 +#define WLANITEM_STATUS_missing_conv_func 8
29337 +#define WLANITEM_STATUS_string_too_long 9
29338 +#define WLANITEM_STATUS_data_out_of_range 10
29339 +#define WLANITEM_STATUS_string_too_short 11
29340 +#define WLANITEM_STATUS_missing_valid_func 12
29341 +#define WLANITEM_STATUS_unknown 13
29342 +#define WLANITEM_STATUS_invalid_did 14
29343 +#define WLANITEM_STATUS_missing_print_func 15
29345 +#define WLAN_DEVNAMELEN_MAX 16
29346 +typedef struct wlansniffrm {
29347 + u32 msgcode __WLAN_ATTRIB_PACK__;
29348 + u32 msglen __WLAN_ATTRIB_PACK__;
29349 + u8 devname[WLAN_DEVNAMELEN_MAX] __WLAN_ATTRIB_PACK__;
29350 + wlanitem_u32_t hosttime __WLAN_ATTRIB_PACK__;
29351 + wlanitem_u32_t mactime __WLAN_ATTRIB_PACK__;
29352 + wlanitem_u32_t channel __WLAN_ATTRIB_PACK__;
29353 + wlanitem_u32_t rssi __WLAN_ATTRIB_PACK__;
29354 + wlanitem_u32_t sq __WLAN_ATTRIB_PACK__;
29355 + wlanitem_u32_t signal __WLAN_ATTRIB_PACK__;
29356 + wlanitem_u32_t noise __WLAN_ATTRIB_PACK__;
29357 + wlanitem_u32_t rate __WLAN_ATTRIB_PACK__;
29358 + wlanitem_u32_t istx __WLAN_ATTRIB_PACK__; /* tx? 0:no 1:yes */
29359 + wlanitem_u32_t frmlen __WLAN_ATTRIB_PACK__;
29361 +#define WLANSNIFFFRM 0x0041
29362 +#define WLANSNIFFFRM_hosttime 0x1041
29363 +#define WLANSNIFFFRM_mactime 0x2041
29364 +#define WLANSNIFFFRM_channel 0x3041
29365 +#define WLANSNIFFFRM_rssi 0x4041
29366 +#define WLANSNIFFFRM_sq 0x5041
29367 +#define WLANSNIFFFRM_signal 0x6041
29368 +#define WLANSNIFFFRM_noise 0x7041
29369 +#define WLANSNIFFFRM_rate 0x8041
29370 +#define WLANSNIFFFRM_istx 0x9041
29371 +#define WLANSNIFFFRM_frmlen 0xA041
29372 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
29373 --- linux-2.6.14-omap2/drivers/net/wireless/tiacx/wlan_mgmt.h 1970-01-01 02:00:00.000000000 +0200
29374 +++ linux-h6300-omap2-2.6.14.3/drivers/net/wireless/tiacx/wlan_mgmt.h 2005-09-28 23:54:23.000000000 +0300
29376 +/***********************************************************************
29377 +** Copyright (C) 2003 ACX100 Open Source Project
29379 +** The contents of this file are subject to the Mozilla Public
29380 +** License Version 1.1 (the "License"); you may not use this file
29381 +** except in compliance with the License. You may obtain a copy of
29382 +** the License at http://www.mozilla.org/MPL/
29384 +** Software distributed under the License is distributed on an "AS
29385 +** IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
29386 +** implied. See the License for the specific language governing
29387 +** rights and limitations under the License.
29389 +** Alternatively, the contents of this file may be used under the
29390 +** terms of the GNU Public License version 2 (the "GPL"), in which
29391 +** case the provisions of the GPL are applicable instead of the
29392 +** above. If you wish to allow the use of your version of this file
29393 +** only under the terms of the GPL and not to allow others to use
29394 +** your version of this file under the MPL, indicate your decision
29395 +** by deleting the provisions above and replace them with the notice
29396 +** and other provisions required by the GPL. If you do not delete
29397 +** the provisions above, a recipient may use your version of this
29398 +** file under either the MPL or the GPL.
29399 +** ---------------------------------------------------------------------
29400 +** Inquiries regarding the ACX100 Open Source Project can be
29401 +** made directly to:
29403 +** acx100-users@lists.sf.net
29404 +** http://acx100.sf.net
29405 +** ---------------------------------------------------------------------
29408 +/***********************************************************************
29409 +** This code is based on elements which are
29410 +** Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
29411 +** info@linux-wlan.com
29412 +** http://www.linux-wlan.com
29415 +/***********************************************************************
29419 +/*-- Information Element IDs --------------------*/
29420 +#define WLAN_EID_SSID 0
29421 +#define WLAN_EID_SUPP_RATES 1
29422 +#define WLAN_EID_FH_PARMS 2
29423 +#define WLAN_EID_DS_PARMS 3
29424 +#define WLAN_EID_CF_PARMS 4
29425 +#define WLAN_EID_TIM 5
29426 +#define WLAN_EID_IBSS_PARMS 6
29427 +#define WLAN_EID_COUNTRY 7 /* 802.11d */
29428 +#define WLAN_EID_FH_HOP_PARMS 8 /* 802.11d */
29429 +#define WLAN_EID_FH_TABLE 9 /* 802.11d */
29430 +#define WLAN_EID_REQUEST 10 /* 802.11d */
29431 +/*-- values 11-15 reserved --*/
29432 +#define WLAN_EID_CHALLENGE 16
29433 +/*-- values 17-31 reserved for challenge text extension --*/
29434 +#define WLAN_EID_ERP_INFO 42
29435 +#define WLAN_EID_NONERP 47 /* was seen from WRT54GS with OpenWrt */
29436 +#define WLAN_EID_RSN 48
29437 +#define WLAN_EID_EXT_RATES 50
29438 +#define WLAN_EID_GENERIC 221
29441 +#define WLAN_EID_PWR_CONSTRAINT 32 /* 11H PowerConstraint */
29442 +#define WLAN_EID_PWR_CAP 33 /* 11H PowerCapability */
29443 +#define WLAN_EID_TPC_REQUEST 34 /* 11H TPC Request */
29444 +#define WLAN_EID_TPC_REPORT 35 /* 11H TPC Report */
29445 +#define WLAN_EID_SUPP_CHANNELS 36 /* 11H Supported Channels */
29446 +#define WLAN_EID_CHANNEL_SWITCH 37 /* 11H ChannelSwitch */
29447 +#define WLAN_EID_MEASURE_REQUEST 38 /* 11H MeasurementRequest */
29448 +#define WLAN_EID_MEASURE_REPORT 39 /* 11H MeasurementReport */
29449 +#define WLAN_EID_QUIET_ID 40 /* 11H Quiet */
29450 +#define WLAN_EID_IBSS_DFS_ID 41 /* 11H IBSS_DFS */
29453 +/*-- Reason Codes -------------------------------*/
29454 +#define WLAN_MGMT_REASON_RSVD 0
29455 +#define WLAN_MGMT_REASON_UNSPEC 1
29456 +#define WLAN_MGMT_REASON_PRIOR_AUTH_INVALID 2
29457 +#define WLAN_MGMT_REASON_DEAUTH_LEAVING 3
29458 +#define WLAN_MGMT_REASON_DISASSOC_INACTIVE 4
29459 +#define WLAN_MGMT_REASON_DISASSOC_AP_BUSY 5
29460 +#define WLAN_MGMT_REASON_CLASS2_NONAUTH 6
29461 +#define WLAN_MGMT_REASON_CLASS3_NONASSOC 7
29462 +#define WLAN_MGMT_REASON_DISASSOC_STA_HASLEFT 8
29463 +#define WLAN_MGMT_REASON_CANT_ASSOC_NONAUTH 9
29465 +/*-- Status Codes -------------------------------*/
29466 +#define WLAN_MGMT_STATUS_SUCCESS 0
29467 +#define WLAN_MGMT_STATUS_UNSPEC_FAILURE 1
29468 +#define WLAN_MGMT_STATUS_CAPS_UNSUPPORTED 10
29469 +#define WLAN_MGMT_STATUS_REASSOC_NO_ASSOC 11
29470 +#define WLAN_MGMT_STATUS_ASSOC_DENIED_UNSPEC 12
29471 +#define WLAN_MGMT_STATUS_UNSUPPORTED_AUTHALG 13
29472 +#define WLAN_MGMT_STATUS_RX_AUTH_NOSEQ 14
29473 +#define WLAN_MGMT_STATUS_CHALLENGE_FAIL 15
29474 +#define WLAN_MGMT_STATUS_AUTH_TIMEOUT 16
29475 +#define WLAN_MGMT_STATUS_ASSOC_DENIED_BUSY 17
29476 +#define WLAN_MGMT_STATUS_ASSOC_DENIED_RATES 18
29477 +/* p80211b additions */
29478 +#define WLAN_MGMT_STATUS_ASSOC_DENIED_NOSHORT 19
29479 +#define WLAN_MGMT_STATUS_ASSOC_DENIED_NOPBCC 20
29480 +#define WLAN_MGMT_STATUS_ASSOC_DENIED_NOAGILITY 21
29482 +/*-- Auth Algorithm Field ---------------------------*/
29483 +#define WLAN_AUTH_ALG_OPENSYSTEM 0
29484 +#define WLAN_AUTH_ALG_SHAREDKEY 1
29486 +/*-- Management Frame Field Offsets -------------*/
29487 +/* Note: Not all fields are listed because of variable lengths */
29488 +/* Note: These offsets are from the start of the frame data */
29490 +#define WLAN_BEACON_OFF_TS 0
29491 +#define WLAN_BEACON_OFF_BCN_INT 8
29492 +#define WLAN_BEACON_OFF_CAPINFO 10
29493 +#define WLAN_BEACON_OFF_SSID 12
29495 +#define WLAN_DISASSOC_OFF_REASON 0
29497 +#define WLAN_ASSOCREQ_OFF_CAP_INFO 0
29498 +#define WLAN_ASSOCREQ_OFF_LISTEN_INT 2
29499 +#define WLAN_ASSOCREQ_OFF_SSID 4
29501 +#define WLAN_ASSOCRESP_OFF_CAP_INFO 0
29502 +#define WLAN_ASSOCRESP_OFF_STATUS 2
29503 +#define WLAN_ASSOCRESP_OFF_AID 4
29504 +#define WLAN_ASSOCRESP_OFF_SUPP_RATES 6
29506 +#define WLAN_REASSOCREQ_OFF_CAP_INFO 0
29507 +#define WLAN_REASSOCREQ_OFF_LISTEN_INT 2
29508 +#define WLAN_REASSOCREQ_OFF_CURR_AP 4
29509 +#define WLAN_REASSOCREQ_OFF_SSID 10
29511 +#define WLAN_REASSOCRESP_OFF_CAP_INFO 0
29512 +#define WLAN_REASSOCRESP_OFF_STATUS 2
29513 +#define WLAN_REASSOCRESP_OFF_AID 4
29514 +#define WLAN_REASSOCRESP_OFF_SUPP_RATES 6
29516 +#define WLAN_PROBEREQ_OFF_SSID 0
29518 +#define WLAN_PROBERESP_OFF_TS 0
29519 +#define WLAN_PROBERESP_OFF_BCN_INT 8
29520 +#define WLAN_PROBERESP_OFF_CAP_INFO 10
29521 +#define WLAN_PROBERESP_OFF_SSID 12
29523 +#define WLAN_AUTHEN_OFF_AUTH_ALG 0
29524 +#define WLAN_AUTHEN_OFF_AUTH_SEQ 2
29525 +#define WLAN_AUTHEN_OFF_STATUS 4
29526 +#define WLAN_AUTHEN_OFF_CHALLENGE 6
29528 +#define WLAN_DEAUTHEN_OFF_REASON 0
29531 +IEEE16(WF_MGMT_CAP_ESS, 0x0001)
29532 +IEEE16(WF_MGMT_CAP_IBSS, 0x0002)
29533 +/* In (re)assoc request frames by STA:
29534 +** Pollable=0, PollReq=0: STA is not CF-Pollable
29535 +** 0 1: STA is CF-Pollable, not requesting to be placed on the CF-Polling list
29536 +** 1 0: STA is CF-Pollable, requesting to be placed on the CF-Polling list
29537 +** 1 1: STA is CF-Pollable, requesting never to be polled
29538 +** In beacon, proberesp, (re)assoc resp frames by AP:
29539 +** 0 0: No point coordinator at AP
29540 +** 0 1: Point coordinator at AP for delivery only (no polling)
29541 +** 1 0: Point coordinator at AP for delivery and polling
29542 +** 1 1: Reserved */
29543 +IEEE16(WF_MGMT_CAP_CFPOLLABLE, 0x0004)
29544 +IEEE16(WF_MGMT_CAP_CFPOLLREQ, 0x0008)
29545 +/* 1=non-WEP data frames are disallowed */
29546 +IEEE16(WF_MGMT_CAP_PRIVACY, 0x0010)
29547 +/* In beacon, proberesp, (re)assocresp by AP/AdHoc:
29548 +** 1=use of shortpre is allowed ("I can receive shortpre") */
29549 +IEEE16(WF_MGMT_CAP_SHORT, 0x0020)
29550 +IEEE16(WF_MGMT_CAP_PBCC, 0x0040)
29551 +IEEE16(WF_MGMT_CAP_AGILITY, 0x0080)
29552 +/* In (re)assoc request frames by STA:
29553 +** 1=short slot time implemented and enabled
29554 +** NB: AP shall use long slot time beginning at the next Beacon after assoc
29555 +** of STA with this bit set to 0
29556 +** In beacon, proberesp, (re)assoc resp frames by AP:
29557 +** currently used slot time value: 0/1 - long/short */
29558 +IEEE16(WF_MGMT_CAP_SHORTSLOT, 0x0400)
29559 +/* In (re)assoc request frames by STA: 1=CCK-OFDM is implemented and enabled
29560 +** In beacon, proberesp, (re)assoc resp frames by AP/AdHoc:
29561 +** 1=CCK-OFDM is allowed */
29562 +IEEE16(WF_MGMT_CAP_CCKOFDM, 0x2000)
29566 +/***********************************************************************
29570 +/* Information Element types */
29572 +/* prototype structure, all IEs start with these members */
29573 +typedef struct wlan_ie {
29574 + u8 eid __WLAN_ATTRIB_PACK__;
29575 + u8 len __WLAN_ATTRIB_PACK__;
29578 +/*-- Service Set Identity (SSID) -----------------*/
29579 +typedef struct wlan_ie_ssid {
29580 + u8 eid __WLAN_ATTRIB_PACK__;
29581 + u8 len __WLAN_ATTRIB_PACK__;
29582 + u8 ssid[1] __WLAN_ATTRIB_PACK__; /* may be zero */
29585 +/*-- Supported Rates -----------------------------*/
29586 +typedef struct wlan_ie_supp_rates {
29587 + u8 eid __WLAN_ATTRIB_PACK__;
29588 + u8 len __WLAN_ATTRIB_PACK__;
29589 + u8 rates[1] __WLAN_ATTRIB_PACK__; /* had better be at LEAST one! */
29590 +} wlan_ie_supp_rates_t;
29592 +/*-- FH Parameter Set ----------------------------*/
29593 +typedef struct wlan_ie_fh_parms {
29594 + u8 eid __WLAN_ATTRIB_PACK__;
29595 + u8 len __WLAN_ATTRIB_PACK__;
29596 + u16 dwell __WLAN_ATTRIB_PACK__;
29597 + u8 hopset __WLAN_ATTRIB_PACK__;
29598 + u8 hoppattern __WLAN_ATTRIB_PACK__;
29599 + u8 hopindex __WLAN_ATTRIB_PACK__;
29600 +} wlan_ie_fh_parms_t;
29602 +/*-- DS Parameter Set ----------------------------*/
29603 +typedef struct wlan_ie_ds_parms {
29604 + u8 eid __WLAN_ATTRIB_PACK__;
29605 + u8 len __WLAN_ATTRIB_PACK__;
29606 + u8 curr_ch __WLAN_ATTRIB_PACK__;
29607 +} wlan_ie_ds_parms_t;
29609 +/*-- CF Parameter Set ----------------------------*/
29610 +typedef struct wlan_ie_cf_parms {
29611 + u8 eid __WLAN_ATTRIB_PACK__;
29612 + u8 len __WLAN_ATTRIB_PACK__;
29613 + u8 cfp_cnt __WLAN_ATTRIB_PACK__;
29614 + u8 cfp_period __WLAN_ATTRIB_PACK__;
29615 + u16 cfp_maxdur __WLAN_ATTRIB_PACK__;
29616 + u16 cfp_durremaining __WLAN_ATTRIB_PACK__;
29617 +} wlan_ie_cf_parms_t;
29619 +/*-- TIM ------------------------------------------*/
29620 +typedef struct wlan_ie_tim {
29621 + u8 eid __WLAN_ATTRIB_PACK__;
29622 + u8 len __WLAN_ATTRIB_PACK__;
29623 + u8 dtim_cnt __WLAN_ATTRIB_PACK__;
29624 + u8 dtim_period __WLAN_ATTRIB_PACK__;
29625 + u8 bitmap_ctl __WLAN_ATTRIB_PACK__;
29626 + u8 virt_bm[1] __WLAN_ATTRIB_PACK__;
29629 +/*-- IBSS Parameter Set ---------------------------*/
29630 +typedef struct wlan_ie_ibss_parms {
29631 + u8 eid __WLAN_ATTRIB_PACK__;
29632 + u8 len __WLAN_ATTRIB_PACK__;
29633 + u16 atim_win __WLAN_ATTRIB_PACK__;
29634 +} wlan_ie_ibss_parms_t;
29636 +/*-- Challenge Text ------------------------------*/
29637 +typedef struct wlan_ie_challenge {
29638 + u8 eid __WLAN_ATTRIB_PACK__;
29639 + u8 len __WLAN_ATTRIB_PACK__;
29640 + u8 challenge[1] __WLAN_ATTRIB_PACK__;
29641 +} wlan_ie_challenge_t;
29643 +/*-- ERP (42) -------------------------------------*/
29644 +typedef struct wlan_ie_erp {
29645 + u8 eid __WLAN_ATTRIB_PACK__;
29646 + u8 len __WLAN_ATTRIB_PACK__;
29647 + /* bit 0:Non ERP present
29648 + ** 1:Use Protection
29649 + ** 2:Barker Preamble mode
29650 + ** 3-7:reserved */
29651 + u8 erp __WLAN_ATTRIB_PACK__;
29654 +/* Types for parsing mgmt frames */
29656 +/* prototype structure, all mgmt frame types will start with these members */
29657 +typedef struct wlan_fr_mgmt {
29659 + u16 len; /* DOES NOT include FCS */
29661 + /* used for target specific data, skb in Linux */
29662 + /*-- fixed fields -----------*/
29663 + /*-- info elements ----------*/
29666 +/*-- Beacon ---------------------------------------*/
29667 +typedef struct wlan_fr_beacon {
29671 + /*-- fixed fields -----------*/
29675 + /*-- info elements ----------*/
29676 + wlan_ie_ssid_t *ssid;
29677 + wlan_ie_supp_rates_t *supp_rates;
29678 + wlan_ie_supp_rates_t *ext_rates;
29679 + wlan_ie_fh_parms_t *fh_parms;
29680 + wlan_ie_ds_parms_t *ds_parms;
29681 + wlan_ie_cf_parms_t *cf_parms;
29682 + wlan_ie_ibss_parms_t *ibss_parms;
29683 + wlan_ie_tim_t *tim; /* in beacon only, not proberesp */
29684 + wlan_ie_erp_t *erp; /* in beacon only, not proberesp */
29685 +} wlan_fr_beacon_t;
29686 +#define wlan_fr_proberesp wlan_fr_beacon
29687 +#define wlan_fr_proberesp_t wlan_fr_beacon_t
29689 +/*-- IBSS ATIM ------------------------------------*/
29690 +typedef struct wlan_fr_ibssatim {
29694 + /*-- fixed fields -----------*/
29695 + /*-- info elements ----------*/
29696 + /* this frame type has a null body */
29697 +} wlan_fr_ibssatim_t;
29699 +/*-- Disassociation -------------------------------*/
29700 +typedef struct wlan_fr_disassoc {
29704 + /*-- fixed fields -----------*/
29706 + /*-- info elements ----------*/
29707 +} wlan_fr_disassoc_t;
29709 +/*-- Association Request --------------------------*/
29710 +typedef struct wlan_fr_assocreq {
29714 + /*-- fixed fields -----------*/
29717 + /*-- info elements ----------*/
29718 + wlan_ie_ssid_t *ssid;
29719 + wlan_ie_supp_rates_t *supp_rates;
29720 + wlan_ie_supp_rates_t *ext_rates;
29721 +} wlan_fr_assocreq_t;
29723 +/*-- Association Response -------------------------*/
29724 +typedef struct wlan_fr_assocresp {
29728 + /*-- fixed fields -----------*/
29732 + /*-- info elements ----------*/
29733 + wlan_ie_supp_rates_t *supp_rates;
29734 + wlan_ie_supp_rates_t *ext_rates;
29735 +} wlan_fr_assocresp_t;
29737 +/*-- Reassociation Request ------------------------*/
29738 +typedef struct wlan_fr_reassocreq {
29742 + /*-- fixed fields -----------*/
29746 + /*-- info elements ----------*/
29747 + wlan_ie_ssid_t *ssid;
29748 + wlan_ie_supp_rates_t *supp_rates;
29749 + wlan_ie_supp_rates_t *ext_rates;
29750 +} wlan_fr_reassocreq_t;
29752 +/*-- Reassociation Response -----------------------*/
29753 +typedef struct wlan_fr_reassocresp {
29757 + /*-- fixed fields -----------*/
29761 + /*-- info elements ----------*/
29762 + wlan_ie_supp_rates_t *supp_rates;
29763 + wlan_ie_supp_rates_t *ext_rates;
29764 +} wlan_fr_reassocresp_t;
29766 +/*-- Probe Request --------------------------------*/
29767 +typedef struct wlan_fr_probereq {
29771 + /*-- fixed fields -----------*/
29772 + /*-- info elements ----------*/
29773 + wlan_ie_ssid_t *ssid;
29774 + wlan_ie_supp_rates_t *supp_rates;
29775 + wlan_ie_supp_rates_t *ext_rates;
29776 +} wlan_fr_probereq_t;
29778 +/*-- Authentication -------------------------------*/
29779 +typedef struct wlan_fr_authen {
29783 + /*-- fixed fields -----------*/
29787 + /*-- info elements ----------*/
29788 + wlan_ie_challenge_t *challenge;
29789 +} wlan_fr_authen_t;
29791 +/*-- Deauthenication -----------------------------*/
29792 +typedef struct wlan_fr_deauthen {
29796 + /*-- fixed fields -----------*/
29798 + /*-- info elements ----------*/
29799 +} wlan_fr_deauthen_t;
29801 +/* Types for building mgmt frames */
29803 +/* Warning. Several types used in below structs are
29804 +** in fact variable length. Use structs with such fields with caution */
29805 +typedef struct auth_frame_body {
29806 + u16 auth_alg __WLAN_ATTRIB_PACK__;
29807 + u16 auth_seq __WLAN_ATTRIB_PACK__;
29808 + u16 status __WLAN_ATTRIB_PACK__;
29809 + wlan_ie_challenge_t challenge __WLAN_ATTRIB_PACK__;
29810 +} auth_frame_body_t;
29812 +typedef struct assocresp_frame_body {
29813 + u16 cap_info __WLAN_ATTRIB_PACK__;
29814 + u16 status __WLAN_ATTRIB_PACK__;
29815 + u16 aid __WLAN_ATTRIB_PACK__;
29816 + wlan_ie_supp_rates_t rates __WLAN_ATTRIB_PACK__;
29817 +} assocresp_frame_body_t;
29819 +typedef struct reassocreq_frame_body {
29820 + u16 cap_info __WLAN_ATTRIB_PACK__;
29821 + u16 listen_int __WLAN_ATTRIB_PACK__;
29822 + u8 current_ap[ETH_ALEN] __WLAN_ATTRIB_PACK__;
29823 + wlan_ie_ssid_t ssid __WLAN_ATTRIB_PACK__;
29824 +/* access to this one is disabled since ssid_t is variable length: */
29825 + /* wlan_ie_supp_rates_t rates __WLAN_ATTRIB_PACK__; */
29826 +} reassocreq_frame_body_t;
29828 +typedef struct reassocresp_frame_body {
29829 + u16 cap_info __WLAN_ATTRIB_PACK__;
29830 + u16 status __WLAN_ATTRIB_PACK__;
29831 + u16 aid __WLAN_ATTRIB_PACK__;
29832 + wlan_ie_supp_rates_t rates __WLAN_ATTRIB_PACK__;
29833 +} reassocresp_frame_body_t;
29835 +typedef struct deauthen_frame_body {
29836 + u16 reason __WLAN_ATTRIB_PACK__;
29837 +} deauthen_frame_body_t;
29839 +typedef struct disassoc_frame_body {
29840 + u16 reason __WLAN_ATTRIB_PACK__;
29841 +} disassoc_frame_body_t;
29843 +typedef struct probereq_frame_body {
29844 + wlan_ie_ssid_t ssid __WLAN_ATTRIB_PACK__;
29845 + wlan_ie_supp_rates_t rates __WLAN_ATTRIB_PACK__;
29846 +} probereq_frame_body_t;
29848 +typedef struct proberesp_frame_body {
29849 + u8 timestamp[8] __WLAN_ATTRIB_PACK__;
29850 + u16 beacon_int __WLAN_ATTRIB_PACK__;
29851 + u16 cap_info __WLAN_ATTRIB_PACK__;
29852 + wlan_ie_ssid_t ssid __WLAN_ATTRIB_PACK__;
29853 +/* access to these is disabled since ssid_t is variable length: */
29854 + /* wlan_ie_supp_rates_t rates __WLAN_ATTRIB_PACK__; */
29855 + /* fhps_t fhps __WLAN_ATTRIB_PACK__; */
29856 + /* dsps_t dsps __WLAN_ATTRIB_PACK__; */
29857 + /* cfps_t cfps __WLAN_ATTRIB_PACK__; */
29858 +} proberesp_frame_body_t;
29861 +/***********************************************************************
29865 +/* Helpers for parsing mgmt frames */
29866 +void wlan_mgmt_decode_ibssatim(wlan_fr_ibssatim_t *f);
29867 +void wlan_mgmt_decode_assocreq(wlan_fr_assocreq_t *f);
29868 +void wlan_mgmt_decode_assocresp(wlan_fr_assocresp_t *f);
29869 +void wlan_mgmt_decode_authen(wlan_fr_authen_t *f);
29870 +void wlan_mgmt_decode_beacon(wlan_fr_beacon_t *f);
29871 +void wlan_mgmt_decode_deauthen(wlan_fr_deauthen_t *f);
29872 +void wlan_mgmt_decode_disassoc(wlan_fr_disassoc_t *f);
29873 +void wlan_mgmt_decode_probereq(wlan_fr_probereq_t *f);
29874 +void wlan_mgmt_decode_proberesp(wlan_fr_proberesp_t *f);
29875 +void wlan_mgmt_decode_reassocreq(wlan_fr_reassocreq_t *f);
29876 +void wlan_mgmt_decode_reassocresp(wlan_fr_reassocresp_t *f);
29878 +/* Helpers for building mgmt frames */
29880 +wlan_fill_ie_ssid(u8 *p, int len, const char *ssid)
29882 + struct wlan_ie_ssid *ie = (void*)p;
29883 + ie->eid = WLAN_EID_SSID;
29885 + memcpy(ie->ssid, ssid, len);
29886 + return p + len + 2;
29888 +/* This controls whether we create 802.11g 'ext supported rates' IEs
29889 +** or just create overlong 'supported rates' IEs instead
29890 +** (non-11g compliant) */
29891 +#define WE_OBEY_802_11G 1
29893 +wlan_fill_ie_rates(u8 *p, int len, const u8 *rates)
29895 + struct wlan_ie_supp_rates *ie = (void*)p;
29896 +#if WE_OBEY_802_11G
29897 + if (len > 8 ) len = 8;
29899 + /* supported rates (1 to 8 octets) */
29900 + ie->eid = WLAN_EID_SUPP_RATES;
29902 + memcpy(ie->rates, rates, len);
29903 + return p + len + 2;
29905 +/* This one wouldn't create an IE at all if not needed */
29907 +wlan_fill_ie_rates_ext(u8 *p, int len, const u8 *rates)
29909 + struct wlan_ie_supp_rates *ie = (void*)p;
29910 +#if !WE_OBEY_802_11G
29914 + if (len < 0) return p;
29915 + /* ext supported rates */
29916 + ie->eid = WLAN_EID_EXT_RATES;
29918 + memcpy(ie->rates, rates+8, len);
29919 + return p + len + 2;
29922 +wlan_fill_ie_ds_parms(u8 *p, int channel)
29924 + struct wlan_ie_ds_parms *ie = (void*)p;
29925 + ie->eid = WLAN_EID_DS_PARMS;
29927 + ie->curr_ch = channel;
29928 + return p + sizeof(*ie);
29931 +wlan_fill_ie_ibss_parms(u8 *p, int atim_win)
29933 + struct wlan_ie_ibss_parms *ie = (void*)p;
29934 + ie->eid = WLAN_EID_IBSS_PARMS;
29936 + ie->atim_win = atim_win;
29937 + return p + sizeof(*ie);
29940 +wlan_fill_ie_tim(u8 *p, int rem, int period, int bcast,
29941 + int ofs, int len, const u8 *vbm)
29943 + struct wlan_ie_tim *ie = (void*)p;
29944 + ie->eid = WLAN_EID_TIM;
29945 + ie->len = len + 3;
29946 + ie->dtim_cnt = rem;
29947 + ie->dtim_period = period;
29948 + ie->bitmap_ctl = ofs | (bcast!=0);
29950 + memcpy(ie->virt_bm, vbm, len); /* min 1 byte */
29952 + ie->virt_bm[0] = 0;
29953 + return p + len + 3 + 2;
29955 diff -Naur linux-2.6.14-omap2/drivers/ssi/omap-tsc2101.c linux-h6300-omap2-2.6.14.3/drivers/ssi/omap-tsc2101.c
29956 --- linux-2.6.14-omap2/drivers/ssi/omap-tsc2101.c 2005-12-02 01:53:33.000000000 +0200
29957 +++ linux-h6300-omap2-2.6.14.3/drivers/ssi/omap-tsc2101.c 2005-10-22 03:52:45.000000000 +0300
29958 @@ -36,10 +36,11 @@
29959 #include <asm/arch/hardware.h>
29960 #include <asm/hardware/tsc2101.h>
29961 #include <asm/arch/gpioexpander.h>
29962 +#include <asm/arch/gpio.h>
29964 #include "omap-tsc2101.h"
29966 -#if CONFIG_ARCH_OMAP16XX
29967 +#if CONFIG_ARCH_OMAP1
29968 #include <../drivers/ssi/omap-uwire.h>
29970 #error "Unsupported configuration"
29971 @@ -66,27 +67,28 @@
29972 if (count++ == 0) {
29974 /* set the Mux to provide MCLK to TSC2101 */
29975 - if (machine_is_omap_h3()) {
29976 + if (machine_is_omap_h3())
29977 ret = omap_cfg_reg(V5_1710_MCLK_ON);
29979 - if (machine_is_omap_h2()) {
29980 - ret = omap_cfg_reg(R10_1610_MCLK_ON);
29981 + else if (machine_is_omap_h2())
29982 + ret = omap_cfg_reg(R10_1610_MCLK_ON);
29983 + else if (machine_is_h6300 ())
29984 + ret = omap_cfg_reg(R10_1510_MCLK_ON);
29986 + if (!cpu_is_omap1510 ()) {
29987 + /* Get the MCLK */
29988 + tsc2101_mclk_ck = clk_get(NULL, "mclk");
29989 + if (NULL == tsc2101_mclk_ck) {
29990 + printk(KERN_ERR "Unable to get the clock MCLK!!!\n");;
29996 - /* Get the MCLK */
29997 - tsc2101_mclk_ck = clk_get(NULL, "mclk");
29998 - if (NULL == tsc2101_mclk_ck) {
29999 - printk(KERN_ERR "Unable to get the clock MCLK!!!\n");;
30003 - if (clk_set_rate(tsc2101_mclk_ck, 12000000)) {
30004 - printk(KERN_ERR "Unable to set rate to the MCLK!!!\n");;
30008 - clk_enable(tsc2101_mclk_ck);
30009 + if (clk_set_rate(tsc2101_mclk_ck, 12000000)) {
30010 + printk(KERN_ERR "Unable to set rate to the MCLK!!!\n");;
30014 + clk_enable(tsc2101_mclk_ck);
30015 + } /* if (!cpu_is_omap1510 ()) */
30017 ret = omap_tsc2101_configure();
30019 @@ -116,10 +118,16 @@
30023 - /* Release the MCLK */
30024 - clk_disable(tsc2101_mclk_ck);
30025 - clk_put(tsc2101_mclk_ck);
30026 - tsc2101_mclk_ck = NULL;
30027 + if (!cpu_is_omap1510 ()) {
30028 + /* Release the MCLK */
30029 + clk_disable(tsc2101_mclk_ck);
30030 + clk_put(tsc2101_mclk_ck);
30031 + tsc2101_mclk_ck = NULL;
30034 +#if defined(CONFIG_MACH_OMAP_H6300)
30035 + omap_free_gpio(8);
30038 module_put(THIS_MODULE);
30040 @@ -150,7 +158,10 @@
30044 - if (machine_is_omap_h3()) {
30045 + if (machine_is_omap_h3() || machine_is_h6300 ()) {
30047 + if (machine_is_h6300 ())
30048 + omap_set_gpio_dataout (8, 0);
30051 omap_uwire_data_transfer(0, ((page << 11) | (address << 5)),
30052 @@ -159,6 +170,8 @@
30054 "uwire-write returned error for address %x\n",
30056 + if (machine_is_h6300 ())
30057 + omap_set_gpio_dataout (8, 1);
30060 ret = omap_uwire_data_transfer(0, data, 16, 0, NULL, 0);
30061 @@ -166,10 +179,14 @@
30063 "uwire-write returned error for address %x\n",
30065 + if (machine_is_h6300 ())
30066 + omap_set_gpio_dataout (8, 1);
30071 + if (machine_is_h6300 ())
30072 + omap_set_gpio_dataout (8, 1);
30076 void omap_tsc2101_reads(int page, u8 startaddress, u16 * data, int numregs)
30077 @@ -178,9 +195,13 @@
30078 if (machine_is_omap_h2()) {
30081 - if (machine_is_omap_h3()) {
30082 + if (machine_is_omap_h3() || machine_is_h6300 ()) {
30086 + if (machine_is_h6300 ())
30087 + omap_set_gpio_dataout(8, 0);
30089 (void)omap_uwire_data_transfer(cs, (0x8000 | (page << 11)
30090 | (startaddress << 5)),
30092 @@ -188,6 +209,9 @@
30093 omap_uwire_data_transfer(cs, 0, 0, 16, data, 1);
30095 omap_uwire_data_transfer(cs, 0, 0, 16, data, 0);
30097 + if (machine_is_h6300 ())
30098 + omap_set_gpio_dataout(8, 1);
30101 u16 omap_tsc2101_read(int page, u8 address)
30102 @@ -228,9 +252,24 @@
30103 omap_cfg_reg(N14_1610_UWIRE_CS0);
30104 omap_uwire_configure_mode(0, uwire_flags);
30106 + if (machine_is_h6300()) {
30107 + uwire_flags = UWIRE_READ_RISING_EDGE | UWIRE_WRITE_RISING_EDGE;
30108 + omap_cfg_reg(N14_1510_UWIRE_CS0);
30109 + omap_uwire_configure_mode(0, uwire_flags);
30111 + omap_request_gpio(8);
30112 + omap_set_gpio_dataout(8, 0);
30113 + omap_set_gpio_direction (8, 0);
30116 /* Configure MCLK enable */
30117 - omap_writel(omap_readl(PU_PD_SEL_2) | (1 << 22), PU_PD_SEL_2);
30118 + if (cpu_is_omap16xx() || cpu_is_omap1710())
30119 + omap_writel(omap_readl(PU_PD_SEL_2) | (1 << 22), PU_PD_SEL_2);
30120 + if (machine_is_h6300()) {
30121 + omap_cfg_reg(V19_1510_UWIRE_SCLK);
30122 + omap_cfg_reg(W21_1510_UWIRE_SDO);
30123 + omap_cfg_reg(U18_1510_UWIRE_SDI);
30128 @@ -243,5 +282,5 @@
30130 MODULE_AUTHOR("Texas Instruments");
30132 - ("Glue audio driver for the TI OMAP1610/OMAP1710 TSC2101 codec.");
30133 + ("Glue audio driver for the TI OMAP1510/1610/OMAP1710 TSC2101 codec.");
30134 MODULE_LICENSE("GPL");
30135 diff -Naur linux-2.6.14-omap2/drivers/ssi/omap-uwire.c linux-h6300-omap2-2.6.14.3/drivers/ssi/omap-uwire.c
30136 --- linux-2.6.14-omap2/drivers/ssi/omap-uwire.c 2005-12-02 01:53:33.000000000 +0200
30137 +++ linux-h6300-omap2-2.6.14.3/drivers/ssi/omap-uwire.c 2005-08-12 13:46:22.000000000 +0300
30138 @@ -212,6 +212,10 @@
30139 omap_cfg_reg(N14_1610_UWIRE_CS0);
30140 omap_cfg_reg(P15_1610_UWIRE_CS3);
30142 + if (machine_is_h6300 ()) {
30143 + omap_cfg_reg(N14_1510_UWIRE_CS0);
30144 + omap_cfg_reg(P15_1510_UWIRE_CS3);
30146 if (machine_is_omap_perseus2()) {
30147 /* configure pins: MPU_UW_nSCS1, MPU_UW_SDO, MPU_UW_SCLK */
30148 int val = omap_readl(OMAP730_IO_CONF_9) & ~0x00EEE000;
30149 diff -Naur linux-2.6.14-omap2/drivers/telephony/Kconfig linux-h6300-omap2-2.6.14.3/drivers/telephony/Kconfig
30150 --- linux-2.6.14-omap2/drivers/telephony/Kconfig 2005-10-28 03:02:08.000000000 +0300
30151 +++ linux-h6300-omap2-2.6.14.3/drivers/telephony/Kconfig 2005-10-06 02:34:39.000000000 +0300
30154 Say Y here to configure in PCMCIA service support for the Quicknet
30155 cards manufactured by Quicknet Technologies, Inc. This changes the
30156 - card initialization code to work with the card manager daemon.
30157 + card initialization code to work with the card manager daemon.
30160 + tristate "H6300 P5186 GSM/GPRS DRIVER"
30161 + depends on PHONE && I2C && PCA9535
30163 + Bluetooth H6300 P5186 gsm/gprs driver.
30164 + This driver provides the firmware loading mechanism for the P5185
30165 + gsm/gprs hardware in iPAQ h6300.
30167 + Say Y here to compile support for P5186 gsm/gprs devices into the
30168 + kernel or say M to compile it as module (h6300_gsm).
30172 diff -Naur linux-2.6.14-omap2/drivers/telephony/Makefile linux-h6300-omap2-2.6.14.3/drivers/telephony/Makefile
30173 --- linux-2.6.14-omap2/drivers/telephony/Makefile 2005-10-28 03:02:08.000000000 +0300
30174 +++ linux-h6300-omap2-2.6.14.3/drivers/telephony/Makefile 2005-10-06 02:34:39.000000000 +0300
30176 # Makefile for drivers/telephony
30179 -obj-$(CONFIG_PHONE) += phonedev.o
30180 -obj-$(CONFIG_PHONE_IXJ) += ixj.o
30181 -obj-$(CONFIG_PHONE_IXJ_PCMCIA) += ixj_pcmcia.o
30182 +obj-$(CONFIG_PHONE) += phonedev.o
30183 +obj-$(CONFIG_PHONE_IXJ) += ixj.o
30184 +obj-$(CONFIG_PHONE_IXJ_PCMCIA) += ixj_pcmcia.o
30185 +obj-$(CONFIG_GSM_H6300) += omap/
30186 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
30187 --- linux-2.6.14-omap2/drivers/telephony/omap/h6300_gsm_led.c 1970-01-01 02:00:00.000000000 +0200
30188 +++ linux-h6300-omap2-2.6.14.3/drivers/telephony/omap/h6300_gsm_led.c 2005-10-06 02:34:39.000000000 +0300
30191 + * GSM interface driver helper for controlling bluetooth leds available in iPAQ h6300.
30193 + * Copyright (C) 2005 Mika Laitio <lamikr@cc.jyu.fi>
30195 + * This program is free software; you can redistribute it and/or modify
30196 + * it under the terms of the GNU General Public License version 2 as
30197 + * published by the Free Software Foundation.
30200 +#include <linux/module.h>
30201 +#include <linux/kernel.h>
30202 +#include <linux/delay.h>
30203 +#include <linux/device.h>
30205 +#include <asm/hardware.h>
30206 +#include <asm/arch/gpio.h>
30209 + * Low level access for disabling h6300 gsm led.
30211 + * TODO: implement for h6300
30213 +void h6300_clear_gsm_led(int led_num)
30215 + printk(KERN_NOTICE "h6300_gsm_led.c h6300_clear_gsm_led() done\n");
30216 + //hx4700_set_led(led_num, 0, 16);
30218 +EXPORT_SYMBOL(h6300_clear_gsm_led);
30221 + * Low level access for setting up the gsm led.
30223 + * TODO: implement for h6300
30225 +void h6300_set_gsm_led(int led_num, int duty_time, int cycle_time)
30227 + printk(KERN_NOTICE "h6300_gsm_led.c h6300_set_gsm_led() done\n");
30229 +EXPORT_SYMBOL(h6300_set_gsm_led);
30230 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
30231 --- linux-2.6.14-omap2/drivers/telephony/omap/h6300_gsm_led.h 1970-01-01 02:00:00.000000000 +0200
30232 +++ linux-h6300-omap2-2.6.14.3/drivers/telephony/omap/h6300_gsm_led.h 2005-10-06 02:34:39.000000000 +0300
30234 +#ifndef H6300_GSM_LED_H_
30235 +#define H6300_GSM_LED_H_
30237 +#define INDEX_GSM_LED 1
30239 +void h6300_clear_gsm_led(int led_num);
30240 +void h6300_set_gsm_led(int led_num, int duty_time, int cycle_time);
30243 +#endif /*H6300_GSM_LED_H_*/
30244 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
30245 --- linux-2.6.14-omap2/drivers/telephony/omap/h6300_gsm_p5186.c 1970-01-01 02:00:00.000000000 +0200
30246 +++ linux-h6300-omap2-2.6.14.3/drivers/telephony/omap/h6300_gsm_p5186.c 2005-10-20 20:57:07.000000000 +0300
30249 + * Wavecom P5186 GPRS and GSM module driver for iPAQ h6300.
30251 + * Copyright (C) 2005 Mika Laitio <lamikr@cc.jyu.fi>
30253 + * This program is free software; you can redistribute it and/or modify
30254 + * it under the terms of the GNU General Public License version 2 as
30255 + * published by the Free Software Foundation.
30258 +#include <linux/module.h>
30259 +#include <linux/kernel.h>
30260 +#include <linux/delay.h>
30261 +#include <linux/device.h>
30263 +#include <asm/hardware.h>
30264 +#include <asm/arch/gpio.h>
30266 +#include <asm/arch/pca9535.h>
30267 +#include <asm/arch/h6300_uart_info.h>
30268 +#include "h6300_gsm_led.h"
30271 +h6300_gsm_configure(struct uart_omap_port *up, int enable)
30273 + printk(KERN_NOTICE "h6300_gsm_p5186.c h6300_gsm_configure() started, enable = %d\n", enable);
30275 + // printk( KERN_NOTICE "h6300 configure bluetooth: %d\n", enable );
30276 + if (enable == 0) {
30277 + pca9535_gpio_write(GPIO_I2C_GPRS_RESET, GPIO_VALUE_OFF); // turn off gpio
30279 + h6300_clear_gsm_led(INDEX_GSM_LED);
30281 + else if (enable == 1) {
30282 + pca9535_gpio_write(GPIO_I2C_GPRS_RESET, GPIO_VALUE_ON); // turn on gpio
30285 + else if (enable == 2) {
30286 + h6300_set_gsm_led(INDEX_GSM_LED, 16, 16);
30288 + printk(KERN_NOTICE "h6300_gsm_p5186.c h6300_gsm_configure() done\n");
30292 +h6300_gsm_set_txrx(struct uart_omap_port *up, int txrx)
30294 + printk(KERN_NOTICE "h6300_gsm_p5186.c h6300_gsm_set_txrx(), txrx = %d done\n", txrx);
30299 +h6300_gsm_get_txrx(struct uart_omap_port *up)
30301 + printk(KERN_NOTICE "h6300_gsm_p5186.c h6300_gsm_get_txrx() done\n");
30307 +h6300_gsm_probe(struct device *dev)
30312 + struct h6300_uart_funcs *funcs = (struct h6300_uart_funcs *)dev->platform_data;
30314 + printk(KERN_NOTICE "h6300_gsm_p5186.c h6300_gsm_probe() started\n");
30315 + for (ii = 0; ii < 8; ii++)
30317 + curVal = pca9535_gpio_read(ii);
30318 + printk(KERN_NOTICE "I2C[%d] = %d ", ii, curVal);
30320 + for (ii = 10; ii < 18; ii++)
30322 + curVal = pca9535_gpio_read(ii);
30323 + printk(KERN_NOTICE "I2C[%d] = %d ", ii, curVal);
30325 + printk(KERN_NOTICE "\nfirst check done\n");
30327 + pca9535_gpio_direction(GPIO_I2C_GPRS_RESET, GPIO_DIR_OUTPUT); // set gpio direction to be output
30328 + pca9535_gpio_write(GPIO_I2C_GPRS_RESET, GPIO_VALUE_ON); // turn on gpio
30331 + pca9535_gpio_direction(GPIO_I2C_MIC_OP_EN, GPIO_DIR_OUTPUT); // set gpio direction to be output
30332 + pca9535_gpio_write(GPIO_I2C_MIC_OP_EN, GPIO_VALUE_ON); // turn on gpio
30335 + pca9535_gpio_direction(GPIO_I2C_SPK_OP_PD, GPIO_DIR_OUTPUT); // set gpio direction to be output
30336 + pca9535_gpio_write(GPIO_I2C_SPK_OP_PD, GPIO_VALUE_ON); // pd = pulldown?, normal off = on
30340 + //pca9535_gpio_direction(
30341 + /* configure bluetooth UART */
30342 + //h6300_gpio_mode(GPIO_NR_H6300_BT_RXD_MD);
30343 + //h6300_gpio_mode(GPIO_NR_H6300_BT_TXD_MD);
30344 + //h6300_gpio_mode(GPIO_NR_H6300_BT_UART_CTS_MD);
30345 + //h6300_gpio_mode(GPIO_NR_H6300_BT_UART_RTS_MD);
30347 + funcs->configure = h6300_gsm_configure;
30348 + funcs->set_txrx = h6300_gsm_set_txrx;
30349 + funcs->get_txrx = h6300_gsm_get_txrx;
30351 + /* Make sure the LED is off */
30352 + h6300_clear_gsm_led(INDEX_GSM_LED);
30354 + for (ii = 0; ii < 8; ii++)
30356 + curVal = pca9535_gpio_read(ii);
30357 + printk(KERN_NOTICE "I2C[%d] = %d ", ii, curVal);
30359 + for (ii = 10; ii < 18; ii++)
30361 + curVal = pca9535_gpio_read(ii);
30362 + printk(KERN_NOTICE "I2C[%d] = %d ", ii, curVal);
30365 + printk(KERN_NOTICE "\nh6300_gsm_p5186.c h6300_gsm_probe() done\n");
30371 +h6300_gsm_remove(struct device *dev)
30373 + struct h6300_uart_funcs *funcs = (struct h6300_uart_funcs *)dev->platform_data;
30375 + printk(KERN_NOTICE "h6300_gsm_p5186.c h6300_gsm_remove() started\n");
30377 + pca9535_gpio_write(GPIO_I2C_GPRS_RESET, 0); // turn off gpio
30379 + funcs->configure = NULL;
30380 + funcs->set_txrx = NULL;
30381 + funcs->get_txrx = NULL;
30383 + /* Make sure the LED is off */
30384 + h6300_clear_gsm_led(INDEX_GSM_LED);
30386 + printk(KERN_NOTICE "h6300_gsm_p5186.c, h6300_gsm_remove() done\n");
30391 +static struct device_driver gsm_driver = {
30392 + .name = "h6300_gsm",
30393 + .bus = &platform_bus_type,
30394 + .probe = h6300_gsm_probe,
30395 + .remove = h6300_gsm_remove,
30399 +h6300_gsm_init(void)
30401 + printk(KERN_NOTICE "h6300 GSM Driver init()\n");
30402 + return driver_register(&gsm_driver);
30405 +static void __exit
30406 +h6300_gsm_exit(void)
30408 + printk(KERN_NOTICE "h6300 GSM Driver exit()\n");
30409 + driver_unregister(&gsm_driver);
30412 +module_init(h6300_gsm_init);
30413 +module_exit(h6300_gsm_exit);
30415 +MODULE_AUTHOR("Mika Laitio, <lamikr@cc.jyu.fi>");
30416 +MODULE_DESCRIPTION("iPAQ h6300 Wavecom P5186 GPRS and GSM module driver.");
30417 +MODULE_LICENSE("GPL");
30419 diff -Naur linux-2.6.14-omap2/drivers/telephony/omap/Makefile linux-h6300-omap2-2.6.14.3/drivers/telephony/omap/Makefile
30420 --- linux-2.6.14-omap2/drivers/telephony/omap/Makefile 1970-01-01 02:00:00.000000000 +0200
30421 +++ linux-h6300-omap2-2.6.14.3/drivers/telephony/omap/Makefile 2005-10-06 02:34:39.000000000 +0300
30424 +# Makefile for the Linux iPAQ H6300 BRF6100 Bluetooth device drivers.
30427 +h6300_gsm-objs := h6300_gsm_led.o h6300_gsm_p5186.o
30428 +obj-$(CONFIG_GSM_H6300) += h6300_gsm.o
30429 diff -Naur linux-2.6.14-omap2/drivers/usb/core/sysfs.c linux-h6300-omap2-2.6.14.3/drivers/usb/core/sysfs.c
30430 --- linux-2.6.14-omap2/drivers/usb/core/sysfs.c 2005-10-28 03:02:08.000000000 +0300
30431 +++ linux-h6300-omap2-2.6.14.3/drivers/usb/core/sysfs.c 2005-11-23 01:44:02.000000000 +0200
30432 @@ -292,30 +292,23 @@
30434 struct usb_interface *intf;
30435 struct usb_device *udev;
30437 + struct usb_host_interface *alt;
30439 intf = to_usb_interface(dev);
30440 udev = interface_to_usbdev(intf);
30441 + alt = intf->cur_altsetting;
30443 - len = sprintf(buf, "usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic",
30444 - le16_to_cpu(udev->descriptor.idVendor),
30445 - le16_to_cpu(udev->descriptor.idProduct),
30446 - le16_to_cpu(udev->descriptor.bcdDevice),
30447 - udev->descriptor.bDeviceClass,
30448 - udev->descriptor.bDeviceSubClass,
30449 - udev->descriptor.bDeviceProtocol);
30452 - if (udev->descriptor.bDeviceClass == 0) {
30453 - struct usb_host_interface *alt = intf->cur_altsetting;
30455 - return len + sprintf(buf, "%02Xisc%02Xip%02X\n",
30456 - alt->desc.bInterfaceClass,
30457 - alt->desc.bInterfaceSubClass,
30458 - alt->desc.bInterfaceProtocol);
30460 - return len + sprintf(buf, "*isc*ip*\n");
30462 + return sprintf(buf, "usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02X"
30463 + "ic%02Xisc%02Xip%02X\n",
30464 + le16_to_cpu(udev->descriptor.idVendor),
30465 + le16_to_cpu(udev->descriptor.idProduct),
30466 + le16_to_cpu(udev->descriptor.bcdDevice),
30467 + udev->descriptor.bDeviceClass,
30468 + udev->descriptor.bDeviceSubClass,
30469 + udev->descriptor.bDeviceProtocol,
30470 + alt->desc.bInterfaceClass,
30471 + alt->desc.bInterfaceSubClass,
30472 + alt->desc.bInterfaceProtocol);
30474 static DEVICE_ATTR(modalias, S_IRUGO, show_modalias, NULL);
30476 diff -Naur linux-2.6.14-omap2/drivers/usb/core/usb.c linux-h6300-omap2-2.6.14.3/drivers/usb/core/usb.c
30477 --- linux-2.6.14-omap2/drivers/usb/core/usb.c 2005-10-28 03:02:08.000000000 +0300
30478 +++ linux-h6300-omap2-2.6.14.3/drivers/usb/core/usb.c 2005-11-23 01:44:02.000000000 +0200
30479 @@ -557,6 +557,7 @@
30481 struct usb_interface *intf;
30482 struct usb_device *usb_dev;
30483 + struct usb_host_interface *alt;
30487 @@ -573,7 +574,8 @@
30489 intf = to_usb_interface(dev);
30490 usb_dev = interface_to_usbdev (intf);
30492 + alt = intf->cur_altsetting;
30494 if (usb_dev->devnum < 0) {
30495 pr_debug ("usb %s: already deleted?\n", dev->bus_id);
30497 @@ -615,46 +617,27 @@
30498 usb_dev->descriptor.bDeviceProtocol))
30501 - if (usb_dev->descriptor.bDeviceClass == 0) {
30502 - struct usb_host_interface *alt = intf->cur_altsetting;
30503 + if (add_hotplug_env_var(envp, num_envp, &i,
30504 + buffer, buffer_size, &length,
30505 + "INTERFACE=%d/%d/%d",
30506 + alt->desc.bInterfaceClass,
30507 + alt->desc.bInterfaceSubClass,
30508 + alt->desc.bInterfaceProtocol))
30511 - /* 2.4 only exposed interface zero. in 2.5, hotplug
30512 - * agents are called for all interfaces, and can use
30513 - * $DEVPATH/bInterfaceNumber if necessary.
30515 - if (add_hotplug_env_var(envp, num_envp, &i,
30516 - buffer, buffer_size, &length,
30517 - "INTERFACE=%d/%d/%d",
30518 - alt->desc.bInterfaceClass,
30519 - alt->desc.bInterfaceSubClass,
30520 - alt->desc.bInterfaceProtocol))
30523 - if (add_hotplug_env_var(envp, num_envp, &i,
30524 - buffer, buffer_size, &length,
30525 - "MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X",
30526 - le16_to_cpu(usb_dev->descriptor.idVendor),
30527 - le16_to_cpu(usb_dev->descriptor.idProduct),
30528 - le16_to_cpu(usb_dev->descriptor.bcdDevice),
30529 - usb_dev->descriptor.bDeviceClass,
30530 - usb_dev->descriptor.bDeviceSubClass,
30531 - usb_dev->descriptor.bDeviceProtocol,
30532 - alt->desc.bInterfaceClass,
30533 - alt->desc.bInterfaceSubClass,
30534 - alt->desc.bInterfaceProtocol))
30537 - if (add_hotplug_env_var(envp, num_envp, &i,
30538 - buffer, buffer_size, &length,
30539 - "MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic*isc*ip*",
30540 - le16_to_cpu(usb_dev->descriptor.idVendor),
30541 - le16_to_cpu(usb_dev->descriptor.idProduct),
30542 - le16_to_cpu(usb_dev->descriptor.bcdDevice),
30543 - usb_dev->descriptor.bDeviceClass,
30544 - usb_dev->descriptor.bDeviceSubClass,
30545 - usb_dev->descriptor.bDeviceProtocol))
30548 + if (add_hotplug_env_var(envp, num_envp, &i,
30549 + buffer, buffer_size, &length,
30550 + "MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X",
30551 + le16_to_cpu(usb_dev->descriptor.idVendor),
30552 + le16_to_cpu(usb_dev->descriptor.idProduct),
30553 + le16_to_cpu(usb_dev->descriptor.bcdDevice),
30554 + usb_dev->descriptor.bDeviceClass,
30555 + usb_dev->descriptor.bDeviceSubClass,
30556 + usb_dev->descriptor.bDeviceProtocol,
30557 + alt->desc.bInterfaceClass,
30558 + alt->desc.bInterfaceSubClass,
30559 + alt->desc.bInterfaceProtocol))
30564 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
30565 --- linux-2.6.14-omap2/drivers/usb/gadget/omap_udc.c 2005-12-02 01:53:33.000000000 +0200
30566 +++ linux-h6300-omap2-2.6.14.3/drivers/usb/gadget/omap_udc.c 2005-11-11 04:13:42.000000000 +0200
30570 /* bulk DMA seems to be behaving for both IN and OUT */
30577 @@ -2109,7 +2110,7 @@
30578 /* boards that don't have VBUS sensing can't autogate 48MHz;
30579 * can't enter deep sleep while a gadget driver is active.
30581 - if (machine_is_omap_innovator() || machine_is_omap_osk())
30582 + if (machine_is_omap_innovator() || machine_is_omap_osk() || machine_is_h6300())
30583 omap_vbus_session(&udc->gadget, 1);
30586 @@ -2127,7 +2128,7 @@
30587 if (!driver || driver != udc->driver)
30590 - if (machine_is_omap_innovator() || machine_is_omap_osk())
30591 + if (machine_is_omap_innovator() || machine_is_omap_osk() || machine_is_h6300())
30592 omap_vbus_session(&udc->gadget, 0);
30594 if (udc->transceiver)
30595 @@ -2735,7 +2736,7 @@
30597 type = "(unknown)";
30599 - if (machine_is_omap_innovator()) {
30600 + if (machine_is_omap_innovator() || machine_is_h6300()) {
30601 /* just set up software VBUS detect, and then
30602 * later rig it so we always report VBUS.
30603 * FIXME without really sensing VBUS, we can't
30604 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
30605 --- linux-2.6.14-omap2/drivers/video/omap/lcd_h6300.c 1970-01-01 02:00:00.000000000 +0200
30606 +++ linux-h6300-omap2-2.6.14.3/drivers/video/omap/lcd_h6300.c 2005-11-11 04:13:42.000000000 +0200
30609 + * File: drivers/video/omap_new/lcd-h6300.c
30611 + * LCD panel support for the TI OMAP1510 Innovator board
30613 + * Copyright (C) 2004 Nokia Corporation
30614 + * Author: Imre Deak <imre.deak@nokia.com>
30616 + * This program is free software; you can redistribute it and/or modify it
30617 + * under the terms of the GNU General Public License as published by the
30618 + * Free Software Foundation; either version 2 of the License, or (at your
30619 + * option) any later version.
30621 + * This program is distributed in the hope that it will be useful, but
30622 + * WITHOUT ANY WARRANTY; without even the implied warranty of
30623 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
30624 + * General Public License for more details.
30626 + * You should have received a copy of the GNU General Public License along
30627 + * with this program; if not, write to the Free Software Foundation, Inc.,
30628 + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
30631 +#include <linux/module.h>
30632 +#include <asm/io.h>
30634 +#include <asm/hardware/clock.h>
30635 +#include <asm/arch/omapfb.h>
30637 +/* #define OMAPFB_DBG 1 */
30639 +#include "debug.h"
30641 +//static struct clk *h6300_lcd_ck;
30643 +static int h6300_panel_init(struct omapfb_device *fbdev)
30647 + if ((h6300_lcd_ck = clk_get (NULL, "lcd_ck")) == NULL) {
30648 + printk(KERN_ERR "Unable to get the clock LCD_CK!!!\n");
30650 + } clk_enable(h6300_lcd_ck);
30653 + printk(KERN_INFO "lcd_h6300.c: h6300_panel_init() done\n");
30657 +static void h6300_panel_cleanup(void)
30661 + if (h6300_lcd_ck) {
30662 + clk_disable(h6300_lcd_ck);
30663 + clk_put (h6300_lcd_ck);
30664 + h6300_lcd_ck = NULL;
30668 + printk(KERN_INFO "lcd_h6300.c: h6300_panel_cleanup() done\n");
30671 +static int h6300_panel_enable(void)
30675 + printk(KERN_INFO "lcd_h6300.c: h6300_panel_enable() done\n");
30679 +static void h6300_panel_disable(void)
30683 + printk(KERN_INFO "lcd_h6300.c: h6300_panel_disable() done\n");
30686 +static unsigned long h6300_panel_get_caps(void)
30688 + printk(KERN_INFO "lcd_h6300.c: h6300_panel_get_caps() called\n");
30692 +struct lcd_panel h6300_panel = {
30694 + .config = OMAP_LCDC_PANEL_TFT,
30697 + .data_lines = 16,
30700 + .pixel_clock = 21000,
30709 + .init = h6300_panel_init,
30710 + .cleanup = h6300_panel_cleanup,
30711 + .enable = h6300_panel_enable,
30712 + .disable = h6300_panel_disable,
30713 + .get_caps = h6300_panel_get_caps,
30715 diff -Naur linux-2.6.14-omap2/drivers/video/omap/Makefile linux-h6300-omap2-2.6.14.3/drivers/video/omap/Makefile
30716 --- linux-2.6.14-omap2/drivers/video/omap/Makefile 2005-12-02 01:53:33.000000000 +0200
30717 +++ linux-h6300-omap2-2.6.14.3/drivers/video/omap/Makefile 2005-10-22 03:52:45.000000000 +0300
30719 objs-$(CONFIG_ARCH_OMAP15XX)$(CONFIG_MACH_OMAP_INNOVATOR) += lcd_inn1510.o
30720 objs-y$(CONFIG_MACH_OMAP_OSK) += lcd_osk.o
30721 objs-y$(CONFIG_MACH_OMAP_PERSEUS2) += lcd_p2.o
30722 +objs-$(CONFIG_ARCH_OMAP15XX)$(CONFIG_MACH_OMAP_H6300) += lcd_h6300.o
30724 omapfb-objs := $(objs-yy)
30726 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
30727 --- linux-2.6.14-omap2/drivers/video/omap/omapfb_main.c 2005-12-02 01:53:33.000000000 +0200
30728 +++ linux-h6300-omap2-2.6.14.3/drivers/video/omap/omapfb_main.c 2005-10-24 19:16:46.000000000 +0300
30730 extern struct lcd_panel innovator1610_panel;
30731 extern struct lcd_panel innovator1510_panel;
30732 extern struct lcd_panel lph8923_panel;
30733 +extern struct lcd_panel h6300_panel;
30735 static struct lcd_panel *panels[] = {
30736 #ifdef CONFIG_MACH_OMAP_H2
30737 @@ -109,6 +110,9 @@
30738 #ifdef CONFIG_MACH_OMAP_PALMTE
30741 +#ifdef CONFIG_MACH_OMAP_H6300
30745 #ifdef CONFIG_MACH_OMAP_INNOVATOR
30747 diff -Naur linux-2.6.14-omap2/fs/exec.c linux-h6300-omap2-2.6.14.3/fs/exec.c
30748 --- linux-2.6.14-omap2/fs/exec.c 2005-10-28 03:02:08.000000000 +0300
30749 +++ linux-h6300-omap2-2.6.14.3/fs/exec.c 2005-11-23 01:44:02.000000000 +0200
30750 @@ -593,6 +593,7 @@
30751 struct signal_struct *sig = tsk->signal;
30752 struct sighand_struct *newsighand, *oldsighand = tsk->sighand;
30753 spinlock_t *lock = &oldsighand->siglock;
30754 + struct task_struct *leader = NULL;
30758 @@ -668,7 +669,7 @@
30759 * and to assume its PID:
30761 if (!thread_group_leader(current)) {
30762 - struct task_struct *leader = current->group_leader, *parent;
30763 + struct task_struct *parent;
30764 struct dentry *proc_dentry1, *proc_dentry2;
30765 unsigned long exit_state, ptrace;
30767 @@ -677,6 +678,7 @@
30768 * It should already be zombie at this point, most
30771 + leader = current->group_leader;
30772 while (leader->exit_state != EXIT_ZOMBIE)
30775 @@ -736,7 +738,6 @@
30776 proc_pid_flush(proc_dentry2);
30778 BUG_ON(exit_state != EXIT_ZOMBIE);
30779 - release_task(leader);
30783 @@ -746,8 +747,11 @@
30787 - BUG_ON(atomic_read(&sig->count) != 1);
30790 + release_task(leader);
30792 + BUG_ON(atomic_read(&sig->count) != 1);
30794 if (atomic_read(&oldsighand->count) == 1) {
30796 diff -Naur linux-2.6.14-omap2/fs/locks.c linux-h6300-omap2-2.6.14.3/fs/locks.c
30797 --- linux-2.6.14-omap2/fs/locks.c 2005-10-28 03:02:08.000000000 +0300
30798 +++ linux-h6300-omap2-2.6.14.3/fs/locks.c 2005-12-02 01:34:35.000000000 +0200
30799 @@ -1418,7 +1418,7 @@
30802 error = __setlease(filp, arg, &flp);
30804 + if (error || arg == F_UNLCK)
30807 error = fasync_helper(fd, filp, 1, &flp->fl_fasync);
30808 diff -Naur linux-2.6.14-omap2/fs/xfs/Kconfig linux-h6300-omap2-2.6.14.3/fs/xfs/Kconfig
30809 --- linux-2.6.14-omap2/fs/xfs/Kconfig 2005-10-28 03:02:08.000000000 +0300
30810 +++ linux-h6300-omap2-2.6.14.3/fs/xfs/Kconfig 2005-11-23 01:44:02.000000000 +0200
30815 - tristate "XFS Quota support"
30816 + bool "XFS Quota support"
30819 If you say Y here, you will be able to set limits for disk usage on
30820 diff -Naur linux-2.6.14-omap2/include/asm-alpha/barrier.h linux-h6300-omap2-2.6.14.3/include/asm-alpha/barrier.h
30821 --- linux-2.6.14-omap2/include/asm-alpha/barrier.h 2005-10-28 03:02:08.000000000 +0300
30822 +++ linux-h6300-omap2-2.6.14.3/include/asm-alpha/barrier.h 2005-11-23 01:44:02.000000000 +0200
30824 #ifndef __BARRIER_H
30825 #define __BARRIER_H
30827 +#include <asm/compiler.h>
30830 __asm__ __volatile__("mb": : :"memory")
30832 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
30833 --- linux-2.6.14-omap2/include/asm-arm/arch-omap/board-h6300.h 1970-01-01 02:00:00.000000000 +0200
30834 +++ linux-h6300-omap2-2.6.14.3/include/asm-arm/arch-omap/board-h6300.h 2005-08-12 13:46:22.000000000 +0300
30837 + * linux/include/asm-arm/arch-omap/board-innovator.h
30839 + * Copyright (C) 2001 RidgeRun, Inc.
30841 + * This program is free software; you can redistribute it and/or modify it
30842 + * under the terms of the GNU General Public License as published by the
30843 + * Free Software Foundation; either version 2 of the License, or (at your
30844 + * option) any later version.
30846 + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
30847 + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
30848 + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
30849 + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
30850 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30851 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
30852 + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
30853 + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30854 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30855 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30857 + * You should have received a copy of the GNU General Public License along
30858 + * with this program; if not, write to the Free Software Foundation, Inc.,
30859 + * 675 Mass Ave, Cambridge, MA 02139, USA.
30861 +#ifndef __ASM_ARCH_H6300_H
30862 +#define __ASM_ARCH_H6300_H
30864 +#ifndef OMAP_SDRAM_DEVICE
30865 +#define OMAP_SDRAM_DEVICE D256M_1X16_4B
30868 +#define OMAP1510P1_IMIF_PRI_VALUE 0x00
30869 +#define OMAP1510P1_EMIFS_PRI_VALUE 0x00
30870 +#define OMAP1510P1_EMIFF_PRI_VALUE 0x00
30872 +#define NR_FPGA_IRQS 24
30873 +#define NR_IRQS IH_BOARD_BASE + NR_FPGA_IRQS
30875 +#endif /* __ASM_ARCH_H6300_H */
30876 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
30877 --- linux-2.6.14-omap2/include/asm-arm/arch-omap/h6300_uart_info.h 1970-01-01 02:00:00.000000000 +0200
30878 +++ linux-h6300-omap2-2.6.14.3/include/asm-arm/arch-omap/h6300_uart_info.h 2005-10-14 18:55:31.000000000 +0300
30881 + * Support file for calling h6300 uart configuration functions.
30882 + * Used at least by h6300_bt driver.
30884 + * Copyright (c) 2005 SDG Systems, LLC
30885 + * 2005-03-29 Todd Blumer Converted basic structure to support hx4700
30886 + * 2005-10-03 Mika Laitio (lamikr@cc.jyu.fi) Reorganized for the iPAQ h6300 bt driver.
30889 +#ifndef _H6300_UART_INFO_H
30890 +#define _H6300_UART_INFO_H
30892 +#include "omap_serial.h"
30894 +#define GPIO_BT_PWR_EN 3
30895 +#define GPIO_N_BT_RST 9
30897 +#define GPIO_I2C_GPRS_RESET 16
30898 +#define GPIO_I2C_MIC_OP_EN 10
30899 +#define GPIO_I2C_SPK_OP_PD 11
30901 +#define GPIO_VALUE_OFF 0
30902 +#define GPIO_VALUE_ON 1
30904 +#define GPIO_DIR_OUTPUT 1
30906 +struct h6300_uart_funcs {
30907 + void (*configure)( struct uart_omap_port *up, int state);
30908 + void (*set_txrx)( struct uart_omap_port *up, int txrx);
30909 + int (*get_txrx)( struct uart_omap_port *up);
30913 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
30914 --- linux-2.6.14-omap2/include/asm-arm/arch-omap/hardware.h 2005-12-02 01:53:34.000000000 +0200
30915 +++ linux-h6300-omap2-2.6.14.3/include/asm-arm/arch-omap/hardware.h 2005-10-22 03:52:45.000000000 +0300
30916 @@ -290,6 +290,10 @@
30917 #include "board-innovator.h"
30920 +#ifdef CONFIG_MACH_OMAP_H6300
30921 +#include "board-h6300.h"
30924 #ifdef CONFIG_MACH_OMAP_H2
30925 #include "board-h2.h"
30927 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
30928 --- linux-2.6.14-omap2/include/asm-arm/arch-omap/irqs.h 2005-12-02 01:53:34.000000000 +0200
30929 +++ linux-h6300-omap2-2.6.14.3/include/asm-arm/arch-omap/irqs.h 2005-11-11 04:13:42.000000000 +0200
30930 @@ -237,7 +237,7 @@
30931 #define INT_24XX_SDMA_IRQ1 13
30932 #define INT_24XX_SDMA_IRQ2 14
30933 #define INT_24XX_SDMA_IRQ3 15
30934 -#define INT_24XX_DSS_IRQ 25
30935 +#define INT_24XX_DSS_IRQ 25
30936 #define INT_24XX_GPIO_BANK1 29
30937 #define INT_24XX_GPIO_BANK2 30
30938 #define INT_24XX_GPIO_BANK3 31
30939 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
30940 --- linux-2.6.14-omap2/include/asm-arm/arch-omap/mux.h 2005-12-02 01:53:34.000000000 +0200
30941 +++ linux-h6300-omap2-2.6.14.3/include/asm-arm/arch-omap/mux.h 2005-10-14 18:55:31.000000000 +0300
30942 @@ -316,6 +316,13 @@
30943 P15_1610_UWIRE_CS3,
30944 N15_1610_UWIRE_CS1,
30946 + /* OMAP-1510 uWire */
30947 + P15_1510_UWIRE_CS3,
30948 + N14_1510_UWIRE_CS0,
30949 + V19_1510_UWIRE_SCLK,
30950 + W21_1510_UWIRE_SDO,
30951 + U18_1510_UWIRE_SDI,
30953 /* OMAP-1610 Flash */
30954 L3_1610_FLASH_CS2B_OE,
30955 M8_1610_FLASH_CS2B_WE,
30956 @@ -380,6 +387,7 @@
30959 /* MCLK Settings */
30960 + R10_1510_MCLK_ON,
30964 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
30965 --- linux-2.6.14-omap2/include/asm-arm/arch-omap/omapfb.h 2005-12-02 01:53:34.000000000 +0200
30966 +++ linux-h6300-omap2-2.6.14.3/include/asm-arm/arch-omap/omapfb.h 2005-11-11 04:13:42.000000000 +0200
30967 @@ -267,6 +267,7 @@
30968 extern struct lcd_panel osk_panel;
30969 extern struct lcd_panel innovator1610_panel;
30970 extern struct lcd_panel innovator1510_panel;
30971 +extern struct lcd_panel h6300_panel;
30973 #ifdef CONFIG_ARCH_OMAP1
30974 extern struct lcd_ctrl omap1_lcd_ctrl;
30975 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
30976 --- linux-2.6.14-omap2/include/asm-arm/arch-omap/omap_serial.h 1970-01-01 02:00:00.000000000 +0200
30977 +++ linux-h6300-omap2-2.6.14.3/include/asm-arm/arch-omap/omap_serial.h 2005-10-04 00:58:34.000000000 +0300
30980 + * Omap/h6300 serial driver private interface.
30981 + * Code originates from the pxa-serial.h available in the handheld org drivers
30982 + * for iPAQ PXA4700.
30984 + * Copyright (c) 2005 SDG Systems, LLC
30985 + * 2005-03-29 Todd Blumer Converted basic structure to support hx4700
30986 + * 2005-10-03 Mika Laitio (lamikr@cc.jyu.fi) Reorganized for the iPAQ h6300 bt driver.
30989 +#ifndef _OMAP_SERIAL_H
30990 +#define _OMAP_SERIAL_H
30992 +#define OMAP_SERIAL_TX 1
30993 +#define OMAP_SERIAL_RX 2
30995 +#include <linux/tty.h>
30996 +#include <linux/serial_core.h>
30998 +struct platform_omap_serial_funcs;
31000 +struct uart_omap_port {
31001 + struct uart_port port;
31002 + unsigned char ier;
31003 + unsigned char lcr;
31004 + unsigned char mcr;
31005 + unsigned int lsr_break_flag;
31006 + unsigned int cken;
31008 + struct platform_omap_serial_funcs *pf;
31011 +/* A pointer to such a structure can be contained in the platform_data
31012 + * field of every PXA UART platform_device. If the field is NULL, the
31013 + * serial port works as usual.
31015 + * For the sake of simplicity/performance no one of the function pointers
31016 + * in the structure below can be NULL.
31018 +struct platform_omap_serial_funcs {
31019 + /* Platform-specific function to initialize whatever is connected
31020 + to this serial port... enable=1 -> enable transceiver,
31021 + 0 -> disable transceiver. */
31022 + void (*configure) (struct uart_omap_port *up, int enable);
31023 + /* Platform-specific function to enable or disable the individual
31024 + transmitter/receiver submodules. On transceivers without echo
31025 + cancellation (e.g. SIR) transmitter always has priority, e.g.
31026 + if both bits are set, only the transmitter is enabled. */
31027 + void (*set_txrx) (struct uart_omap_port *up, int txrx);
31028 + /* Get the current state of tx/rx (see bitflags above) */
31029 + int (*get_txrx) (struct uart_omap_port *up);
31033 + * The variables below are located in arch/arm/mach-omap/board_h6300.c
31034 + * Machine-specific code may want to put a pointer to a static
31035 + * platform_pxa_serial_funcs structure in the dev.platform_data
31036 + * field of the respective port device.
31038 +extern struct platform_device btuart_device;
31041 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
31042 --- linux-2.6.14-omap2/include/asm-arm/arch-omap/pca9535.h 1970-01-01 02:00:00.000000000 +0200
31043 +++ linux-h6300-omap2-2.6.14.3/include/asm-arm/arch-omap/pca9535.h 2005-10-25 03:24:45.000000000 +0300
31045 +#ifndef _PCA9535_H
31046 +#define _PCA9535_H
31048 +enum pca9535_gpios {
31069 +enum gpio_values {
31074 +enum gpio_direction {
31079 +extern int pca9535_gpio_read(int gpio);
31080 +extern int pca9535_gpio_write(int gpio, unsigned char val);
31081 +extern int pca9535_gpio_direction(int gpio, unsigned char direction);
31084 diff -Naur linux-2.6.14-omap2/include/linux/proc_fs.h linux-h6300-omap2-2.6.14.3/include/linux/proc_fs.h
31085 --- linux-2.6.14-omap2/include/linux/proc_fs.h 2005-10-28 03:02:08.000000000 +0300
31086 +++ linux-h6300-omap2-2.6.14.3/include/linux/proc_fs.h 2005-11-23 01:44:02.000000000 +0200
31088 write_proc_t *write_proc;
31089 atomic_t count; /* use count */
31090 int deleted; /* delete flag */
31094 struct kcore_list {
31095 diff -Naur linux-2.6.14-omap2/include/linux/sysctl.h linux-h6300-omap2-2.6.14.3/include/linux/sysctl.h
31096 --- linux-2.6.14-omap2/include/linux/sysctl.h 2005-10-28 03:02:08.000000000 +0300
31097 +++ linux-h6300-omap2-2.6.14.3/include/linux/sysctl.h 2005-11-23 01:44:02.000000000 +0200
31099 #include <linux/compiler.h>
31102 +struct completion;
31104 #define CTL_MAXNAME 10 /* how many path components do we allow in a
31105 call to sysctl? In other words, what is
31106 @@ -925,6 +926,8 @@
31108 ctl_table *ctl_table;
31109 struct list_head ctl_entry;
31111 + struct completion *unregistering;
31114 struct ctl_table_header * register_sysctl_table(ctl_table * table,
31115 diff -Naur linux-2.6.14-omap2/include/net/ipv6.h linux-h6300-omap2-2.6.14.3/include/net/ipv6.h
31116 --- linux-2.6.14-omap2/include/net/ipv6.h 2005-10-28 03:02:08.000000000 +0300
31117 +++ linux-h6300-omap2-2.6.14.3/include/net/ipv6.h 2005-12-02 01:34:35.000000000 +0200
31118 @@ -237,6 +237,8 @@
31120 struct ipv6_opt_hdr __user *newopt,
31122 +struct ipv6_txoptions *ipv6_fixup_options(struct ipv6_txoptions *opt_space,
31123 + struct ipv6_txoptions *opt);
31125 extern int ip6_frag_nqueues;
31126 extern atomic_t ip6_frag_mem;
31127 diff -Naur linux-2.6.14-omap2/kernel/ptrace.c linux-h6300-omap2-2.6.14.3/kernel/ptrace.c
31128 --- linux-2.6.14-omap2/kernel/ptrace.c 2005-10-28 03:02:08.000000000 +0300
31129 +++ linux-h6300-omap2-2.6.14.3/kernel/ptrace.c 2005-11-23 01:44:02.000000000 +0200
31130 @@ -152,7 +152,7 @@
31132 if (task->pid <= 1)
31134 - if (task == current)
31135 + if (task->tgid == current->tgid)
31137 /* the same process cannot be attached many times */
31138 if (task->ptrace & PT_PTRACED)
31139 diff -Naur linux-2.6.14-omap2/kernel/signal.c linux-h6300-omap2-2.6.14.3/kernel/signal.c
31140 --- linux-2.6.14-omap2/kernel/signal.c 2005-10-28 03:02:08.000000000 +0300
31141 +++ linux-h6300-omap2-2.6.14.3/kernel/signal.c 2005-12-02 01:34:35.000000000 +0200
31142 @@ -406,6 +406,8 @@
31144 void exit_signal(struct task_struct *tsk)
31146 + atomic_dec(&tsk->signal->live);
31148 write_lock_irq(&tasklist_lock);
31149 __exit_signal(tsk);
31150 write_unlock_irq(&tasklist_lock);
31151 @@ -1522,7 +1524,7 @@
31153 psig = tsk->parent->sighand;
31154 spin_lock_irqsave(&psig->siglock, flags);
31155 - if (sig == SIGCHLD &&
31156 + if (!tsk->ptrace && sig == SIGCHLD &&
31157 (psig->action[SIGCHLD-1].sa.sa_handler == SIG_IGN ||
31158 (psig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDWAIT))) {
31160 diff -Naur linux-2.6.14-omap2/kernel/sysctl.c linux-h6300-omap2-2.6.14.3/kernel/sysctl.c
31161 --- linux-2.6.14-omap2/kernel/sysctl.c 2005-10-28 03:02:08.000000000 +0300
31162 +++ linux-h6300-omap2-2.6.14.3/kernel/sysctl.c 2005-11-23 01:44:02.000000000 +0200
31163 @@ -169,7 +169,7 @@
31165 extern struct proc_dir_entry *proc_sys_root;
31167 -static void register_proc_table(ctl_table *, struct proc_dir_entry *);
31168 +static void register_proc_table(ctl_table *, struct proc_dir_entry *, void *);
31169 static void unregister_proc_table(ctl_table *, struct proc_dir_entry *);
31172 @@ -992,10 +992,51 @@
31174 extern void init_irq_proc (void);
31176 +static DEFINE_SPINLOCK(sysctl_lock);
31178 +/* called under sysctl_lock */
31179 +static int use_table(struct ctl_table_header *p)
31181 + if (unlikely(p->unregistering))
31187 +/* called under sysctl_lock */
31188 +static void unuse_table(struct ctl_table_header *p)
31191 + if (unlikely(p->unregistering))
31192 + complete(p->unregistering);
31195 +/* called under sysctl_lock, will reacquire if has to wait */
31196 +static void start_unregistering(struct ctl_table_header *p)
31199 + * if p->used is 0, nobody will ever touch that entry again;
31200 + * we'll eliminate all paths to it before dropping sysctl_lock
31202 + if (unlikely(p->used)) {
31203 + struct completion wait;
31204 + init_completion(&wait);
31205 + p->unregistering = &wait;
31206 + spin_unlock(&sysctl_lock);
31207 + wait_for_completion(&wait);
31208 + spin_lock(&sysctl_lock);
31211 + * do not remove from the list until nobody holds it; walking the
31212 + * list in do_sysctl() relies on that.
31214 + list_del_init(&p->ctl_entry);
31217 void __init sysctl_init(void)
31219 #ifdef CONFIG_PROC_FS
31220 - register_proc_table(root_table, proc_sys_root);
31221 + register_proc_table(root_table, proc_sys_root, &root_table_header);
31225 @@ -1004,6 +1045,7 @@
31226 void __user *newval, size_t newlen)
31228 struct list_head *tmp;
31229 + int error = -ENOTDIR;
31231 if (nlen <= 0 || nlen >= CTL_MAXNAME)
31233 @@ -1012,20 +1054,30 @@
31234 if (!oldlenp || get_user(old_len, oldlenp))
31237 + spin_lock(&sysctl_lock);
31238 tmp = &root_table_header.ctl_entry;
31240 struct ctl_table_header *head =
31241 list_entry(tmp, struct ctl_table_header, ctl_entry);
31242 void *context = NULL;
31243 - int error = parse_table(name, nlen, oldval, oldlenp,
31245 + if (!use_table(head))
31248 + spin_unlock(&sysctl_lock);
31250 + error = parse_table(name, nlen, oldval, oldlenp,
31251 newval, newlen, head->ctl_table,
31255 + spin_lock(&sysctl_lock);
31256 + unuse_table(head);
31257 if (error != -ENOTDIR)
31260 - } while (tmp != &root_table_header.ctl_entry);
31263 + } while ((tmp = tmp->next) != &root_table_header.ctl_entry);
31264 + spin_unlock(&sysctl_lock);
31268 asmlinkage long sys_sysctl(struct __sysctl_args __user *args)
31269 @@ -1236,12 +1288,16 @@
31271 tmp->ctl_table = table;
31272 INIT_LIST_HEAD(&tmp->ctl_entry);
31274 + tmp->unregistering = NULL;
31275 + spin_lock(&sysctl_lock);
31276 if (insert_at_head)
31277 list_add(&tmp->ctl_entry, &root_table_header.ctl_entry);
31279 list_add_tail(&tmp->ctl_entry, &root_table_header.ctl_entry);
31280 + spin_unlock(&sysctl_lock);
31281 #ifdef CONFIG_PROC_FS
31282 - register_proc_table(table, proc_sys_root);
31283 + register_proc_table(table, proc_sys_root, tmp);
31287 @@ -1255,10 +1311,13 @@
31289 void unregister_sysctl_table(struct ctl_table_header * header)
31291 - list_del(&header->ctl_entry);
31293 + spin_lock(&sysctl_lock);
31294 + start_unregistering(header);
31295 #ifdef CONFIG_PROC_FS
31296 unregister_proc_table(header->ctl_table, proc_sys_root);
31298 + spin_unlock(&sysctl_lock);
31302 @@ -1269,7 +1328,7 @@
31303 #ifdef CONFIG_PROC_FS
31305 /* Scan the sysctl entries in table and add them all into /proc */
31306 -static void register_proc_table(ctl_table * table, struct proc_dir_entry *root)
31307 +static void register_proc_table(ctl_table * table, struct proc_dir_entry *root, void *set)
31309 struct proc_dir_entry *de;
31311 @@ -1305,13 +1364,14 @@
31312 de = create_proc_entry(table->procname, mode, root);
31316 de->data = (void *) table;
31317 if (table->proc_handler)
31318 de->proc_fops = &proc_sys_file_operations;
31321 if (de->mode & S_IFDIR)
31322 - register_proc_table(table->child, de);
31323 + register_proc_table(table->child, de, set);
31327 @@ -1336,6 +1396,13 @@
31332 + * In any case, mark the entry as goner; we'll keep it
31333 + * around if it's busy, but we'll know to do nothing with
31334 + * its fields. We are under sysctl_lock here.
31338 /* Don't unregister proc entries that are still being used.. */
31339 if (atomic_read(&de->count))
31341 @@ -1349,27 +1416,38 @@
31342 size_t count, loff_t *ppos)
31345 - struct proc_dir_entry *de;
31346 + struct proc_dir_entry *de = PDE(file->f_dentry->d_inode);
31347 struct ctl_table *table;
31351 - de = PDE(file->f_dentry->d_inode);
31352 - if (!de || !de->data)
31354 - table = (struct ctl_table *) de->data;
31355 - if (!table || !table->proc_handler)
31357 - op = (write ? 002 : 004);
31358 - if (ctl_perm(table, op))
31360 + ssize_t error = -ENOTDIR;
31364 - error = (*table->proc_handler) (table, write, file, buf, &res, ppos);
31368 + spin_lock(&sysctl_lock);
31369 + if (de && de->data && use_table(de->set)) {
31371 + * at that point we know that sysctl was not unregistered
31372 + * and won't be until we finish
31374 + spin_unlock(&sysctl_lock);
31375 + table = (struct ctl_table *) de->data;
31376 + if (!table || !table->proc_handler)
31379 + op = (write ? 002 : 004);
31380 + if (ctl_perm(table, op))
31383 + /* careful: calling conventions are nasty here */
31385 + error = (*table->proc_handler)(table, write, file,
31386 + buf, &res, ppos);
31390 + spin_lock(&sysctl_lock);
31391 + unuse_table(de->set);
31393 + spin_unlock(&sysctl_lock);
31397 static int proc_opensys(struct inode *inode, struct file *file)
31398 diff -Naur linux-2.6.14-omap2/Makefile linux-h6300-omap2-2.6.14.3/Makefile
31399 --- linux-2.6.14-omap2/Makefile 2005-12-02 01:53:31.000000000 +0200
31400 +++ linux-h6300-omap2-2.6.14.3/Makefile 2005-12-02 01:34:34.000000000 +0200
31407 NAME=Affluent Albatross
31411 # expect to learn how to build the kernel reading this file.
31413 # Add custom flags here to avoid conflict with updates
31414 -EXTRAVERSION := $(EXTRAVERSION)-omap2
31415 +EXTRAVERSION := $(EXTRAVERSION)-omap1-h6300
31417 # Do not print "Entering directory ..."
31418 MAKEFLAGS += --no-print-directory
31419 diff -Naur linux-2.6.14-omap2/net/core/datagram.c linux-h6300-omap2-2.6.14.3/net/core/datagram.c
31420 --- linux-2.6.14-omap2/net/core/datagram.c 2005-10-28 03:02:08.000000000 +0300
31421 +++ linux-h6300-omap2-2.6.14.3/net/core/datagram.c 2005-11-23 01:44:02.000000000 +0200
31422 @@ -213,6 +213,10 @@
31424 int i, err, fraglen, end = 0;
31425 struct sk_buff *next = skb_shinfo(skb)->frag_list;
31431 fraglen = skb_headlen(skb);
31433 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
31434 --- linux-2.6.14-omap2/net/ipv4/ipvs/ip_vs_core.c 2005-10-28 03:02:08.000000000 +0300
31435 +++ linux-h6300-omap2-2.6.14.3/net/ipv4/ipvs/ip_vs_core.c 2005-11-23 01:44:02.000000000 +0200
31436 @@ -1009,11 +1009,10 @@
31437 if (sysctl_ip_vs_expire_nodest_conn) {
31438 /* try to expire the connection immediately */
31439 ip_vs_conn_expire_now(cp);
31441 - /* don't restart its timer, and silently
31442 - drop the packet. */
31443 - __ip_vs_conn_put(cp);
31445 + /* don't restart its timer, and silently
31446 + drop the packet. */
31447 + __ip_vs_conn_put(cp);
31451 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
31452 --- linux-2.6.14-omap2/net/ipv4/netfilter/ip_conntrack_ftp.c 2005-10-28 03:02:08.000000000 +0300
31453 +++ linux-h6300-omap2-2.6.14.3/net/ipv4/netfilter/ip_conntrack_ftp.c 2005-12-02 01:34:35.000000000 +0200
31455 static DEFINE_SPINLOCK(ip_ftp_lock);
31457 #define MAX_PORTS 8
31458 -static short ports[MAX_PORTS];
31459 +static unsigned short ports[MAX_PORTS];
31460 static int ports_c;
31461 -module_param_array(ports, short, &ports_c, 0400);
31462 +module_param_array(ports, ushort, &ports_c, 0400);
31465 module_param(loose, int, 0600);
31466 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
31467 --- linux-2.6.14-omap2/net/ipv4/netfilter/ip_conntrack_irc.c 2005-10-28 03:02:08.000000000 +0300
31468 +++ linux-h6300-omap2-2.6.14.3/net/ipv4/netfilter/ip_conntrack_irc.c 2005-12-02 01:34:35.000000000 +0200
31470 #include <linux/moduleparam.h>
31472 #define MAX_PORTS 8
31473 -static short ports[MAX_PORTS];
31474 +static unsigned short ports[MAX_PORTS];
31475 static int ports_c;
31476 static int max_dcc_channels = 8;
31477 static unsigned int dcc_timeout = 300;
31479 MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
31480 MODULE_DESCRIPTION("IRC (DCC) connection tracking helper");
31481 MODULE_LICENSE("GPL");
31482 -module_param_array(ports, short, &ports_c, 0400);
31483 +module_param_array(ports, ushort, &ports_c, 0400);
31484 MODULE_PARM_DESC(ports, "port numbers of IRC servers");
31485 module_param(max_dcc_channels, int, 0400);
31486 MODULE_PARM_DESC(max_dcc_channels, "max number of expected DCC channels per IRC session");
31487 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
31488 --- linux-2.6.14-omap2/net/ipv4/netfilter/ip_conntrack_netlink.c 2005-10-28 03:02:08.000000000 +0300
31489 +++ linux-h6300-omap2-2.6.14.3/net/ipv4/netfilter/ip_conntrack_netlink.c 2005-12-02 01:34:35.000000000 +0200
31490 @@ -58,14 +58,17 @@
31491 const struct ip_conntrack_tuple *tuple)
31493 struct ip_conntrack_protocol *proto;
31496 NFA_PUT(skb, CTA_PROTO_NUM, sizeof(u_int8_t), &tuple->dst.protonum);
31498 proto = ip_conntrack_proto_find_get(tuple->dst.protonum);
31499 - if (proto && proto->tuple_to_nfattr)
31500 - return proto->tuple_to_nfattr(skb, tuple);
31501 + if (likely(proto && proto->tuple_to_nfattr)) {
31502 + ret = proto->tuple_to_nfattr(skb, tuple);
31503 + ip_conntrack_proto_put(proto);
31511 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
31512 --- linux-2.6.14-omap2/net/ipv4/netfilter/ip_conntrack_proto_icmp.c 2005-10-28 03:02:08.000000000 +0300
31513 +++ linux-h6300-omap2-2.6.14.3/net/ipv4/netfilter/ip_conntrack_proto_icmp.c 2005-12-02 01:34:35.000000000 +0200
31514 @@ -296,7 +296,8 @@
31515 struct ip_conntrack_tuple *tuple)
31517 if (!tb[CTA_PROTO_ICMP_TYPE-1]
31518 - || !tb[CTA_PROTO_ICMP_CODE-1])
31519 + || !tb[CTA_PROTO_ICMP_CODE-1]
31520 + || !tb[CTA_PROTO_ICMP_ID-1])
31523 tuple->dst.u.icmp.type =
31524 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
31525 --- linux-2.6.14-omap2/net/ipv4/netfilter/ip_conntrack_proto_tcp.c 2005-10-28 03:02:08.000000000 +0300
31526 +++ linux-h6300-omap2-2.6.14.3/net/ipv4/netfilter/ip_conntrack_proto_tcp.c 2005-12-02 01:34:35.000000000 +0200
31527 @@ -362,6 +362,11 @@
31528 struct nfattr *attr = cda[CTA_PROTOINFO_TCP-1];
31529 struct nfattr *tb[CTA_PROTOINFO_TCP_MAX];
31531 + /* updates could not contain anything about the private
31532 + * protocol info, in that case skip the parsing */
31536 if (nfattr_parse_nested(tb, CTA_PROTOINFO_TCP_MAX, attr) < 0)
31537 goto nfattr_failure;
31539 @@ -813,6 +818,7 @@
31542 [TH_SYN|TH_ACK] = 1,
31543 + [TH_SYN|TH_PUSH] = 1,
31544 [TH_SYN|TH_ACK|TH_PUSH] = 1,
31546 [TH_RST|TH_ACK] = 1,
31547 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
31548 --- linux-2.6.14-omap2/net/ipv4/netfilter/ip_conntrack_tftp.c 2005-10-28 03:02:08.000000000 +0300
31549 +++ linux-h6300-omap2-2.6.14.3/net/ipv4/netfilter/ip_conntrack_tftp.c 2005-12-02 01:34:35.000000000 +0200
31551 MODULE_LICENSE("GPL");
31553 #define MAX_PORTS 8
31554 -static short ports[MAX_PORTS];
31555 +static unsigned short ports[MAX_PORTS];
31556 static int ports_c;
31557 -module_param_array(ports, short, &ports_c, 0400);
31558 +module_param_array(ports, ushort, &ports_c, 0400);
31559 MODULE_PARM_DESC(ports, "port numbers of tftp servers");
31562 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
31563 --- linux-2.6.14-omap2/net/ipv4/netfilter/ip_nat_core.c 2005-10-28 03:02:08.000000000 +0300
31564 +++ linux-h6300-omap2-2.6.14.3/net/ipv4/netfilter/ip_nat_core.c 2005-12-02 01:34:35.000000000 +0200
31566 * removed until we've grabbed the reference */
31568 p = __ip_nat_proto_find(protonum);
31570 - if (!try_module_get(p->me))
31571 - p = &ip_nat_unknown_protocol;
31573 + if (!try_module_get(p->me))
31574 + p = &ip_nat_unknown_protocol;
31578 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
31579 --- linux-2.6.14-omap2/net/ipv4/netfilter/ip_nat_helper_pptp.c 2005-10-28 03:02:08.000000000 +0300
31580 +++ linux-h6300-omap2-2.6.14.3/net/ipv4/netfilter/ip_nat_helper_pptp.c 2005-12-02 01:34:35.000000000 +0200
31582 struct ip_conntrack_tuple t;
31583 struct ip_ct_pptp_master *ct_pptp_info;
31584 struct ip_nat_pptp *nat_pptp_info;
31585 + struct ip_nat_range range;
31587 ct_pptp_info = &master->help.ct_pptp_info;
31588 nat_pptp_info = &master->nat.help.nat_pptp_info;
31589 @@ -110,7 +111,30 @@
31590 DEBUGP("not found!\n");
31593 - ip_nat_follow_master(ct, exp);
31594 + /* This must be a fresh one. */
31595 + BUG_ON(ct->status & IPS_NAT_DONE_MASK);
31597 + /* Change src to where master sends to */
31598 + range.flags = IP_NAT_RANGE_MAP_IPS;
31599 + range.min_ip = range.max_ip
31600 + = ct->master->tuplehash[!exp->dir].tuple.dst.ip;
31601 + if (exp->dir == IP_CT_DIR_ORIGINAL) {
31602 + range.flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
31603 + range.min = range.max = exp->saved_proto;
31605 + /* hook doesn't matter, but it has to do source manip */
31606 + ip_nat_setup_info(ct, &range, NF_IP_POST_ROUTING);
31608 + /* For DST manip, map port here to where it's expected. */
31609 + range.flags = IP_NAT_RANGE_MAP_IPS;
31610 + range.min_ip = range.max_ip
31611 + = ct->master->tuplehash[!exp->dir].tuple.src.ip;
31612 + if (exp->dir == IP_CT_DIR_REPLY) {
31613 + range.flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
31614 + range.min = range.max = exp->saved_proto;
31616 + /* hook doesn't matter, but it has to do destination manip */
31617 + ip_nat_setup_info(ct, &range, NF_IP_PRE_ROUTING);
31620 /* outbound packets == from PNS to PAC */
31621 @@ -213,7 +237,7 @@
31623 /* alter expectation for PNS->PAC direction */
31624 invert_tuplepr(&inv_t, &expect_orig->tuple);
31625 - expect_orig->saved_proto.gre.key = htons(nat_pptp_info->pac_call_id);
31626 + expect_orig->saved_proto.gre.key = htons(ct_pptp_info->pns_call_id);
31627 expect_orig->tuple.src.u.gre.key = htons(nat_pptp_info->pns_call_id);
31628 expect_orig->tuple.dst.u.gre.key = htons(ct_pptp_info->pac_call_id);
31629 inv_t.src.ip = reply_t->src.ip;
31630 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
31631 --- linux-2.6.14-omap2/net/ipv4/netfilter/ip_nat_proto_gre.c 2005-10-28 03:02:08.000000000 +0300
31632 +++ linux-h6300-omap2-2.6.14.3/net/ipv4/netfilter/ip_nat_proto_gre.c 2005-12-02 01:34:35.000000000 +0200
31633 @@ -139,8 +139,8 @@
31635 case GRE_VERSION_PPTP:
31636 DEBUGP("call_id -> 0x%04x\n",
31637 - ntohl(tuple->dst.u.gre.key));
31638 - pgreh->call_id = htons(ntohl(tuple->dst.u.gre.key));
31639 + ntohs(tuple->dst.u.gre.key));
31640 + pgreh->call_id = tuple->dst.u.gre.key;
31643 DEBUGP("can't nat unknown GRE version\n");
31644 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
31645 --- linux-2.6.14-omap2/net/ipv4/netfilter/ip_nat_proto_unknown.c 2005-10-28 03:02:08.000000000 +0300
31646 +++ linux-h6300-omap2-2.6.14.3/net/ipv4/netfilter/ip_nat_proto_unknown.c 2005-12-02 01:34:35.000000000 +0200
31649 struct ip_nat_protocol ip_nat_unknown_protocol = {
31651 - .me = THIS_MODULE,
31652 + /* .me isn't set: getting a ref to this cannot fail. */
31653 .manip_pkt = unknown_manip_pkt,
31654 .in_range = unknown_in_range,
31655 .unique_tuple = unknown_unique_tuple,
31656 diff -Naur linux-2.6.14-omap2/net/ipv4/tcp_bic.c linux-h6300-omap2-2.6.14.3/net/ipv4/tcp_bic.c
31657 --- linux-2.6.14-omap2/net/ipv4/tcp_bic.c 2005-10-28 03:02:08.000000000 +0300
31658 +++ linux-h6300-omap2-2.6.14.3/net/ipv4/tcp_bic.c 2005-11-23 01:44:02.000000000 +0200
31662 static int fast_convergence = 1;
31663 -static int max_increment = 32;
31664 +static int max_increment = 16;
31665 static int low_window = 14;
31666 static int beta = 819; /* = 819/1024 (BICTCP_BETA_SCALE) */
31667 static int low_utilization_threshold = 153;
31668 diff -Naur linux-2.6.14-omap2/net/ipv6/datagram.c linux-h6300-omap2-2.6.14.3/net/ipv6/datagram.c
31669 --- linux-2.6.14-omap2/net/ipv6/datagram.c 2005-10-28 03:02:08.000000000 +0300
31670 +++ linux-h6300-omap2-2.6.14.3/net/ipv6/datagram.c 2005-12-02 01:34:35.000000000 +0200
31671 @@ -437,7 +437,7 @@
31675 - len = (ptr[1] + 1) << 2;
31676 + len = (ptr[1] + 2) << 2;
31680 diff -Naur linux-2.6.14-omap2/net/ipv6/exthdrs.c linux-h6300-omap2-2.6.14.3/net/ipv6/exthdrs.c
31681 --- linux-2.6.14-omap2/net/ipv6/exthdrs.c 2005-10-28 03:02:08.000000000 +0300
31682 +++ linux-h6300-omap2-2.6.14.3/net/ipv6/exthdrs.c 2005-12-02 01:34:35.000000000 +0200
31683 @@ -628,6 +628,7 @@
31687 + tot_len += sizeof(*opt2);
31688 opt2 = sock_kmalloc(sk, tot_len, GFP_ATOMIC);
31690 return ERR_PTR(-ENOBUFS);
31691 @@ -668,7 +669,26 @@
31695 - sock_kfree_s(sk, p, tot_len);
31696 + sock_kfree_s(sk, opt2, opt2->tot_len);
31697 return ERR_PTR(err);
31700 +struct ipv6_txoptions *ipv6_fixup_options(struct ipv6_txoptions *opt_space,
31701 + struct ipv6_txoptions *opt)
31704 + * ignore the dest before srcrt unless srcrt is being included.
31707 + if (opt && opt->dst0opt && !opt->srcrt) {
31708 + if (opt_space != opt) {
31709 + memcpy(opt_space, opt, sizeof(*opt_space));
31712 + opt->opt_nflen -= ipv6_optlen(opt->dst0opt);
31713 + opt->dst0opt = NULL;
31719 diff -Naur linux-2.6.14-omap2/net/ipv6/ip6_flowlabel.c linux-h6300-omap2-2.6.14.3/net/ipv6/ip6_flowlabel.c
31720 --- linux-2.6.14-omap2/net/ipv6/ip6_flowlabel.c 2005-10-28 03:02:08.000000000 +0300
31721 +++ linux-h6300-omap2-2.6.14.3/net/ipv6/ip6_flowlabel.c 2005-12-02 01:34:35.000000000 +0200
31722 @@ -225,20 +225,16 @@
31723 struct ip6_flowlabel * fl,
31724 struct ipv6_txoptions * fopt)
31726 - struct ipv6_txoptions * fl_opt = fl ? fl->opt : NULL;
31727 + struct ipv6_txoptions * fl_opt = fl->opt;
31729 - if (fopt == NULL || fopt->opt_flen == 0) {
31730 - if (!fl_opt || !fl_opt->dst0opt || fl_opt->srcrt)
31733 + if (fopt == NULL || fopt->opt_flen == 0)
31736 if (fl_opt != NULL) {
31737 opt_space->hopopt = fl_opt->hopopt;
31738 - opt_space->dst0opt = fl_opt->srcrt ? fl_opt->dst0opt : NULL;
31739 + opt_space->dst0opt = fl_opt->dst0opt;
31740 opt_space->srcrt = fl_opt->srcrt;
31741 opt_space->opt_nflen = fl_opt->opt_nflen;
31742 - if (fl_opt->dst0opt && !fl_opt->srcrt)
31743 - opt_space->opt_nflen -= ipv6_optlen(fl_opt->dst0opt);
31745 if (fopt->opt_nflen == 0)
31747 diff -Naur linux-2.6.14-omap2/net/ipv6/raw.c linux-h6300-omap2-2.6.14.3/net/ipv6/raw.c
31748 --- linux-2.6.14-omap2/net/ipv6/raw.c 2005-10-28 03:02:08.000000000 +0300
31749 +++ linux-h6300-omap2-2.6.14.3/net/ipv6/raw.c 2005-12-02 01:34:35.000000000 +0200
31750 @@ -756,7 +756,9 @@
31754 - opt = fl6_merge_options(&opt_space, flowlabel, opt);
31756 + opt = fl6_merge_options(&opt_space, flowlabel, opt);
31757 + opt = ipv6_fixup_options(&opt_space, opt);
31760 rawv6_probe_proto_opt(&fl, msg);
31761 diff -Naur linux-2.6.14-omap2/net/ipv6/udp.c linux-h6300-omap2-2.6.14.3/net/ipv6/udp.c
31762 --- linux-2.6.14-omap2/net/ipv6/udp.c 2005-10-28 03:02:08.000000000 +0300
31763 +++ linux-h6300-omap2-2.6.14.3/net/ipv6/udp.c 2005-12-02 01:34:35.000000000 +0200
31764 @@ -778,7 +778,9 @@
31768 - opt = fl6_merge_options(&opt_space, flowlabel, opt);
31770 + opt = fl6_merge_options(&opt_space, flowlabel, opt);
31771 + opt = ipv6_fixup_options(&opt_space, opt);
31773 fl->proto = IPPROTO_UDP;
31774 ipv6_addr_copy(&fl->fl6_dst, daddr);
31775 diff -Naur linux-2.6.14-omap2/net/netfilter/nf_queue.c linux-h6300-omap2-2.6.14.3/net/netfilter/nf_queue.c
31776 --- linux-2.6.14-omap2/net/netfilter/nf_queue.c 2005-10-28 03:02:08.000000000 +0300
31777 +++ linux-h6300-omap2-2.6.14.3/net/netfilter/nf_queue.c 2005-12-02 01:34:35.000000000 +0200
31778 @@ -117,7 +117,7 @@
31780 /* QUEUE == DROP if noone is waiting, to be safe. */
31781 read_lock(&queue_handler_lock);
31782 - if (!queue_handler[pf]->outfn) {
31783 + if (!queue_handler[pf] || !queue_handler[pf]->outfn) {
31784 read_unlock(&queue_handler_lock);
31787 diff -Naur linux-2.6.14-omap2/sound/arm/Kconfig linux-h6300-omap2-2.6.14.3/sound/arm/Kconfig
31788 --- linux-2.6.14-omap2/sound/arm/Kconfig 2005-12-02 01:53:34.000000000 +0200
31789 +++ linux-h6300-omap2-2.6.14.3/sound/arm/Kconfig 2005-11-13 02:15:10.000000000 +0200
31792 To compile this driver as a module, choose M here: the module
31793 will be called snd-omap-aic23.
31795 +config SND_OMAP_TSC2101
31796 + tristate "OMAP TSC2101 driver (iPaq H63xx)"
31797 + depends ARCH_OMAP && SND
31800 + ALSA driver for TI TSC2101.
31802 + To compile this driver as a module, choose M here: the module
31803 + will be called snd-omap-tsc2101.
31806 diff -Naur linux-2.6.14-omap2/sound/arm/Makefile linux-h6300-omap2-2.6.14.3/sound/arm/Makefile
31807 --- linux-2.6.14-omap2/sound/arm/Makefile 2005-12-02 01:53:34.000000000 +0200
31808 +++ linux-h6300-omap2-2.6.14.3/sound/arm/Makefile 2005-11-13 02:15:10.000000000 +0200
31811 obj-$(CONFIG_SND_OMAP_AIC23) += snd-omap-aic23.o
31812 snd-omap-aic23-objs := omap-aic23.o omap-alsa-dma.o omap-alsa-mixer.o
31814 +obj-$(CONFIG_SND_OMAP_TSC2101) += snd-omap-tsc2101.o
31815 +snd-omap-tsc2101-objs := omap-tsc2101.o omap-alsa-dma.o
31816 diff -Naur linux-2.6.14-omap2/sound/arm/omap-aic23.c linux-h6300-omap2-2.6.14.3/sound/arm/omap-aic23.c
31817 --- linux-2.6.14-omap2/sound/arm/omap-aic23.c 2005-12-02 01:53:34.000000000 +0200
31818 +++ linux-h6300-omap2-2.6.14.3/sound/arm/omap-aic23.c 2005-11-13 02:15:10.000000000 +0200
31819 @@ -262,144 +262,6 @@
31824 - * Depends on omap-aic23-dma.c functions and (omap) dma.c
31827 -#define DMA_BUF_SIZE 1024 * 8
31829 -static int audio_dma_request(struct audio_stream *s,
31830 - void (*callback) (void *))
31834 - err = omap_request_sound_dma(s->dma_dev, s->id, s, &s->lch);
31836 - printk(KERN_ERR "unable to grab audio dma 0x%x\n",
31841 -static int audio_dma_free(struct audio_stream *s)
31845 - err = omap_free_sound_dma(s, &s->lch);
31847 - printk(KERN_ERR "Unable to free audio dma channels!\n");
31852 - * This function should calculate the current position of the dma in the
31853 - * buffer. It will help alsa middle layer to continue update the buffer.
31854 - * Its correctness is crucial for good functioning.
31856 -static u_int audio_get_dma_pos(struct audio_stream *s)
31858 - snd_pcm_substream_t *substream = s->stream;
31859 - snd_pcm_runtime_t *runtime = substream->runtime;
31860 - unsigned int offset;
31861 - unsigned long flags;
31862 - dma_addr_t count;
31865 - /* this must be called w/ interrupts locked as requested in dma.c */
31866 - spin_lock_irqsave(&s->dma_lock, flags);
31868 - /* For the current period let's see where we are */
31869 - count = omap_get_dma_src_addr_counter(s->lch[s->dma_q_head]);
31871 - spin_unlock_irqrestore(&s->dma_lock, flags);
31873 - /* Now, the position related to the end of that period */
31874 - offset = bytes_to_frames(runtime, s->offset) - bytes_to_frames(runtime, count);
31876 - if (offset >= runtime->buffer_size || offset < 0)
31883 - * this stops the dma and clears the dma ptrs
31885 -static void audio_stop_dma(struct audio_stream *s)
31887 - unsigned long flags;
31890 - spin_lock_irqsave(&s->dma_lock, flags);
31895 - /* this stops the dma channel and clears the buffer ptrs */
31896 - omap_audio_stop_dma(s);
31898 - omap_clear_sound_dma(s);
31900 - spin_unlock_irqrestore(&s->dma_lock, flags);
31904 - * Main dma routine, requests dma according where you are in main alsa buffer
31906 -static void audio_process_dma(struct audio_stream *s)
31908 - snd_pcm_substream_t *substream = s->stream;
31909 - snd_pcm_runtime_t *runtime;
31910 - unsigned int dma_size;
31911 - unsigned int offset;
31914 - runtime = substream->runtime;
31916 - dma_size = frames_to_bytes(runtime, runtime->period_size);
31917 - offset = dma_size * s->period;
31918 - snd_assert(dma_size <= DMA_BUF_SIZE,);
31920 - omap_start_sound_dma(s,
31921 - (dma_addr_t) runtime->dma_area +
31922 - offset, dma_size);
31925 - "audio_process_dma: cannot queue DMA buffer (%i)\n",
31931 - s->period %= runtime->periods;
31933 - s->offset = offset;
31938 - * This is called when dma IRQ occurs at the end of each transmited block
31940 -void audio_dma_callback(void *data)
31942 - struct audio_stream *s = data;
31945 - * If we are getting a callback for an active stream then we inform
31946 - * the PCM middle layer we've finished a period
31949 - snd_pcm_period_elapsed(s->stream);
31951 - spin_lock(&s->dma_lock);
31952 - if (s->periods > 0) {
31955 - audio_process_dma(s);
31956 - spin_unlock(&s->dma_lock);
31962 * PCM settings and callbacks
31964 diff -Naur linux-2.6.14-omap2/sound/arm/omap-aic23.h linux-h6300-omap2-2.6.14.3/sound/arm/omap-aic23.h
31965 --- linux-2.6.14-omap2/sound/arm/omap-aic23.h 2005-12-02 01:53:34.000000000 +0200
31966 +++ linux-h6300-omap2-2.6.14.3/sound/arm/omap-aic23.h 2005-11-13 02:15:10.000000000 +0200
31968 #include <asm/arch/dma.h>
31969 #include <sound/core.h>
31970 #include <sound/pcm.h>
31971 +#include "omap-alsa-dma.h"
31973 #define DEFAULT_OUTPUT_VOLUME 0x60
31974 #define DEFAULT_INPUT_VOLUME 0x00 /* 0 ==> mute line in */
31976 #define DEFAULT_ANALOG_AUDIO_CONTROL DAC_SELECTED | STE_ENABLED | BYPASS_ON | INSEL_MIC | MICB_20DB
31979 - * Buffer management for alsa and dma
31981 -struct audio_stream {
31982 - char *id; /* identification string */
31983 - int stream_id; /* numeric identification */
31984 - int dma_dev; /* dma number of that device */
31985 - int *lch; /* Chain of channels this stream is linked to */
31986 - char started; /* to store if the chain was started or not */
31987 - int dma_q_head; /* DMA Channel Q Head */
31988 - int dma_q_tail; /* DMA Channel Q Tail */
31989 - char dma_q_count; /* DMA Channel Q Count */
31990 - int active:1; /* we are using this stream for transfer now */
31991 - int period; /* current transfer period */
31992 - int periods; /* current count of periods registerd in the DMA engine */
31993 - spinlock_t dma_lock; /* for locking in DMA operations */
31994 - snd_pcm_substream_t *stream; /* the pcm stream */
31995 - unsigned linked:1; /* dma channels linked */
31996 - int offset; /* store start position of the last period in the alsa buffer */
32000 * Alsa card structure for aic23
32002 struct snd_card_omap_aic23 {
32005 /*********** Function Prototypes *************************/
32007 -void audio_dma_callback(void *);
32008 int snd_omap_mixer(struct snd_card_omap_aic23 *);
32009 void snd_omap_init_mixer(void);
32010 /* Clock functions */
32011 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
32012 --- linux-2.6.14-omap2/sound/arm/omap-alsa-dma.c 2005-12-02 01:53:34.000000000 +0200
32013 +++ linux-h6300-omap2-2.6.14.3/sound/arm/omap-alsa-dma.c 2005-11-13 02:15:10.000000000 +0200
32014 @@ -440,6 +440,134 @@
32018 +int audio_dma_request(struct audio_stream *s,
32019 + void (*callback) (void *))
32023 + err = omap_request_sound_dma(s->dma_dev, s->id, s, &s->lch);
32025 + printk(KERN_ERR "unable to grab audio dma 0x%x\n",
32030 +int audio_dma_free(struct audio_stream *s)
32034 + err = omap_free_sound_dma(s, &s->lch);
32036 + printk(KERN_ERR "Unable to free audio dma channels!\n");
32041 + * This function should calculate the current position of the dma in the
32042 + * buffer. It will help alsa middle layer to continue update the buffer.
32043 + * Its correctness is crucial for good functioning.
32045 +u_int audio_get_dma_pos(struct audio_stream *s)
32047 + snd_pcm_substream_t *substream = s->stream;
32048 + snd_pcm_runtime_t *runtime = substream->runtime;
32049 + unsigned int offset;
32050 + unsigned long flags;
32051 + dma_addr_t count;
32053 + /* this must be called w/ interrupts locked as requested in dma.c */
32054 + spin_lock_irqsave(&s->dma_lock, flags);
32056 + /* For the current period let's see where we are */
32057 + count = omap_get_dma_src_addr_counter(s->lch[s->dma_q_head]);
32059 + spin_unlock_irqrestore(&s->dma_lock, flags);
32061 + /* Now, the position related to the end of that period */
32062 + offset = bytes_to_frames(runtime, s->offset) - bytes_to_frames(runtime, count);
32064 + if (offset >= runtime->buffer_size || offset < 0)
32071 + * this stops the dma and clears the dma ptrs
32073 +void audio_stop_dma(struct audio_stream *s)
32075 + unsigned long flags;
32077 + spin_lock_irqsave(&s->dma_lock, flags);
32082 + /* this stops the dma channel and clears the buffer ptrs */
32083 + omap_audio_stop_dma(s);
32085 + omap_clear_sound_dma(s);
32087 + spin_unlock_irqrestore(&s->dma_lock, flags);
32091 + * Main dma routine, requests dma according where you are in main alsa buffer
32093 +void audio_process_dma(struct audio_stream *s)
32095 + snd_pcm_substream_t *substream = s->stream;
32096 + snd_pcm_runtime_t *runtime;
32097 + unsigned int dma_size;
32098 + unsigned int offset;
32101 + runtime = substream->runtime;
32103 + dma_size = frames_to_bytes(runtime, runtime->period_size);
32104 + offset = dma_size * s->period;
32105 + snd_assert(dma_size <= DMA_BUF_SIZE,);
32107 + omap_start_sound_dma(s,
32108 + (dma_addr_t) runtime->dma_area +
32109 + offset, dma_size);
32112 + "audio_process_dma: cannot queue DMA buffer (%i)\n",
32118 + s->period %= runtime->periods;
32120 + s->offset = offset;
32125 + * This is called when dma IRQ occurs at the end of each transmited block
32127 +void audio_dma_callback(void *data)
32129 + struct audio_stream *s = data;
32132 + * If we are getting a callback for an active stream then we inform
32133 + * the PCM middle layer we've finished a period
32136 + snd_pcm_period_elapsed(s->stream);
32138 + spin_lock(&s->dma_lock);
32139 + if (s->periods > 0) {
32142 + audio_process_dma(s);
32143 + spin_unlock(&s->dma_lock);
32146 MODULE_AUTHOR("Texas Instruments");
32148 ("Common DMA handling for Audio driver on OMAP processors");
32149 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
32150 --- linux-2.6.14-omap2/sound/arm/omap-alsa-dma.h 2005-12-02 01:53:34.000000000 +0200
32151 +++ linux-h6300-omap2-2.6.14.3/sound/arm/omap-alsa-dma.h 2005-11-13 02:15:10.000000000 +0200
32154 /************************** INCLUDES *************************************/
32156 -#include "omap-aic23.h"
32157 +/* h6300 tsc2101 changes start */
32158 +//#include "omap-aic23.h"
32159 +#include <sound/driver.h>
32160 +#include <asm/arch/dma.h>
32161 +#include <sound/core.h>
32162 +#include <sound/pcm.h>
32163 +/* h6300 tsc2101 changes end */
32165 /************************** GLOBAL MACROS *************************************/
32168 #define DMA_FREE(s) omap_free_sound_dma(s, &s->lch)
32169 #define DMA_CLEAR(s) omap_clear_sound_dma(s)
32171 +/* h6300 tsc2101 changes start */
32172 +#define DMA_BUF_SIZE 1024 * 8
32174 /************************** GLOBAL DATA STRUCTURES *********************************/
32177 + * Buffer management for alsa and dma
32179 +struct audio_stream {
32180 + char *id; /* identification string */
32181 + int stream_id; /* numeric identification */
32182 + int dma_dev; /* dma number of that device */
32183 + int *lch; /* Chain of channels this stream is linked to */
32184 + char started; /* to store if the chain was started or not */
32185 + int dma_q_head; /* DMA Channel Q Head */
32186 + int dma_q_tail; /* DMA Channel Q Tail */
32187 + char dma_q_count; /* DMA Channel Q Count */
32188 + int active:1; /* we are using this stream for transfer now */
32189 + int period; /* current transfer period */
32190 + int periods; /* current count of periods registerd in the DMA engine */
32191 + spinlock_t dma_lock; /* for locking in DMA operations */
32192 + snd_pcm_substream_t *stream; /* the pcm stream */
32193 + unsigned linked:1; /* dma channels linked */
32194 + int offset; /* store start position of the last period in the alsa buffer */
32196 +/* h6300 tsc2101 changes end */
32198 typedef void (*dma_callback_t) (int lch, u16 ch_status, void *data);
32200 /**************** ARCH SPECIFIC FUNCIONS *******************************************/
32202 int omap_start_sound_dma(struct audio_stream *s, dma_addr_t dma_ptr,
32205 +/* h6300 tsc2101 changes start */
32206 void omap_audio_stop_dma(struct audio_stream *s);
32207 +void audio_dma_callback(void *);
32208 +void audio_process_dma(struct audio_stream *s);
32209 +u_int audio_get_dma_pos(struct audio_stream *s);
32210 +int audio_dma_request(struct audio_stream *s, void (*callback) (void *));
32211 +int audio_dma_free(struct audio_stream *s);
32212 +void audio_stop_dma(struct audio_stream *s);
32213 +/* h6300 tsc2101 changes end */
32216 diff -Naur linux-2.6.14-omap2/sound/arm/omap-tsc2101.c linux-h6300-omap2-2.6.14.3/sound/arm/omap-tsc2101.c
32217 --- linux-2.6.14-omap2/sound/arm/omap-tsc2101.c 1970-01-01 02:00:00.000000000 +0200
32218 +++ linux-h6300-omap2-2.6.14.3/sound/arm/omap-tsc2101.c 2005-11-13 02:15:10.000000000 +0200
32220 +#include <linux/config.h>
32221 +#include <sound/driver.h>
32222 +#include <linux/module.h>
32223 +#include <linux/device.h>
32224 +#include <linux/moduleparam.h>
32225 +#include <linux/init.h>
32226 +#include <linux/errno.h>
32227 +#include <linux/ioctl.h>
32228 +#include <linux/delay.h>
32229 +#include <linux/slab.h>
32232 +#include <linux/pm.h>
32235 +#include <asm/hardware.h>
32236 +#include <asm/mach-types.h>
32237 +#include <asm/arch/dma.h>
32238 +#include <asm/hardware/tsc2101.h>
32239 +#include <../drivers/ssi/omap-tsc2101.h>
32240 +#include <asm/arch/mcbsp.h>
32242 +#include <sound/core.h>
32243 +#include <sound/pcm.h>
32244 +#include <sound/initval.h>
32245 +#include <sound/memalloc.h>
32247 +#include "omap-alsa-dma.h"
32248 +#include "omap-tsc2101.h"
32254 +#define ADEBUG() printk("XXX Alsa debug f:%s, l:%d\n", __FUNCTION__, __LINE__)
32256 +#define ADEBUG() /* nop */
32259 +#define TSC2101_MASTER
32261 +#define DEFAULT_BITPERSAMPLE 16
32262 +#define AUDIO_RATE_DEFAULT 44100
32263 +#define AUDIO_MCBSP OMAP_MCBSP1
32264 +#define NUMBER_SAMPLE_RATES_SUPPORTED 16
32265 +#define PAGE2_AUDIO_CODEC_REGISTERS (2)
32267 +MODULE_AUTHOR("Everett Coleman, Daniel Petrini, David Cohen, Anderson Briglia - INdT");
32268 +MODULE_LICENSE("GPL");
32269 +MODULE_DESCRIPTION("OMAP TSC2101 driver for ALSA");
32270 +MODULE_SUPPORTED_DEVICE("{{TSC2101,OMAP TSC2101}}");
32271 +MODULE_ALIAS("omap_mcbsp.1");
32273 +static char *id = NULL;
32274 +MODULE_PARM_DESC(id, "OMAP ALSA Driver for TSC2101 chip.");
32276 +static struct snd_card_omap_tsc2101 *omap_tsc2101 = NULL;
32278 +static struct omap_mcbsp_reg_cfg initial_config_mcbsp = {
32279 +#ifdef CONFIG_MACH_H6300
32290 + .spcr2 = FREE | FRST | GRST | XRST | XINTM(3),
32291 + .spcr1 = RINTM(3) | RRST,
32292 + .rcr2 = RPHASE | RFRLEN2(OMAP_MCBSP_WORD_8) |
32293 + RWDLEN2(OMAP_MCBSP_WORD_16) | RDATDLY(1),
32294 + .rcr1 = RFRLEN1(OMAP_MCBSP_WORD_8) | RWDLEN1(OMAP_MCBSP_WORD_16),
32295 + .xcr2 = XPHASE | XFRLEN2(OMAP_MCBSP_WORD_8) |
32296 + XWDLEN2(OMAP_MCBSP_WORD_16) | XDATDLY(1) | XFIG,
32297 + .xcr1 = XFRLEN1(OMAP_MCBSP_WORD_8) | XWDLEN1(OMAP_MCBSP_WORD_16),
32298 + .srgr1 = FWID(15),
32299 + .srgr2 = GSYNC | CLKSP | FSGM | FPER(31),
32301 + /* platform specific initialization */
32302 +# if defined(CONFIG_MACH_OMAP_H2)
32303 + .pcr0 = CLKXM | CLKRM | FSXP | FSRP | CLKXP | CLKRP,
32304 +# elif defined(CONFIG_MACH_OMAP_H3)
32306 +# ifndef TSC2101_MASTER
32307 + .pcr0 = FSXM | FSRM | CLKXM | CLKRM | CLKXP | CLKRP,
32309 + .pcr0 = CLKRM | SCLKME | FSXP | FSRP | CLKXP | CLKRP,
32310 +# endif /* !TSC2101_MASTER */
32311 +# endif /* CONFIG_MACH_OMAP_H2 */
32312 +#endif /* CONFIG_MACH_H6300 */
32315 +static unsigned int rates[] = {
32316 + 7350, 8000, 8018, 8727,
32317 + 8820, 9600, 11025, 12000,
32318 + 14700, 16000, 22050, 24000,
32319 + 29400, 32000, 44100, 48000
32322 +static snd_pcm_hw_constraint_list_t hw_constraints_rates = {
32323 + .count = ARRAY_SIZE(rates),
32328 +struct sample_rate_reg_info {
32334 +static const struct sample_rate_reg_info
32335 +reg_info[NUMBER_SAMPLE_RATES_SUPPORTED] = {
32336 + {48000, 0, 0}, {44100, 0, 1}, {32000, 1, 0}, {29400, 1, 1},
32337 + {24000, 2, 0}, {22050, 2, 1}, {16000, 3, 0}, {14700, 3, 1},
32338 + {12000, 4, 0}, {11025, 4, 1}, {9600, 5, 0}, {8820, 5, 1},
32339 + {8727, 6, 0}, {8018, 6, 1}, {8000, 7, 0}, {7350, 7, 1}
32342 +static snd_pcm_hardware_t snd_omap_tsc2101_capture = {
32343 + .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
32344 + SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID),
32345 + .formats = (SNDRV_PCM_FMTBIT_S16_LE),
32346 + .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
32347 + SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 |
32348 + SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
32349 + SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
32350 + SNDRV_PCM_RATE_KNOT),
32351 + .rate_min = 7350,
32352 + .rate_max = 48000,
32353 + .channels_min = 2,
32354 + .channels_max = 2,
32355 + .buffer_bytes_max = 128 * 1024,
32356 + .period_bytes_min = 32,
32357 + .period_bytes_max = 8 * 1024,
32358 + .periods_min = 16,
32359 + .periods_max = 255,
32363 +static snd_pcm_hardware_t snd_omap_tsc2101_playback = {
32364 + .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
32365 + SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID),
32366 + .formats = (SNDRV_PCM_FMTBIT_S16_LE),
32367 + .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
32368 + SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 |
32369 + SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
32370 + SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
32371 + SNDRV_PCM_RATE_KNOT),
32372 + .rate_min = 7350,
32373 + .rate_max = 48000,
32374 + .channels_min = 2,
32375 + .channels_max = 2,
32376 + .buffer_bytes_max = 128 * 1024,
32377 + .period_bytes_min = 32,
32378 + .period_bytes_max = 8 * 1024,
32379 + .periods_min = 16,
32380 + .periods_max = 255,
32384 +static __inline__ void
32385 +audio_tsc2101_write (u8 address, u16 data) {
32386 + omap_tsc2101_write (PAGE2_AUDIO_CODEC_REGISTERS, address, data);
32387 +} /* audio_tsc2101_write */
32389 +static __inline__ u16
32390 +audio_tsc2101_read (u8 address) {
32391 + return (omap_tsc2101_read(PAGE2_AUDIO_CODEC_REGISTERS, address));
32392 +} /* audio_tsc2101_read */
32404 +snd_omap_tsc2101_free (snd_card_t * card) {
32405 + struct snd_card_omap_tsc2101 *chip = card->private_data;
32409 + * Turn off codec after it is done.
32410 + * Can't do it immediately, since it may still have
32417 + audio_dma_free (&chip->s[SNDRV_PCM_STREAM_PLAYBACK]);
32418 + audio_dma_free (&chip->s[SNDRV_PCM_STREAM_CAPTURE]);
32419 +} /* snd_omap_tsc2101_free */
32423 +snd_omap_tsc2101_suspend (snd_card_t * card, pm_message_t state) {
32424 + // TODO: function
32426 +} /* snd_omap_tsc2101_suspend */
32429 +snd_omap_tsc2101_resume (snd_card_t * card) {
32430 + // TODO: function
32432 +} /* snd_omap_tsc2101_resume */
32435 +omap_tsc2101_suspend (struct device *dev, pm_message_t state, u32 level) {
32436 + // TODO: function
32438 +} /* omap_tsc2101_suspend */
32441 +omap_tsc2101_resume (struct device *dev, u32 level) {
32442 + // TODO: function
32444 +} /* omap_tsc2101_resume */
32447 +# define snd_omap_tsc2101_suspend NULL
32448 +# define snd_omap_tsc2101_resume NULL
32449 +# define omap_tsc2101_suspend NULL
32450 +# define omap_tsc2101_resume NULL
32451 +#endif /* CONFIG_PM */
32453 +static inline void
32454 +tsc2101_configure (void) {
32455 + audio_tsc2101_write (TSC2101_CODEC_POWER_CTRL, 0x0000);
32457 + /*Mute Analog Sidetone */
32458 + /*Select MIC_INHED input for headset */
32459 + /*Cell Phone In not connected */
32460 + audio_tsc2101_write (TSC2101_MIXER_PGA_CTRL,
32461 + MPC_ASTMU | MPC_ASTG(0x40) | MPC_MICADC);
32463 + /* Set record source */
32464 + // TODO:MIXER tsc2101_update (SET_RECSRC, tsc2101_local.recsrc);
32466 + /* ADC, DAC, Analog Sidetone, cellphone, buzzer softstepping enabled */
32467 + /* 1dB AGC hysteresis */
32468 + /* MICes bias 2V */
32469 + audio_tsc2101_write (TSC2101_AUDIO_CTRL_4, AC4_MB_HED(0));
32471 + /* Set codec output volume */
32472 + audio_tsc2101_write (TSC2101_DAC_GAIN_CTRL, 0x0000);
32474 + /* DAC left and right routed to SPK2 */
32475 + /* SPK1/2 unmuted */
32476 + audio_tsc2101_write (TSC2101_AUDIO_CTRL_5,
32477 + AC5_DAC2SPK1(3) | AC5_AST2SPK1 | AC5_KCL2SPK1 |
32478 + AC5_DAC2SPK2(3) | AC5_AST2SPK2 | AC5_KCL2SPK2 |
32481 + /* OUT8P/N muted, CPOUT muted */
32483 + audio_tsc2101_write (TSC2101_AUDIO_CTRL_6,
32484 + AC6_MUTLSPK | AC6_MUTSPK2 | AC6_LDSCPTC |
32487 + /* Headset/Hook switch detect disabled */
32488 + audio_tsc2101_write (TSC2101_AUDIO_CTRL_7, 0x0000);
32490 + /* Left line input volume control */
32491 + // TODO:MIXER tsc2101_update (SET_LINE, tsc2101_local.line);
32493 + /* mic input volume control */
32494 + // TODO:MIXER tsc2101_update(SET_MIC, tsc2101_local.mic);
32496 + /* Left/Right headphone channel volume control */
32497 + /* Zero-cross detect on */
32498 + // TODO:MIXER tsc2101_update (SET_VOLUME, tsc2101_local.volume);
32499 +} /* tsc2101_configure */
32502 +snd_card_omap_tsc2101_open (snd_pcm_substream_t * substream) {
32503 + struct snd_card_omap_tsc2101 *chip = snd_pcm_substream_chip(substream);
32504 + snd_pcm_runtime_t *runtime = substream->runtime;
32505 + int stream_id = substream->pstr->stream;
32509 + chip->s[stream_id].stream = substream;
32511 +// TODO: turn audio on, power on
32513 + if (stream_id == SNDRV_PCM_STREAM_PLAYBACK)
32514 + runtime->hw = snd_omap_tsc2101_playback;
32516 + runtime->hw = snd_omap_tsc2101_capture;
32517 + if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
32519 + if ((err = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates)) < 0)
32522 +} /* snd_card_omap_tsc2101_open */
32525 +snd_card_omap_tsc2101_close (snd_pcm_substream_t *substream) {
32526 + struct snd_card_omap_tsc2101 *chip = snd_pcm_substream_chip(substream);
32529 + // TODO: omap_tsc2101_clock_off();
32530 + chip->s[substream->pstr->stream].stream = NULL;
32532 +} /* snd_card_omap_tsc2101_close */
32535 +snd_omap_tsc2101_hw_params (snd_pcm_substream_t *substream, snd_pcm_hw_params_t *hw_params) {
32536 + return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
32537 +} /* snd_omap_tsc2101_hw_params */
32540 +snd_omap_tsc2101_hw_free (snd_pcm_substream_t *substream) {
32541 + return snd_pcm_lib_free_pages(substream);
32542 +} /* snd_omap_tsc2101_hw_free */
32545 +omap_tsc2101_set_samplerate (struct snd_card_omap_tsc2101 *omap_tsc2101, long rate) {
32550 + if (rate >= 48000)
32552 + else if (rate >= 44100)
32554 + else if (rate >= 32000)
32556 + else if (rate >= 29400)
32558 + else if (rate >= 24000)
32560 + else if (rate >= 22050)
32562 + else if (rate >= 16000)
32564 + else if (rate >= 14700)
32566 + else if (rate >= 12000)
32568 + else if (rate >= 11025)
32570 + else if (rate >= 9600)
32572 + else if (rate >= 8820)
32574 + else if (rate >= 8727)
32576 + else if (rate >= 8018)
32578 + else if (rate >= 8000)
32583 + /* wait for any frame to complete */
32586 + /* Search for the right sample rate */
32587 + while ((reg_info[count].sample_rate != rate) &&
32588 + (count < NUMBER_SAMPLE_RATES_SUPPORTED)) {
32591 + if (count == NUMBER_SAMPLE_RATES_SUPPORTED) {
32592 + printk(KERN_ERR "Invalid Sample Rate %d requested\n",
32598 + data = audio_tsc2101_read(TSC2101_AUDIO_CTRL_1);
32599 + /*Clear prev settings */
32600 + data &= ~(AC1_DACFS(0x07) | AC1_ADCFS(0x07));
32602 + AC1_DACFS(reg_info[count].divisor) | AC1_ADCFS(reg_info[count].
32604 + audio_tsc2101_write(TSC2101_AUDIO_CTRL_1, data);
32606 + /* Set the AC3 */
32607 + data = audio_tsc2101_read(TSC2101_AUDIO_CTRL_3);
32608 + /*Clear prev settings */
32609 + data &= ~(AC3_REFFS | AC3_SLVMS);
32610 + data |= (reg_info[count].fs_44kHz) ? AC3_REFFS : 0;
32611 +#ifdef TSC2101_MASTER
32612 + data |= AC3_SLVMS;
32613 +#endif /* #ifdef TSC2101_MASTER */
32614 + audio_tsc2101_write(TSC2101_AUDIO_CTRL_3, data);
32616 + /* program the PLLs */
32617 + if (reg_info[count].fs_44kHz) {
32618 + /* 44.1 khz - 12 MHz Mclk */
32619 + audio_tsc2101_write(TSC2101_PLL_PROG_1, PLL1_PLLSEL | PLL1_PVAL(1) | PLL1_I_VAL(7)); /* PVAL 1; I_VAL 7 */
32620 + audio_tsc2101_write(TSC2101_PLL_PROG_2, PLL2_D_VAL(0x1490)); /* D_VAL 5264 */
32622 + /* 48 khz - 12 Mhz Mclk */
32623 + audio_tsc2101_write(TSC2101_PLL_PROG_1, PLL1_PLLSEL | PLL1_PVAL(1) | PLL1_I_VAL(8)); /* PVAL 1; I_VAL 8 */
32624 + audio_tsc2101_write(TSC2101_PLL_PROG_2, PLL2_D_VAL(0x780)); /* D_VAL 1920 */
32627 + omap_tsc2101->samplerate = rate;
32629 + /* Set the sample rate */
32630 +#ifndef TSC2101_MASTER
32632 + DEFAULT_MCBSP_CLOCK / (rate *
32633 + (DEFAULT_BITPERSAMPLE * 2 - 1));
32635 + initial_config_mcbsp.srgr1 =
32636 + (FWID(DEFAULT_BITPERSAMPLE - 1) | CLKGDV(clkgdv));
32640 + /* Stereo Mode */
32641 + initial_config_mcbsp.srgr2 =
32642 + (CLKSM | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1));
32644 + initial_config_mcbsp.srgr1 =
32645 + (FWID(DEFAULT_BITPERSAMPLE - 1) | CLKGDV(clkgdv));
32646 + initial_config_mcbsp.srgr2 =
32647 + ((GSYNC | CLKSP | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1)));
32649 +#endif /* end of #ifdef TSC2101_MASTER */
32650 + omap_mcbsp_config(AUDIO_MCBSP, &initial_config_mcbsp);
32652 +} /* omap_tsc2101_set_samplerate */
32655 +snd_omap_tsc2101_prepare (snd_pcm_substream_t *substream) {
32656 + struct snd_card_omap_tsc2101 *chip = snd_pcm_substream_chip(substream);
32657 + snd_pcm_runtime_t *runtime = substream->runtime;
32658 + struct audio_stream *s = &chip->s[substream->pstr->stream];
32660 + /* set requested samplerate */
32661 + omap_tsc2101_set_samplerate (chip, runtime->rate);
32666 +} /* snd_omap_tsc2101_prepare */
32669 +snd_omap_tsc2101_trigger (snd_pcm_substream_t *substream, int cmd) {
32670 + struct snd_card_omap_tsc2101 *chip = snd_pcm_substream_chip(substream);
32671 + int stream_id = substream->pstr->stream;
32672 + struct audio_stream *s = &chip->s[stream_id];
32676 + /* note local interrupts are already disabled in the midlevel code */
32677 + spin_lock(&s->dma_lock);
32679 + case SNDRV_PCM_TRIGGER_START:
32680 + /* requested stream startup */
32682 + audio_process_dma(s);
32684 + case SNDRV_PCM_TRIGGER_STOP:
32685 + /* requested stream shutdown */
32686 + audio_stop_dma(s);
32692 + spin_unlock(&s->dma_lock);
32694 +} /* snd_omap_tsc2101_trigger */
32696 +static snd_pcm_uframes_t
32697 +snd_omap_tsc2101_pointer (snd_pcm_substream_t *substream) {
32698 + struct snd_card_omap_tsc2101 *chip = snd_pcm_substream_chip(substream);
32699 + return audio_get_dma_pos(&chip->s[substream->pstr->stream]);
32700 +} /* snd_omap_tsc2101_pointer */
32702 +static snd_pcm_ops_t snd_card_omap_tsc2101_playback_ops = {
32703 + .open = snd_card_omap_tsc2101_open,
32704 + .close = snd_card_omap_tsc2101_close,
32705 + .ioctl = snd_pcm_lib_ioctl,
32706 + .hw_params = snd_omap_tsc2101_hw_params,
32707 + .hw_free = snd_omap_tsc2101_hw_free,
32708 + .prepare = snd_omap_tsc2101_prepare,
32709 + .trigger = snd_omap_tsc2101_trigger,
32710 + .pointer = snd_omap_tsc2101_pointer,
32713 +static snd_pcm_ops_t snd_card_omap_tsc2101_capture_ops = {
32714 + .open = snd_card_omap_tsc2101_open,
32715 + .close = snd_card_omap_tsc2101_close,
32716 + .ioctl = snd_pcm_lib_ioctl,
32717 + .hw_params = snd_omap_tsc2101_hw_params,
32718 + .hw_free = snd_omap_tsc2101_hw_free,
32719 + .prepare = snd_omap_tsc2101_prepare,
32720 + .trigger = snd_omap_tsc2101_trigger,
32721 + .pointer = snd_omap_tsc2101_pointer,
32725 +omap_tsc2101_audio_init (struct snd_card_omap_tsc2101 *omap_tsc2101) {
32726 + /* Setup DMA stuff */
32727 + omap_tsc2101->s[SNDRV_PCM_STREAM_PLAYBACK].id = "Alsa TSC2101 out";
32728 + omap_tsc2101->s[SNDRV_PCM_STREAM_PLAYBACK].stream_id =
32729 + SNDRV_PCM_STREAM_PLAYBACK;
32730 + omap_tsc2101->s[SNDRV_PCM_STREAM_PLAYBACK].dma_dev =
32731 + OMAP_DMA_MCBSP1_TX;
32733 + omap_tsc2101->s[SNDRV_PCM_STREAM_CAPTURE].id = "Alsa TSC2101 in";
32734 + omap_tsc2101->s[SNDRV_PCM_STREAM_CAPTURE].stream_id =
32735 + SNDRV_PCM_STREAM_CAPTURE;
32736 + omap_tsc2101->s[SNDRV_PCM_STREAM_CAPTURE].dma_dev =
32737 + OMAP_DMA_MCBSP1_RX;
32739 + /* configuring the McBSP */
32740 + omap_mcbsp_request (AUDIO_MCBSP);
32742 + /* if configured, then stop mcbsp */
32743 + omap_mcbsp_stop (AUDIO_MCBSP);
32745 + omap_mcbsp_config (AUDIO_MCBSP, &initial_config_mcbsp);
32746 + omap_mcbsp_start (AUDIO_MCBSP);
32748 + tsc2101_configure ();
32749 +} /* omap_tsc2101_audio_init */
32752 +snd_card_omap_tsc2101_pcm (struct snd_card_omap_tsc2101 *omap_tsc2101, int device) {
32757 + if ((err = snd_pcm_new (omap_tsc2101->card, "TSC2101 PCM", device, 1, 1, &pcm)) < 0)
32760 + snd_pcm_lib_preallocate_pages_for_all (pcm,
32761 + SNDRV_DMA_TYPE_CONTINUOUS,
32762 + snd_dma_continuous_data (GFP_KERNEL),
32763 + 128 * 1024, 128 * 1024);
32765 + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
32766 + &snd_card_omap_tsc2101_playback_ops);
32767 + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
32768 + &snd_card_omap_tsc2101_capture_ops);
32770 + pcm->private_data = omap_tsc2101;
32771 + pcm->info_flags = 0;
32772 + strcpy (pcm->name, "omap tsc2101 pcm");
32774 + omap_tsc2101_audio_init (omap_tsc2101);
32776 + audio_dma_request(&omap_tsc2101->s[SNDRV_PCM_STREAM_PLAYBACK],
32777 + audio_dma_callback);
32778 + audio_dma_request(&omap_tsc2101->s[SNDRV_PCM_STREAM_CAPTURE],
32779 + audio_dma_callback);
32781 + omap_tsc2101->pcm = pcm;
32783 +} /* snd_card_omap_tsc2101_pcm */
32786 +snd_omap_tsc2101_probe (struct device *dev) {
32788 + snd_card_t *card;
32791 + if ((card = snd_card_new (-1, id, THIS_MODULE, sizeof (omap_tsc2101))) == NULL)
32793 + if ((omap_tsc2101 = kcalloc (1, sizeof (*omap_tsc2101), GFP_KERNEL)) == NULL)
32796 + card->private_data = (void *)omap_tsc2101;
32797 + card->private_free = snd_omap_tsc2101_free;
32798 + omap_tsc2101->card = card;
32799 + omap_tsc2101->samplerate = AUDIO_RATE_DEFAULT;
32801 + spin_lock_init(&omap_tsc2101->s[0].dma_lock);
32802 + spin_lock_init(&omap_tsc2101->s[1].dma_lock);
32804 + // TODO: setup mixer (fail, goto nodev)
32806 + if ((err = snd_card_omap_tsc2101_pcm (omap_tsc2101, 0)) < 0)
32809 + snd_card_set_pm_callback (card, snd_omap_tsc2101_suspend, snd_omap_tsc2101_resume, omap_tsc2101);
32811 + strcpy (card->driver, "TSC2101");
32812 + strcpy (card->shortname, "TI TSC2101");
32813 + strcpy (card->longname, "TI OMAP TSC2101");
32815 + // TODO: init mixer
32817 + if ((err = snd_card_register (card)) == 0) {
32818 + printk(KERN_INFO "TSC2101 audio support initialized\n");
32819 + dev_set_drvdata(dev, card);
32824 + printk (KERN_ERR "failed to initialize TSC2101\n");
32825 + snd_omap_tsc2101_free (card);
32827 +} /* snd_omap_tsc2101_probe */
32830 +snd_omap_tsc2101_remove (struct device *dev) {
32831 + snd_card_t *card = dev_get_drvdata(dev);
32832 + struct snd_card_omap_tsc2101 *chip = card->private_data;
32834 + snd_card_free(card);
32835 + omap_tsc2101 = NULL;
32836 + card->private_data = NULL;
32838 + dev_set_drvdata (dev, NULL);
32840 +} /* snd_omap_tsc2101_remove */
32842 +static struct device_driver omap_alsa_driver = {
32843 + .name = "omap_mcbsp",
32844 + .bus = &platform_bus_type,
32845 + .probe = snd_omap_tsc2101_probe,
32846 + .remove = snd_omap_tsc2101_remove,
32847 + .suspend = omap_tsc2101_suspend,
32848 + .resume = omap_tsc2101_resume,
32852 +omap_alsa_device_release (struct device *dev) {
32856 +static struct platform_device omap_alsa_device = {
32857 + .name = "omap_mcbsp",
32860 + .release = omap_alsa_device_release,
32865 +omap_tsc2101_init (void) {
32869 + if ((err = platform_device_register (&omap_alsa_device)) != 0)
32871 + if ((err = driver_register (&omap_alsa_driver)) != 0)
32872 + platform_device_unregister (&omap_alsa_device);
32874 +} /* omap_tsc2101_init */
32876 +static void __exit
32877 +omap_tsc2101_exit (void) {
32879 + driver_unregister (&omap_alsa_driver);
32880 + platform_device_unregister (&omap_alsa_device);
32881 +} /* omap_tsc2101_exit */
32883 +module_init (omap_tsc2101_init);
32884 +module_exit (omap_tsc2101_exit);
32885 diff -Naur linux-2.6.14-omap2/sound/arm/omap-tsc2101.h linux-h6300-omap2-2.6.14.3/sound/arm/omap-tsc2101.h
32886 --- linux-2.6.14-omap2/sound/arm/omap-tsc2101.h 1970-01-01 02:00:00.000000000 +0200
32887 +++ linux-h6300-omap2-2.6.14.3/sound/arm/omap-tsc2101.h 2005-11-13 02:15:10.000000000 +0200
32889 +#ifndef __OMAP_AUDIO_TSC2101_H
32890 +#define __OMAP_AUDIO_TSC2101_H
32892 +# include "omap-alsa-dma.h"
32894 +struct snd_card_omap_tsc2101 {
32895 + snd_card_t *card;
32898 + struct audio_stream s[2]; /* playback & capture */
32901 +#endif /* __OMAP_AUDIO_TSC2101_H */
32902 diff -Naur linux-2.6.14-omap2/sound/oss/Kconfig linux-h6300-omap2-2.6.14.3/sound/oss/Kconfig
32903 --- linux-2.6.14-omap2/sound/oss/Kconfig 2005-12-02 01:53:34.000000000 +0200
32904 +++ linux-h6300-omap2-2.6.14.3/sound/oss/Kconfig 2005-10-22 03:52:45.000000000 +0300
32907 config SOUND_OMAP_TSC2101
32908 tristate "TSC2101 Stereo Codec"
32909 - depends on SOUND_OMAP && ( MACH_OMAP_H2 || MACH_OMAP_H3 )
32910 + depends on SOUND_OMAP && ( MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_H6300)
32911 select OMAP_TSC2101
32912 select OMAP_UWIRE if ARCH_OMAP
32914 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
32915 --- linux-2.6.14-omap2/sound/oss/omap-audio-tsc2101.c 2005-12-02 01:53:34.000000000 +0200
32916 +++ linux-h6300-omap2-2.6.14.3/sound/oss/omap-audio-tsc2101.c 2005-10-22 03:52:45.000000000 +0300
32918 #include "omap-audio.h"
32919 #include "omap-audio-dma-intfc.h"
32920 #include <asm/arch/mcbsp.h>
32921 -#if CONFIG_ARCH_OMAP16XX
32922 +#if defined (CONFIG_ARCH_OMAP16XX) || defined (CONFIG_MACH_OMAP_H6300)
32923 #include <../drivers/ssi/omap-uwire.h>
32924 #include <asm/arch/dsp_common.h>
32928 #if CONFIG_ARCH_OMAP16XX
32929 #define PLATFORM_NAME "OMAP16XX"
32930 +#elif CONFIG_MACH_OMAP_H6300
32931 +#define PLATFORM_NAME "OMAP15XX"
32934 #if CONFIG_ARCH_OMAP16XX
32936 #define LEAVE_CS 0x80
32938 /* Select the McBSP For Audio */
32939 -#if CONFIG_ARCH_OMAP16XX
32940 +#if defined (CONFIG_ARCH_OMAP16XX) || defined(CONFIG_MACH_OMAP_H6300)
32941 #define AUDIO_MCBSP OMAP_MCBSP1
32943 #error "UnSupported Configuration"
32944 @@ -124,7 +126,7 @@
32945 /*********** Debug Macros ********/
32946 /* To Generate a rather shrill tone -test the entire path */
32948 -/* To Generate a tone for each keyclick - test the tsc,spi paths*/
32949 +///* To Generate a tone for each keyclick - test the tsc,spi paths*/
32950 //#define TEST_KEYCLICK
32951 /* To dump the tsc registers for debug */
32952 //#define TSC_DUMP_REGISTERS
32953 @@ -215,6 +217,17 @@
32956 static struct omap_mcbsp_reg_cfg initial_config = {
32957 +#ifdef CONFIG_MACH_OMAP_H6300
32968 .spcr2 = FREE | FRST | GRST | XRST | XINTM(3),
32969 .spcr1 = RINTM(3) | RRST,
32970 .rcr2 = RPHASE | RFRLEN2(OMAP_MCBSP_WORD_8) |
32971 @@ -238,6 +251,7 @@
32972 #endif /* tsc Master defs */
32974 #endif /* platform specific inits */
32975 +#endif /* CONFIG_MACH_OMAP_H6300 */
32978 /***************************** MODULES SPECIFIC FUNCTION PROTOTYPES ********************/